Merge "Add EnableCellularModem Api to reinitiallise QESDK" into udc-dev am: e7d9a12327 am: f48d917192

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/22339602

Change-Id: I6701c0b75addfd83545b0ef77ee2ef66f3c6fc04
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/Android.bp b/Android.bp
index cff863b..9cd43fa 100644
--- a/Android.bp
+++ b/Android.bp
@@ -224,6 +224,7 @@
         "android.hardware.radio.messaging-V2-java",
         "android.hardware.radio.modem-V2-java",
         "android.hardware.radio.network-V2-java",
+        "android.hardware.radio.satellite-V1-java",
         "android.hardware.radio.sim-V2-java",
         "android.hardware.radio.voice-V2-java",
         "android.hardware.thermal-V1.0-java-constants",
@@ -503,6 +504,13 @@
 }
 
 filegroup {
+    name: "framework-android-os-unit-testable-src",
+    srcs: [
+        "core/java/android/os/DdmSyncState.java",
+    ],
+}
+
+filegroup {
     name: "framework-networkstack-shared-srcs",
     srcs: [
         // TODO: remove these annotations as soon as we can use andoid.support.annotations.*
diff --git a/apct-tests/perftests/core/src/android/input/VelocityTrackerBenchmarkTest.kt b/apct-tests/perftests/core/src/android/input/VelocityTrackerBenchmarkTest.kt
new file mode 100644
index 0000000..530ca7b
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/input/VelocityTrackerBenchmarkTest.kt
@@ -0,0 +1,258 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.input
+
+import android.perftests.utils.PerfStatusReporter
+import android.view.InputDevice
+import android.view.MotionEvent
+import android.view.VelocityTracker
+
+import androidx.test.filters.LargeTest
+import androidx.test.runner.AndroidJUnit4
+
+import java.time.Duration
+
+import org.junit.Assert
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+/**
+ * Helper class to maintain [MotionEvent]s for tests.
+ *
+ * This is primarily used to create [MotionEvent]s for tests, in a way where a sequence of
+ * [MotionEvent]s created in multiple test runs are exactly the same, as long as [reset] is called
+ * between consecutive sequences of [MotionEvent]s.
+ *
+ * Furthermore, it also contains convenience methods to run any queries/verifications of the
+ * generated [MotionEvent]s.
+ */
+abstract class MotionState {
+    /** Current time, in ms. */
+    protected var currentTime = START_TIME
+
+    /** Resets the state of this instance. */
+    open fun reset() {
+        currentTime = START_TIME
+    }
+
+    /** Creates a [MotionEvent]. */
+    abstract fun createMotionEvent(): MotionEvent
+
+    /** Asserts that the current velocity is not zero, just for verifying there's motion. */
+    abstract fun assertNonZeroVelocity(velocityTracker: VelocityTracker)
+
+    companion object {
+        /** Arbitrarily chosen start time. */
+        val START_TIME = Duration.ofMillis(100)
+        /**
+         * A small enough time jump, which won't be considered by the tracker as big enough to
+         * deduce that a pointer has stopped.
+         */
+        val DEFAULT_TIME_JUMP = Duration.ofMillis(2)
+    }
+}
+
+/** An implementation of [MotionState] for [MotionEvent.AXIS_SCROLL]. */
+private class ScrollMotionState : MotionState() {
+    override fun createMotionEvent(): MotionEvent {
+        val props = MotionEvent.PointerProperties()
+        props.id = 0
+        val coords = MotionEvent.PointerCoords()
+        coords.setAxisValue(MotionEvent.AXIS_SCROLL, DEFAULT_SCROLL_AMOUNT)
+        val motionEvent = MotionEvent.obtain(
+            /*downTime=*/0,
+            currentTime.toMillis(),
+            MotionEvent.ACTION_SCROLL,
+            /*pointerCount=*/1,
+            arrayOf(props),
+            arrayOf(coords),
+            /*metaState=*/0,
+            /*buttonState=*/0,
+            /*xPrecision=*/0f,
+            /*yPrecision=*/0f,
+            /*deviceId=*/1,
+            /*edgeFlags=*/0,
+            InputDevice.SOURCE_ROTARY_ENCODER,
+            /*flags=*/0
+        )
+
+        currentTime = currentTime.plus(DEFAULT_TIME_JUMP)
+
+        return motionEvent
+    }
+
+    override fun assertNonZeroVelocity(velocityTracker: VelocityTracker) {
+        Assert.assertTrue(velocityTracker.getAxisVelocity(MotionEvent.AXIS_SCROLL) != 0f)
+    }
+
+    companion object {
+        private val DEFAULT_SCROLL_AMOUNT: Float = 30f
+    }
+}
+
+/** An implementation of [MotionState] for [MotionEvent.AXIS_X] and [MotionEvent.AXIS_Y]. */
+private class PlanarMotionState : MotionState() {
+    private var x: Float = DEFAULT_X
+    private var y: Float = DEFAULT_Y
+    private var downEventCreated = false
+
+    override fun createMotionEvent(): MotionEvent {
+        val action: Int = if (downEventCreated) MotionEvent.ACTION_MOVE else MotionEvent.ACTION_DOWN
+        val motionEvent = MotionEvent.obtain(
+            /*downTime=*/START_TIME.toMillis(),
+            currentTime.toMillis(),
+            action,
+            x,
+            y,
+            /*metaState=*/0)
+
+        if (downEventCreated) {
+            x += INCREMENT
+            y += INCREMENT
+        } else {
+            downEventCreated = true
+        }
+        currentTime = currentTime.plus(DEFAULT_TIME_JUMP)
+
+        return motionEvent
+    }
+
+    override fun assertNonZeroVelocity(velocityTracker: VelocityTracker) {
+        Assert.assertTrue(velocityTracker.getAxisVelocity(MotionEvent.AXIS_X) != 0f)
+        Assert.assertTrue(velocityTracker.getAxisVelocity(MotionEvent.AXIS_Y) != 0f)
+    }
+
+    override fun reset() {
+        super.reset()
+        x = DEFAULT_X
+        y = DEFAULT_Y
+        downEventCreated = false
+    }
+
+    companion object {
+        /** Arbitrarily chosen constants. No need to have varying velocity for now. */
+        private val DEFAULT_X: Float = 2f
+        private val DEFAULT_Y: Float = 4f
+        private val INCREMENT: Float = 0.7f
+    }
+}
+
+/**
+ * Benchmark tests for [VelocityTracker]
+ *
+ * Build/Install/Run:
+ * atest VelocityTrackerBenchmarkTest
+ */
+@LargeTest
+@RunWith(AndroidJUnit4::class)
+class VelocityTrackerBenchmarkTest {
+    @get:Rule
+    val perfStatusReporter: PerfStatusReporter = PerfStatusReporter()
+
+    private val velocityTracker = VelocityTracker.obtain()
+    @Before
+    fun setup() {
+        velocityTracker.clear()
+    }
+
+    @Test
+    fun addMovement_axisScroll() {
+        testAddMovement(ScrollMotionState())
+    }
+
+    @Test
+    fun computeCurrentVelocity_computeAfterAllAdditions_axisScroll() {
+        testComputeCurrentVelocity_computeAfterAllAdditions(ScrollMotionState())
+    }
+
+    @Test
+    fun computeCurrentVelocity_computeAfterEachAdd_axisScroll() {
+        testComputeCurrentVelocity_computeAfterEachAdd(ScrollMotionState())
+    }
+
+    @Test
+    fun addMovement_planarAxes() {
+        testAddMovement(PlanarMotionState())
+    }
+
+    @Test
+    fun computeCurrentVelocity_computeAfterAllAdditions_planarAxes() {
+        testComputeCurrentVelocity_computeAfterAllAdditions(PlanarMotionState())
+    }
+
+    private fun testAddMovement(motionState: MotionState) {
+        val state = perfStatusReporter.getBenchmarkState()
+        while (state.keepRunning()) {
+            state.pauseTiming()
+            for (i in 0 until TEST_NUM_DATAPOINTS) {
+                val motionEvent = motionState.createMotionEvent()
+                state.resumeTiming()
+                velocityTracker.addMovement(motionEvent)
+                state.pauseTiming()
+            }
+            velocityTracker.computeCurrentVelocity(1000)
+            motionState.assertNonZeroVelocity(velocityTracker)
+            // Clear the tracker for the next run
+            velocityTracker.clear()
+            motionState.reset()
+            state.resumeTiming()
+        }
+    }
+
+    private fun testComputeCurrentVelocity_computeAfterAllAdditions(motionState: MotionState) {
+        val state = perfStatusReporter.getBenchmarkState()
+        while (state.keepRunning()) {
+            // Add the data points
+            state.pauseTiming()
+            for (i in 0 until TEST_NUM_DATAPOINTS) {
+                velocityTracker.addMovement(motionState.createMotionEvent())
+            }
+
+            // Do the velocity computation
+            state.resumeTiming()
+            velocityTracker.computeCurrentVelocity(1000)
+
+            state.pauseTiming()
+            motionState.assertNonZeroVelocity(velocityTracker)
+            // Clear the tracker for the next run
+            velocityTracker.clear()
+            state.resumeTiming()
+        }
+    }
+
+    private fun testComputeCurrentVelocity_computeAfterEachAdd(motionState: MotionState) {
+        val state = perfStatusReporter.getBenchmarkState()
+        while (state.keepRunning()) {
+            state.pauseTiming()
+            for (i in 0 until TEST_NUM_DATAPOINTS) {
+                velocityTracker.addMovement(motionState.createMotionEvent())
+                state.resumeTiming()
+                velocityTracker.computeCurrentVelocity(1000)
+                state.pauseTiming()
+            }
+            motionState.assertNonZeroVelocity(velocityTracker)
+            // Clear the tracker for the next run
+            velocityTracker.clear()
+            state.resumeTiming()
+        }
+    }
+
+    companion object {
+        private const val TEST_NUM_DATAPOINTS = 100
+    }
+}
\ No newline at end of file
diff --git a/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java b/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java
index 051dde0..5b7bca0 100644
--- a/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java
+++ b/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java
@@ -1554,6 +1554,7 @@
     }
 
     private void waitCoolDownPeriod() {
+        // Heuristic value based on local tests. Stability increased compared to no waiting.
         final int tenSeconds = 1000 * 10;
         waitForBroadcastIdle();
         sleep(tenSeconds);
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index b8d24e3..d79131c 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -193,6 +193,9 @@
                 instrument.alwaysCheckSignature = true;
             } else if (opt.equals("--instrument-sdk-sandbox")) {
                 instrument.instrumentSdkSandbox = true;
+            } else if (opt.equals("--instrument-sdk-in-sandbox")) {
+                instrument.instrumentSdkSandbox = true;
+                instrument.instrumentSdkInSandbox = true;
             } else {
                 System.err.println("Error: Unknown option: " + opt);
                 return;
diff --git a/cmds/am/src/com/android/commands/am/Instrument.java b/cmds/am/src/com/android/commands/am/Instrument.java
index 2604497..e60593e 100644
--- a/cmds/am/src/com/android/commands/am/Instrument.java
+++ b/cmds/am/src/com/android/commands/am/Instrument.java
@@ -20,6 +20,7 @@
 import static android.app.ActivityManager.INSTR_FLAG_DISABLE_HIDDEN_API_CHECKS;
 import static android.app.ActivityManager.INSTR_FLAG_DISABLE_ISOLATED_STORAGE;
 import static android.app.ActivityManager.INSTR_FLAG_DISABLE_TEST_API_CHECKS;
+import static android.app.ActivityManager.INSTR_FLAG_INSTRUMENT_SDK_IN_SANDBOX;
 import static android.app.ActivityManager.INSTR_FLAG_INSTRUMENT_SDK_SANDBOX;
 import static android.app.ActivityManager.INSTR_FLAG_NO_RESTART;
 
@@ -99,6 +100,7 @@
     public String componentNameArg;
     public boolean alwaysCheckSignature = false;
     public boolean instrumentSdkSandbox = false;
+    public boolean instrumentSdkInSandbox = false;
 
     /**
      * Construct the instrument command runner.
@@ -530,6 +532,9 @@
             if (instrumentSdkSandbox) {
                 flags |= INSTR_FLAG_INSTRUMENT_SDK_SANDBOX;
             }
+            if (instrumentSdkInSandbox) {
+                flags |= INSTR_FLAG_INSTRUMENT_SDK_IN_SANDBOX;
+            }
             if (!mAm.startInstrumentation(cn, profileFile, flags, args, watcher, connection, userId,
                         abi)) {
                 throw new AndroidException("INSTRUMENTATION_FAILED: " + cn.flattenToString());
diff --git a/cmds/bootanimation/audioplay.cpp b/cmds/bootanimation/audioplay.cpp
index c5e16c6..9b95b04 100644
--- a/cmds/bootanimation/audioplay.cpp
+++ b/cmds/bootanimation/audioplay.cpp
@@ -20,6 +20,8 @@
 #define CHATTY ALOGD
 #define LOG_TAG "audioplay"
 
+#include <binder/IServiceManager.h>
+
 #include "audioplay.h"
 
 #include <string.h>
@@ -316,8 +318,13 @@
         : Thread(false),
           mExampleAudioData(exampleAudioData),
           mExampleAudioLength(exampleAudioLength) {}
+
 private:
     virtual bool threadLoop() {
+        if (defaultServiceManager()->checkService(String16("audio")) == nullptr) {
+            ALOGW("Audio service is not ready yet, ignore creating playback engine");
+            return false;
+        }
         audioplay::create(mExampleAudioData, mExampleAudioLength);
         // Exit immediately
         return false;
@@ -334,6 +341,11 @@
 public:
     void init(const Vector<Animation::Part>& parts) override {
         const Animation::Part* partWithAudio = nullptr;
+
+        if (!playSoundsAllowed()) {
+            return;
+        }
+
         for (const Animation::Part& part : parts) {
             if (part.audioData != nullptr) {
                 partWithAudio = &part;
@@ -401,14 +413,14 @@
 }
 
 bool playClip(const uint8_t* buf, int size) {
-    // Parse the WAV header
-    const ChunkFormat* chunkFormat;
-    if (!parseClipBuf(buf, size, &chunkFormat, &nextBuffer, &nextSize)) {
+    if (!hasPlayer()) {
+        ALOGE("cannot play clip %p without a player", buf);
         return false;
     }
 
-    if (!hasPlayer()) {
-        ALOGD("cannot play clip %p without a player", buf);
+    // Parse the WAV header
+    const ChunkFormat* chunkFormat;
+    if (!parseClipBuf(buf, size, &chunkFormat, &nextBuffer, &nextSize)) {
         return false;
     }
 
@@ -433,11 +445,9 @@
 void setPlaying(bool isPlaying) {
     if (!hasPlayer()) return;
 
-    SLresult result;
-
     if (nullptr != bqPlayerPlay) {
         // set the player's state
-        result = (*bqPlayerPlay)->SetPlayState(bqPlayerPlay,
+        (*bqPlayerPlay)->SetPlayState(bqPlayerPlay,
             isPlaying ? SL_PLAYSTATE_PLAYING : SL_PLAYSTATE_STOPPED);
     }
 
diff --git a/cmds/locksettings/Android.bp b/cmds/locksettings/Android.bp
index 5ee5824..ee31aed 100644
--- a/cmds/locksettings/Android.bp
+++ b/cmds/locksettings/Android.bp
@@ -21,8 +21,7 @@
     default_applicable_licenses: ["frameworks_base_license"],
 }
 
-java_binary {
+sh_binary {
     name: "locksettings",
-    wrapper: "locksettings.sh",
-    srcs: ["**/*.java"],
+    src: "locksettings.sh",
 }
diff --git a/cmds/locksettings/locksettings.sh b/cmds/locksettings/locksettings.sh
index 0ef4fa9..2f8d868 100755
--- a/cmds/locksettings/locksettings.sh
+++ b/cmds/locksettings/locksettings.sh
@@ -1,6 +1,2 @@
 #!/system/bin/sh
-# Script to start "locksettings" on the device
-#
-base=/system
-export CLASSPATH=$base/framework/locksettings.jar
-exec app_process $base/bin com.android.commands.locksettings.LockSettingsCmd "$@"
+cmd lock_settings "$@"
diff --git a/cmds/locksettings/src/com/android/commands/locksettings/LockSettingsCmd.java b/cmds/locksettings/src/com/android/commands/locksettings/LockSettingsCmd.java
deleted file mode 100644
index 7d9260a..0000000
--- a/cmds/locksettings/src/com/android/commands/locksettings/LockSettingsCmd.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2016 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.commands.locksettings;
-
-import android.os.ResultReceiver;
-import android.os.ServiceManager;
-import android.os.ShellCallback;
-
-import com.android.internal.os.BaseCommand;
-import com.android.internal.widget.ILockSettings;
-
-import java.io.FileDescriptor;
-import java.io.PrintStream;
-
-public final class LockSettingsCmd extends BaseCommand {
-
-    public static void main(String[] args) {
-        (new LockSettingsCmd()).run(args);
-    }
-
-    @Override
-    public void onShowUsage(PrintStream out) {
-        main(new String[] { "help" });
-    }
-
-    @Override
-    public void onRun() throws Exception {
-        ILockSettings lockSettings = ILockSettings.Stub.asInterface(
-                ServiceManager.getService("lock_settings"));
-        lockSettings.asBinder().shellCommand(FileDescriptor.in, FileDescriptor.out,
-                FileDescriptor.err, getRawArgs(), new ShellCallback(), new ResultReceiver(null) {});
-    }
-}
diff --git a/core/api/current.txt b/core/api/current.txt
index 80abd84..7c832b3 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -3662,13 +3662,13 @@
   }
 
   public class Account implements android.os.Parcelable {
-    ctor public Account(String, String);
+    ctor public Account(@NonNull String, @NonNull String);
     ctor public Account(android.os.Parcel);
     method public int describeContents();
     method public void writeToParcel(android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.accounts.Account> CREATOR;
-    field public final String name;
-    field public final String type;
+    field @NonNull public final String name;
+    field @NonNull public final String type;
   }
 
   @Deprecated public class AccountAuthenticatorActivity extends android.app.Activity {
@@ -4505,6 +4505,7 @@
     method @NonNull public final <T extends android.view.View> T requireViewById(@IdRes int);
     method public final void runOnUiThread(Runnable);
     method public void setActionBar(@Nullable android.widget.Toolbar);
+    method public void setAllowCrossUidActivitySwitchFromBelow(boolean);
     method public void setContentTransitionManager(android.transition.TransitionManager);
     method public void setContentView(@LayoutRes int);
     method public void setContentView(android.view.View);
@@ -6658,6 +6659,21 @@
     field protected android.app.Notification.Builder mBuilder;
   }
 
+  public static final class Notification.TvExtender implements android.app.Notification.Extender {
+    ctor public Notification.TvExtender();
+    ctor public Notification.TvExtender(@NonNull android.app.Notification);
+    method @NonNull public android.app.Notification.Builder extend(@NonNull android.app.Notification.Builder);
+    method @Nullable public String getChannelId();
+    method @Nullable public android.app.PendingIntent getContentIntent();
+    method @Nullable public android.app.PendingIntent getDeleteIntent();
+    method public boolean isAvailableOnTv();
+    method public boolean isSuppressShowOverApps();
+    method @NonNull public android.app.Notification.TvExtender setChannelId(@Nullable String);
+    method @NonNull public android.app.Notification.TvExtender setContentIntent(@Nullable android.app.PendingIntent);
+    method @NonNull public android.app.Notification.TvExtender setDeleteIntent(@Nullable android.app.PendingIntent);
+    method @NonNull public android.app.Notification.TvExtender setSuppressShowOverApps(boolean);
+  }
+
   public static final class Notification.WearableExtender implements android.app.Notification.Extender {
     ctor public Notification.WearableExtender();
     ctor public Notification.WearableExtender(android.app.Notification);
@@ -9684,7 +9700,8 @@
     ctor public AttributionSource.Builder(@NonNull android.content.AttributionSource);
     method @NonNull public android.content.AttributionSource build();
     method @NonNull public android.content.AttributionSource.Builder setAttributionTag(@Nullable String);
-    method @NonNull public android.content.AttributionSource.Builder setNext(@Nullable android.content.AttributionSource);
+    method @Deprecated @NonNull public android.content.AttributionSource.Builder setNext(@Nullable android.content.AttributionSource);
+    method @NonNull public android.content.AttributionSource.Builder setNextAttributionSource(@NonNull android.content.AttributionSource);
     method @NonNull public android.content.AttributionSource.Builder setPackageName(@Nullable String);
     method @NonNull public android.content.AttributionSource.Builder setPid(int);
   }
@@ -14238,9 +14255,11 @@
 
   public final class SQLiteDatabase extends android.database.sqlite.SQLiteClosable {
     method public void beginTransaction();
+    method public void beginTransactionDeferred();
     method public void beginTransactionNonExclusive();
-    method public void beginTransactionWithListener(android.database.sqlite.SQLiteTransactionListener);
-    method public void beginTransactionWithListenerNonExclusive(android.database.sqlite.SQLiteTransactionListener);
+    method public void beginTransactionWithListener(@Nullable android.database.sqlite.SQLiteTransactionListener);
+    method public void beginTransactionWithListenerDeferred(@Nullable android.database.sqlite.SQLiteTransactionListener);
+    method public void beginTransactionWithListenerNonExclusive(@Nullable android.database.sqlite.SQLiteTransactionListener);
     method public android.database.sqlite.SQLiteStatement compileStatement(String) throws android.database.SQLException;
     method @NonNull public static android.database.sqlite.SQLiteDatabase create(@Nullable android.database.sqlite.SQLiteDatabase.CursorFactory);
     method @NonNull public static android.database.sqlite.SQLiteDatabase createInMemory(@NonNull android.database.sqlite.SQLiteDatabase.OpenParams);
@@ -24806,7 +24825,6 @@
   }
 
   public class Ringtone {
-    method protected void finalize();
     method public android.media.AudioAttributes getAudioAttributes();
     method @Deprecated public int getStreamType();
     method public String getTitle(android.content.Context);
@@ -32654,6 +32672,7 @@
     field public static final int S_V2 = 32; // 0x20
     field public static final int TIRAMISU = 33; // 0x21
     field public static final int UPSIDE_DOWN_CAKE = 10000; // 0x2710
+    field public static final int VANILLA_ICE_CREAM = 10000; // 0x2710
   }
 
   public final class Bundle extends android.os.BaseBundle implements java.lang.Cloneable android.os.Parcelable {
@@ -37094,6 +37113,7 @@
     field public static final String ACTION_CAST_SETTINGS = "android.settings.CAST_SETTINGS";
     field public static final String ACTION_CHANNEL_NOTIFICATION_SETTINGS = "android.settings.CHANNEL_NOTIFICATION_SETTINGS";
     field public static final String ACTION_CONDITION_PROVIDER_SETTINGS = "android.settings.ACTION_CONDITION_PROVIDER_SETTINGS";
+    field public static final String ACTION_CREDENTIAL_PROVIDER = "android.settings.CREDENTIAL_PROVIDER";
     field public static final String ACTION_DATA_ROAMING_SETTINGS = "android.settings.DATA_ROAMING_SETTINGS";
     field public static final String ACTION_DATA_USAGE_SETTINGS = "android.settings.DATA_USAGE_SETTINGS";
     field public static final String ACTION_DATE_SETTINGS = "android.settings.DATE_SETTINGS";
@@ -49032,7 +49052,7 @@
     method public abstract void captureEndValues(android.transition.TransitionValues);
     method public abstract void captureStartValues(android.transition.TransitionValues);
     method public android.transition.Transition clone();
-    method public android.animation.Animator createAnimator(android.view.ViewGroup, android.transition.TransitionValues, android.transition.TransitionValues);
+    method @Nullable public android.animation.Animator createAnimator(@NonNull android.view.ViewGroup, @Nullable android.transition.TransitionValues, @Nullable android.transition.TransitionValues);
     method public android.transition.Transition excludeChildren(int, boolean);
     method public android.transition.Transition excludeChildren(android.view.View, boolean);
     method public android.transition.Transition excludeChildren(Class, boolean);
@@ -55063,6 +55083,7 @@
 
   public final class AutofillManager {
     method public void cancel();
+    method public void clearAutofillRequestCallback();
     method public void commit();
     method public void disableAutofillServices();
     method @Nullable public android.content.ComponentName getAutofillServiceComponentName();
@@ -55089,6 +55110,7 @@
     method public void registerCallback(@Nullable android.view.autofill.AutofillManager.AutofillCallback);
     method public void requestAutofill(@NonNull android.view.View);
     method public void requestAutofill(@NonNull android.view.View, int, @NonNull android.graphics.Rect);
+    method @RequiresPermission(android.Manifest.permission.PROVIDE_OWN_AUTOFILL_SUGGESTIONS) public void setAutofillRequestCallback(@NonNull java.util.concurrent.Executor, @NonNull android.view.autofill.AutofillRequestCallback);
     method public void setUserData(@Nullable android.service.autofill.UserData);
     method public boolean showAutofillDialog(@NonNull android.view.View);
     method public boolean showAutofillDialog(@NonNull android.view.View, int);
@@ -55109,6 +55131,10 @@
     field public static final int EVENT_INPUT_UNAVAILABLE = 3; // 0x3
   }
 
+  public interface AutofillRequestCallback {
+    method public void onFillRequest(@Nullable android.view.inputmethod.InlineSuggestionsRequest, @NonNull android.os.CancellationSignal, @NonNull android.service.autofill.FillCallback);
+  }
+
   public final class AutofillValue implements android.os.Parcelable {
     method public int describeContents();
     method public static android.view.autofill.AutofillValue forDate(long);
@@ -55558,10 +55584,12 @@
     ctor public InlineSuggestionsRequest.Builder(@NonNull java.util.List<android.widget.inline.InlinePresentationSpec>);
     method @NonNull public android.view.inputmethod.InlineSuggestionsRequest.Builder addInlinePresentationSpecs(@NonNull android.widget.inline.InlinePresentationSpec);
     method @NonNull public android.view.inputmethod.InlineSuggestionsRequest build();
+    method @NonNull public android.view.inputmethod.InlineSuggestionsRequest.Builder setClientSupported(boolean);
     method @NonNull public android.view.inputmethod.InlineSuggestionsRequest.Builder setExtras(@NonNull android.os.Bundle);
     method @NonNull public android.view.inputmethod.InlineSuggestionsRequest.Builder setInlinePresentationSpecs(@NonNull java.util.List<android.widget.inline.InlinePresentationSpec>);
     method @NonNull public android.view.inputmethod.InlineSuggestionsRequest.Builder setInlineTooltipPresentationSpec(@NonNull android.widget.inline.InlinePresentationSpec);
     method @NonNull public android.view.inputmethod.InlineSuggestionsRequest.Builder setMaxSuggestionCount(int);
+    method @NonNull public android.view.inputmethod.InlineSuggestionsRequest.Builder setServiceSupported(boolean);
     method @NonNull public android.view.inputmethod.InlineSuggestionsRequest.Builder setSupportedLocales(@NonNull android.os.LocaleList);
   }
 
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index fbc69e3..92a5da7 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -271,6 +271,7 @@
     field public static final String READ_DEVICE_CONFIG = "android.permission.READ_DEVICE_CONFIG";
     field public static final String READ_DREAM_STATE = "android.permission.READ_DREAM_STATE";
     field public static final String READ_GLOBAL_APP_SEARCH_DATA = "android.permission.READ_GLOBAL_APP_SEARCH_DATA";
+    field public static final String READ_INSTALLED_SESSION_PATHS = "android.permission.READ_INSTALLED_SESSION_PATHS";
     field public static final String READ_INSTALL_SESSIONS = "android.permission.READ_INSTALL_SESSIONS";
     field public static final String READ_NETWORK_USAGE_HISTORY = "android.permission.READ_NETWORK_USAGE_HISTORY";
     field public static final String READ_OEM_UNLOCK_STATE = "android.permission.READ_OEM_UNLOCK_STATE";
@@ -969,19 +970,8 @@
   }
 
   public static final class Notification.TvExtender implements android.app.Notification.Extender {
-    ctor public Notification.TvExtender();
-    ctor public Notification.TvExtender(android.app.Notification);
-    method public android.app.Notification.Builder extend(android.app.Notification.Builder);
-    method public String getChannelId();
-    method public android.app.PendingIntent getContentIntent();
-    method public android.app.PendingIntent getDeleteIntent();
     method public boolean getSuppressShowOverApps();
-    method public boolean isAvailableOnTv();
     method public android.app.Notification.TvExtender setChannel(String);
-    method public android.app.Notification.TvExtender setChannelId(String);
-    method public android.app.Notification.TvExtender setContentIntent(android.app.PendingIntent);
-    method public android.app.Notification.TvExtender setDeleteIntent(android.app.PendingIntent);
-    method public android.app.Notification.TvExtender setSuppressShowOverApps(boolean);
   }
 
   public final class NotificationChannel implements android.os.Parcelable {
@@ -1063,6 +1053,23 @@
     method public void launchAssist(@Nullable android.os.Bundle);
   }
 
+  public final class StartLockscreenValidationRequest implements android.os.Parcelable {
+    method public int describeContents();
+    method public int getLockscreenUiType();
+    method public int getRemainingAttempts();
+    method @NonNull public byte[] getSourcePublicKey();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.app.StartLockscreenValidationRequest> CREATOR;
+  }
+
+  public static final class StartLockscreenValidationRequest.Builder {
+    ctor public StartLockscreenValidationRequest.Builder();
+    method @NonNull public android.app.StartLockscreenValidationRequest build();
+    method @NonNull public android.app.StartLockscreenValidationRequest.Builder setLockscreenUiType(int);
+    method @NonNull public android.app.StartLockscreenValidationRequest.Builder setRemainingAttempts(int);
+    method @NonNull public android.app.StartLockscreenValidationRequest.Builder setSourcePublicKey(@NonNull byte[]);
+  }
+
   public class StatusBarManager {
     method @NonNull @RequiresPermission(android.Manifest.permission.STATUS_BAR) public android.app.StatusBarManager.DisableInfo getDisableInfo();
     method @RequiresPermission(android.Manifest.permission.STATUS_BAR) public int getNavBarMode();
@@ -3214,7 +3221,7 @@
     method @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public void registerIntentInterceptor(@NonNull android.content.IntentFilter, @NonNull java.util.concurrent.Executor, @NonNull android.companion.virtual.VirtualDeviceManager.IntentInterceptorCallback);
     method public void removeActivityListener(@NonNull android.companion.virtual.VirtualDeviceManager.ActivityListener);
     method public void removeSoundEffectListener(@NonNull android.companion.virtual.VirtualDeviceManager.SoundEffectListener);
-    method @NonNull @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public void setShowPointerIcon(boolean);
+    method @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public void setShowPointerIcon(boolean);
     method @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public void unregisterIntentInterceptor(@NonNull android.companion.virtual.VirtualDeviceManager.IntentInterceptorCallback);
   }
 
@@ -3805,7 +3812,6 @@
     field public static final String EXTRA_CALLBACK = "android.content.pm.extra.CALLBACK";
     field public static final String EXTRA_DATA_LOADER_TYPE = "android.content.pm.extra.DATA_LOADER_TYPE";
     field public static final String EXTRA_LEGACY_STATUS = "android.content.pm.extra.LEGACY_STATUS";
-    field public static final String EXTRA_RESOLVED_BASE_PATH = "android.content.pm.extra.RESOLVED_BASE_PATH";
     field public static final int LOCATION_DATA_APP = 0; // 0x0
     field public static final int LOCATION_MEDIA_DATA = 2; // 0x2
     field public static final int LOCATION_MEDIA_OBB = 1; // 0x1
@@ -3842,6 +3848,7 @@
     method public boolean getInstallAsVirtualPreload();
     method public int getPendingUserActionReason();
     method public boolean getRequestDowngrade();
+    method @Nullable @RequiresPermission(android.Manifest.permission.READ_INSTALLED_SESSION_PATHS) public String getResolvedBaseApkPath();
     method public int getRollbackDataPolicy();
     method @NonNull public java.util.Set<java.lang.String> getWhitelistedRestrictedPermissions();
   }
@@ -10992,7 +10999,7 @@
     method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS, android.Manifest.permission.QUERY_USERS}) public boolean isPrimaryUser();
     method public static boolean isRemoveResultSuccessful(int);
     method public boolean isRestrictedProfile();
-    method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}, conditional=true) public boolean isRestrictedProfile(@NonNull android.os.UserHandle);
+    method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS, android.Manifest.permission.QUERY_USERS}, conditional=true) public boolean isRestrictedProfile(@NonNull android.os.UserHandle);
     method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.QUERY_USERS}) public boolean isSameProfileGroup(@NonNull android.os.UserHandle, @NonNull android.os.UserHandle);
     method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS, android.Manifest.permission.QUERY_USERS, android.Manifest.permission.GET_ACCOUNTS_PRIVILEGED}) public boolean isUserNameSet();
     method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS, android.Manifest.permission.QUERY_USERS}) public boolean isUserOfType(@NonNull String);
@@ -11234,7 +11241,7 @@
 
   public abstract class PermissionControllerService extends android.app.Service {
     ctor public PermissionControllerService();
-    method @NonNull @RequiresPermission("android.permission.MANAGE_COMPANION_DEVICES") public String getPrivilegesDescriptionStringForProfile(@NonNull String);
+    method @Deprecated @NonNull @RequiresPermission("android.permission.MANAGE_COMPANION_DEVICES") public String getPrivilegesDescriptionStringForProfile(@NonNull String);
     method @BinderThread public void onApplyStagedRuntimePermissionBackup(@NonNull String, @NonNull android.os.UserHandle, @NonNull java.util.function.Consumer<java.lang.Boolean>);
     method @NonNull public final android.os.IBinder onBind(android.content.Intent);
     method @BinderThread public abstract void onCountPermissionApps(@NonNull java.util.List<java.lang.String>, int, @NonNull java.util.function.IntConsumer);
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 873234a..b1f779f 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -3079,6 +3079,7 @@
     field public static final int HAL_SERVICE_MESSAGING = 2; // 0x2
     field public static final int HAL_SERVICE_MODEM = 3; // 0x3
     field public static final int HAL_SERVICE_NETWORK = 4; // 0x4
+    field public static final int HAL_SERVICE_SATELLITE = 8; // 0x8
     field public static final int HAL_SERVICE_SIM = 5; // 0x5
     field public static final int HAL_SERVICE_VOICE = 6; // 0x6
     field public static final android.util.Pair HAL_VERSION_UNKNOWN;
@@ -3522,18 +3523,12 @@
   }
 
   public final class AutofillManager {
-    method public void clearAutofillRequestCallback();
-    method @RequiresPermission(android.Manifest.permission.PROVIDE_OWN_AUTOFILL_SUGGESTIONS) public void setAutofillRequestCallback(@NonNull java.util.concurrent.Executor, @NonNull android.view.autofill.AutofillRequestCallback);
     field public static final String ANY_HINT = "any";
     field public static final int FLAG_SMART_SUGGESTION_OFF = 0; // 0x0
     field public static final int FLAG_SMART_SUGGESTION_SYSTEM = 1; // 0x1
     field public static final int MAX_TEMP_AUGMENTED_SERVICE_DURATION_MS = 120000; // 0x1d4c0
   }
 
-  public interface AutofillRequestCallback {
-    method public void onFillRequest(@Nullable android.view.inputmethod.InlineSuggestionsRequest, @NonNull android.os.CancellationSignal, @NonNull android.service.autofill.FillCallback);
-  }
-
 }
 
 package android.view.contentcapture {
@@ -3657,11 +3652,6 @@
     method @NonNull public static android.view.inputmethod.InlineSuggestionInfo newInlineSuggestionInfo(@NonNull android.widget.inline.InlinePresentationSpec, @NonNull String, @Nullable String[], @NonNull String, boolean);
   }
 
-  public static final class InlineSuggestionsRequest.Builder {
-    method @NonNull public android.view.inputmethod.InlineSuggestionsRequest.Builder setClientSupported(boolean);
-    method @NonNull public android.view.inputmethod.InlineSuggestionsRequest.Builder setServiceSupported(boolean);
-  }
-
   public final class InlineSuggestionsResponse implements android.os.Parcelable {
     method @NonNull public static android.view.inputmethod.InlineSuggestionsResponse newInlineSuggestionsResponse(@NonNull java.util.List<android.view.inputmethod.InlineSuggestion>);
   }
diff --git a/core/api/test-lint-baseline.txt b/core/api/test-lint-baseline.txt
index cf02643..4a97280 100644
--- a/core/api/test-lint-baseline.txt
+++ b/core/api/test-lint-baseline.txt
@@ -183,10 +183,6 @@
     android.telecom.ConnectionRequest does not declare a `shouldShowIncomingCallUi()` method matching method android.telecom.ConnectionRequest.Builder.setShouldShowIncomingCallUi(boolean)
 MissingGetterMatchingBuilder: android.view.Display.Mode.Builder#setResolution(int, int):
     android.view.Display.Mode does not declare a `getResolution()` method matching method android.view.Display.Mode.Builder.setResolution(int,int)
-MissingGetterMatchingBuilder: android.view.inputmethod.InlineSuggestionsRequest.Builder#setClientSupported(boolean):
-    android.view.inputmethod.InlineSuggestionsRequest does not declare a `isClientSupported()` method matching method android.view.inputmethod.InlineSuggestionsRequest.Builder.setClientSupported(boolean)
-MissingGetterMatchingBuilder: android.view.inputmethod.InlineSuggestionsRequest.Builder#setServiceSupported(boolean):
-    android.view.inputmethod.InlineSuggestionsRequest does not declare a `isServiceSupported()` method matching method android.view.inputmethod.InlineSuggestionsRequest.Builder.setServiceSupported(boolean)
 
 
 MissingNullability: android.app.Activity#onMovedToDisplay(int, android.content.res.Configuration) parameter #1:
diff --git a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
index 6dcf331..7337cf8 100644
--- a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
+++ b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
@@ -107,81 +107,82 @@
      * Capability: This accessibility service can retrieve the active window content.
      * @see android.R.styleable#AccessibilityService_canRetrieveWindowContent
      */
-    public static final int CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT = 0x00000001;
+    public static final int CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT = 1 /* << 0 */;
 
     /**
      * Capability: This accessibility service can request touch exploration mode in which
      * touched items are spoken aloud and the UI can be explored via gestures.
      * @see android.R.styleable#AccessibilityService_canRequestTouchExplorationMode
      */
-    public static final int CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION = 0x00000002;
+    public static final int CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION = 1 << 1;
 
     /**
      * @deprecated No longer used
      */
-    public static final int CAPABILITY_CAN_REQUEST_ENHANCED_WEB_ACCESSIBILITY = 0x00000004;
+    @Deprecated
+    public static final int CAPABILITY_CAN_REQUEST_ENHANCED_WEB_ACCESSIBILITY = 1 << 2;
 
     /**
      * Capability: This accessibility service can request to filter the key event stream.
      * @see android.R.styleable#AccessibilityService_canRequestFilterKeyEvents
      */
-    public static final int CAPABILITY_CAN_REQUEST_FILTER_KEY_EVENTS = 0x00000008;
+    public static final int CAPABILITY_CAN_REQUEST_FILTER_KEY_EVENTS = 1 << 3;
 
     /**
      * Capability: This accessibility service can control display magnification.
      * @see android.R.styleable#AccessibilityService_canControlMagnification
      */
-    public static final int CAPABILITY_CAN_CONTROL_MAGNIFICATION = 0x00000010;
+    public static final int CAPABILITY_CAN_CONTROL_MAGNIFICATION = 1 << 4;
 
     /**
      * Capability: This accessibility service can perform gestures.
      * @see android.R.styleable#AccessibilityService_canPerformGestures
      */
-    public static final int CAPABILITY_CAN_PERFORM_GESTURES = 0x00000020;
+    public static final int CAPABILITY_CAN_PERFORM_GESTURES = 1 << 5;
 
     /**
      * Capability: This accessibility service can capture gestures from the fingerprint sensor
      * @see android.R.styleable#AccessibilityService_canRequestFingerprintGestures
      */
-    public static final int CAPABILITY_CAN_REQUEST_FINGERPRINT_GESTURES = 0x00000040;
+    public static final int CAPABILITY_CAN_REQUEST_FINGERPRINT_GESTURES = 1 << 6;
 
     /**
      * Capability: This accessibility service can take screenshot.
      * @see android.R.styleable#AccessibilityService_canTakeScreenshot
      */
-    public static final int CAPABILITY_CAN_TAKE_SCREENSHOT = 0x00000080;
+    public static final int CAPABILITY_CAN_TAKE_SCREENSHOT = 1 << 7;
 
     private static SparseArray<CapabilityInfo> sAvailableCapabilityInfos;
 
     /**
      * Denotes spoken feedback.
      */
-    public static final int FEEDBACK_SPOKEN = 0x0000001;
+    public static final int FEEDBACK_SPOKEN = 1 /* << 0 */;
 
     /**
      * Denotes haptic feedback.
      */
-    public static final int FEEDBACK_HAPTIC =  0x0000002;
+    public static final int FEEDBACK_HAPTIC =  1 << 1;
 
     /**
      * Denotes audible (not spoken) feedback.
      */
-    public static final int FEEDBACK_AUDIBLE = 0x0000004;
+    public static final int FEEDBACK_AUDIBLE = 1 << 2;
 
     /**
      * Denotes visual feedback.
      */
-    public static final int FEEDBACK_VISUAL = 0x0000008;
+    public static final int FEEDBACK_VISUAL = 1 << 3;
 
     /**
      * Denotes generic feedback.
      */
-    public static final int FEEDBACK_GENERIC = 0x0000010;
+    public static final int FEEDBACK_GENERIC = 1 << 4;
 
     /**
      * Denotes braille feedback.
      */
-    public static final int FEEDBACK_BRAILLE = 0x0000020;
+    public static final int FEEDBACK_BRAILLE = 1 << 5;
 
     /**
      * Mask for all feedback types.
@@ -200,7 +201,7 @@
      * Default service is invoked only if no package specific one exists. In case of
      * more than one package specific service only the earlier registered is notified.
      */
-    public static final int DEFAULT = 0x0000001;
+    public static final int DEFAULT = 1 /* << 0 */;
 
     /**
      * If this flag is set the system will regard views that are not important
@@ -230,7 +231,7 @@
      * elements.
      * </p>
      */
-    public static final int FLAG_INCLUDE_NOT_IMPORTANT_VIEWS = 0x0000002;
+    public static final int FLAG_INCLUDE_NOT_IMPORTANT_VIEWS = 1 << 1;
 
     /**
      * This flag requests that the system gets into touch exploration mode.
@@ -258,12 +259,13 @@
      * </p>
      * @see android.R.styleable#AccessibilityService_canRequestTouchExplorationMode
      */
-    public static final int FLAG_REQUEST_TOUCH_EXPLORATION_MODE = 0x0000004;
+    public static final int FLAG_REQUEST_TOUCH_EXPLORATION_MODE = 1 << 2;
 
     /**
      * @deprecated No longer used
      */
-    public static final int FLAG_REQUEST_ENHANCED_WEB_ACCESSIBILITY = 0x00000008;
+    @Deprecated
+    public static final int FLAG_REQUEST_ENHANCED_WEB_ACCESSIBILITY = 1 << 3;
 
     /**
      * This flag requests that the {@link AccessibilityNodeInfo}s obtained
@@ -272,7 +274,7 @@
      * form "package:id/name", for example "foo.bar:id/my_list", and it is
      * useful for UI test automation. This flag is not set by default.
      */
-    public static final int FLAG_REPORT_VIEW_IDS = 0x00000010;
+    public static final int FLAG_REPORT_VIEW_IDS = 1 << 4;
 
     /**
      * This flag requests from the system to filter key events. If this flag
@@ -287,7 +289,7 @@
      * </p>
      * @see android.R.styleable#AccessibilityService_canRequestFilterKeyEvents
      */
-    public static final int FLAG_REQUEST_FILTER_KEY_EVENTS = 0x00000020;
+    public static final int FLAG_REQUEST_FILTER_KEY_EVENTS = 1 << 5;
 
     /**
      * This flag indicates to the system that the accessibility service wants
@@ -308,14 +310,14 @@
      * </p>
      * @see android.R.styleable#AccessibilityService_canRetrieveWindowContent
      */
-    public static final int FLAG_RETRIEVE_INTERACTIVE_WINDOWS = 0x00000040;
+    public static final int FLAG_RETRIEVE_INTERACTIVE_WINDOWS = 1 << 6;
 
     /**
      * This flag requests that all audio tracks system-wide with
      * {@link android.media.AudioAttributes#USAGE_ASSISTANCE_ACCESSIBILITY} be controlled by the
      * {@link android.media.AudioManager#STREAM_ACCESSIBILITY} volume.
      */
-    public static final int FLAG_ENABLE_ACCESSIBILITY_VOLUME = 0x00000080;
+    public static final int FLAG_ENABLE_ACCESSIBILITY_VOLUME = 1 << 7;
 
      /**
      * This flag indicates to the system that the accessibility service requests that an
@@ -326,7 +328,7 @@
       *   accessibility service metadata file. Otherwise, it will be ignored.
       * </p>
      */
-    public static final int FLAG_REQUEST_ACCESSIBILITY_BUTTON = 0x00000100;
+    public static final int FLAG_REQUEST_ACCESSIBILITY_BUTTON = 1 << 8;
 
     /**
      * This flag requests that all fingerprint gestures be sent to the accessibility service.
@@ -341,13 +343,13 @@
      * @see android.R.styleable#AccessibilityService_canRequestFingerprintGestures
      * @see AccessibilityService#getFingerprintGestureController()
      */
-    public static final int FLAG_REQUEST_FINGERPRINT_GESTURES = 0x00000200;
+    public static final int FLAG_REQUEST_FINGERPRINT_GESTURES = 1 << 9;
 
     /**
      * This flag requests that accessibility shortcut warning dialog has spoken feedback when
      * dialog is shown.
      */
-    public static final int FLAG_REQUEST_SHORTCUT_WARNING_DIALOG_SPOKEN_FEEDBACK = 0x00000400;
+    public static final int FLAG_REQUEST_SHORTCUT_WARNING_DIALOG_SPOKEN_FEEDBACK = 1 << 10;
 
     /**
      * This flag requests that when {@link #FLAG_REQUEST_TOUCH_EXPLORATION_MODE} is enabled,
@@ -357,7 +359,7 @@
      *
      * @see #FLAG_REQUEST_TOUCH_EXPLORATION_MODE
      */
-    public static final int FLAG_SERVICE_HANDLES_DOUBLE_TAP = 0x0000800;
+    public static final int FLAG_SERVICE_HANDLES_DOUBLE_TAP = 1 << 11;
 
     /**
      * This flag requests that when when {@link #FLAG_REQUEST_TOUCH_EXPLORATION_MODE} is enabled,
@@ -367,7 +369,7 @@
      *
      * @see #FLAG_REQUEST_TOUCH_EXPLORATION_MODE
      */
-    public static final int FLAG_REQUEST_MULTI_FINGER_GESTURES = 0x0001000;
+    public static final int FLAG_REQUEST_MULTI_FINGER_GESTURES = 1 << 12;
 
     /**
      * This flag requests that when when {@link #FLAG_REQUEST_MULTI_FINGER_GESTURES} is enabled,
@@ -378,7 +380,7 @@
      *
      * @see #FLAG_REQUEST_TOUCH_EXPLORATION_MODE
      */
-    public static final int FLAG_REQUEST_2_FINGER_PASSTHROUGH = 0x0002000;
+    public static final int FLAG_REQUEST_2_FINGER_PASSTHROUGH = 1 << 13;
 
     /**
      * This flag requests that when when {@link #FLAG_REQUEST_TOUCH_EXPLORATION_MODE} is enabled, a
@@ -392,7 +394,7 @@
      *
      * @see #FLAG_REQUEST_TOUCH_EXPLORATION_MODE
      */
-    public static final int FLAG_SEND_MOTION_EVENTS = 0x0004000;
+    public static final int FLAG_SEND_MOTION_EVENTS = 1 << 14;
 
     /**
      * This flag makes the AccessibilityService an input method editor with a subset of input
@@ -401,10 +403,10 @@
      *
      * @see AccessibilityService#getInputMethod()
      */
-    public static final int FLAG_INPUT_METHOD_EDITOR = 0x0008000;
+    public static final int FLAG_INPUT_METHOD_EDITOR = 1 << 15;
 
     /** {@hide} */
-    public static final int FLAG_FORCE_DIRECT_BOOT_AWARE = 0x00010000;
+    public static final int FLAG_FORCE_DIRECT_BOOT_AWARE = 1 << 16;
 
     /**
      * The event types an {@link AccessibilityService} is interested in.
diff --git a/core/java/android/accounts/Account.java b/core/java/android/accounts/Account.java
index 0d6a079..c376eae 100644
--- a/core/java/android/accounts/Account.java
+++ b/core/java/android/accounts/Account.java
@@ -45,8 +45,8 @@
     @GuardedBy("sAccessedAccounts")
     private static final Set<Account> sAccessedAccounts = new ArraySet<>();
 
-    public final String name;
-    public final String type;
+    public final @NonNull String name;
+    public final @NonNull String type;
     private String mSafeName;
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
     private final @Nullable String accessId;
@@ -65,7 +65,7 @@
         return result;
     }
 
-    public Account(String name, String type) {
+    public Account(@NonNull String name, @NonNull String type) {
         this(name, type, null);
     }
 
@@ -79,7 +79,7 @@
     /**
      * @hide
      */
-    public Account(String name, String type, String accessId) {
+    public Account(@NonNull String name, @NonNull String type, String accessId) {
         if (TextUtils.isEmpty(name)) {
             throw new IllegalArgumentException("the name must not be empty: " + name);
         }
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 8021ce0..125e727 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -9209,7 +9209,6 @@
      *
      * @param allowed {@code true} to disable the UID restrictions; {@code false} to revert back to
      *                            the default behaviour
-     * @hide
      */
     public void setAllowCrossUidActivitySwitchFromBelow(boolean allowed) {
         ActivityClient.getInstance().setAllowCrossUidActivitySwitchFromBelow(mToken, allowed);
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 813e32a..b8e40f8 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -192,6 +192,11 @@
      * @hide
      */
     public static final int INSTR_FLAG_INSTRUMENT_SDK_SANDBOX = 1 << 5;
+    /**
+     * Instrument an Sdk Sandbox process corresponding to an Sdk running inside the sandbox.
+     * @hide
+     */
+    public static final int INSTR_FLAG_INSTRUMENT_SDK_IN_SANDBOX = 1 << 6;
 
     static final class UidObserver extends IUidObserver.Stub {
         final OnUidImportanceListener mListener;
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 7b4aeec..ba61fad 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -119,6 +119,8 @@
 import android.os.Build;
 import android.os.Bundle;
 import android.os.CancellationSignal;
+import android.os.DdmSyncStageUpdater;
+import android.os.DdmSyncState.Stage;
 import android.os.Debug;
 import android.os.Environment;
 import android.os.FileUtils;
@@ -265,6 +267,9 @@
  */
 public final class ActivityThread extends ClientTransactionHandler
         implements ActivityThreadInternal {
+
+    private final DdmSyncStageUpdater mDdmSyncStageUpdater = new DdmSyncStageUpdater();
+
     /** @hide */
     public static final String TAG = "ActivityThread";
     private static final android.graphics.Bitmap.Config THUMBNAIL_FORMAT = Bitmap.Config.RGB_565;
@@ -880,6 +885,7 @@
         ApplicationInfo appInfo;
         String sdkSandboxClientAppVolumeUuid;
         String sdkSandboxClientAppPackage;
+        boolean isSdkInSandbox;
         @UnsupportedAppUsage
         List<ProviderInfo> providers;
         ComponentName instrumentationName;
@@ -1161,19 +1167,34 @@
         }
 
         @Override
-        public final void bindApplication(String processName, ApplicationInfo appInfo,
-                String sdkSandboxClientAppVolumeUuid, String sdkSandboxClientAppPackage,
-                ProviderInfoList providerList, ComponentName instrumentationName,
-                ProfilerInfo profilerInfo, Bundle instrumentationArgs,
+        public final void bindApplication(
+                String processName,
+                ApplicationInfo appInfo,
+                String sdkSandboxClientAppVolumeUuid,
+                String sdkSandboxClientAppPackage,
+                boolean isSdkInSandbox,
+                ProviderInfoList providerList,
+                ComponentName instrumentationName,
+                ProfilerInfo profilerInfo,
+                Bundle instrumentationArgs,
                 IInstrumentationWatcher instrumentationWatcher,
-                IUiAutomationConnection instrumentationUiConnection, int debugMode,
-                boolean enableBinderTracking, boolean trackAllocation,
-                boolean isRestrictedBackupMode, boolean persistent, Configuration config,
-                CompatibilityInfo compatInfo, Map services, Bundle coreSettings,
-                String buildSerial, AutofillOptions autofillOptions,
-                ContentCaptureOptions contentCaptureOptions, long[] disabledCompatChanges,
+                IUiAutomationConnection instrumentationUiConnection,
+                int debugMode,
+                boolean enableBinderTracking,
+                boolean trackAllocation,
+                boolean isRestrictedBackupMode,
+                boolean persistent,
+                Configuration config,
+                CompatibilityInfo compatInfo,
+                Map services,
+                Bundle coreSettings,
+                String buildSerial,
+                AutofillOptions autofillOptions,
+                ContentCaptureOptions contentCaptureOptions,
+                long[] disabledCompatChanges,
                 SharedMemory serializedSystemFontMap,
-                long startRequestedElapsedTime, long startRequestedUptime) {
+                long startRequestedElapsedTime,
+                long startRequestedUptime) {
             if (services != null) {
                 if (false) {
                     // Test code to make sure the app could see the passed-in services.
@@ -1207,6 +1228,7 @@
             data.appInfo = appInfo;
             data.sdkSandboxClientAppVolumeUuid = sdkSandboxClientAppVolumeUuid;
             data.sdkSandboxClientAppPackage = sdkSandboxClientAppPackage;
+            data.isSdkInSandbox = isSdkInSandbox;
             data.providers = providerList.getList();
             data.instrumentationName = instrumentationName;
             data.instrumentationArgs = instrumentationArgs;
@@ -6681,6 +6703,8 @@
 
     @UnsupportedAppUsage
     private void handleBindApplication(AppBindData data) {
+        mDdmSyncStageUpdater.next(Stage.Bind);
+
         // Register the UI Thread as a sensitive thread to the runtime.
         VMRuntime.registerSensitiveThread();
         // In the case the stack depth property exists, pass it down to the runtime.
@@ -6730,6 +6754,7 @@
                                                 data.appInfo.packageName,
                                                 UserHandle.myUserId());
         VMRuntime.setProcessPackageName(data.appInfo.packageName);
+        mDdmSyncStageUpdater.next(Stage.Named);
 
         // Pass data directory path to ART. This is used for caching information and
         // should be set before any application code is loaded.
@@ -6934,6 +6959,7 @@
         final StrictMode.ThreadPolicy writesAllowedPolicy = StrictMode.getThreadPolicy();
 
         if (data.debugMode != ApplicationThreadConstants.DEBUG_OFF) {
+            mDdmSyncStageUpdater.next(Stage.Debugger);
             if (data.debugMode == ApplicationThreadConstants.DEBUG_WAIT) {
                 waitForDebugger(data);
             } else if (data.debugMode == ApplicationThreadConstants.DEBUG_SUSPEND) {
@@ -6941,6 +6967,7 @@
             }
             // Nothing special to do in case of DEBUG_ON.
         }
+        mDdmSyncStageUpdater.next(Stage.Running);
 
         try {
             // If the app is being launched for full backup or restore, bring it up in
@@ -7192,8 +7219,14 @@
         // The test context's op package name == the target app's op package name, because
         // the app ops manager checks the op package name against the real calling UID,
         // which is what the target package name is associated with.
-        final ContextImpl instrContext = ContextImpl.createAppContext(this, pi,
-                appContext.getOpPackageName());
+        // In the case of instrumenting an sdk running in the sdk sandbox, appContext refers
+        // to the context of the sdk running in the sandbox. Since the sandbox does not have
+        // access to data outside the sandbox, we require the instrContext to point to the
+        // sdk in the sandbox as well, and not to the test context.
+        final ContextImpl instrContext =
+                (data.isSdkInSandbox)
+                        ? appContext
+                        : ContextImpl.createAppContext(this, pi, appContext.getOpPackageName());
 
         try {
             final ClassLoader cl = instrContext.getClassLoader();
@@ -7844,6 +7877,7 @@
         mConfigurationController = new ConfigurationController(this);
         mSystemThread = system;
         mStartSeq = startSeq;
+        mDdmSyncStageUpdater.next(Stage.Attach);
 
         if (!system) {
             android.ddm.DdmHandleAppName.setAppName("<pre-initialized>",
diff --git a/core/java/android/app/IApplicationThread.aidl b/core/java/android/app/IApplicationThread.aidl
index 6b5f6b0..75d8c10 100644
--- a/core/java/android/app/IApplicationThread.aidl
+++ b/core/java/android/app/IApplicationThread.aidl
@@ -78,6 +78,7 @@
     void scheduleStopService(IBinder token);
     void bindApplication(in String packageName, in ApplicationInfo info,
             in String sdkSandboxClientAppVolumeUuid, in String sdkSandboxClientAppPackage,
+            in boolean isSdkInSandbox,
             in ProviderInfoList providerList, in ComponentName testName,
             in ProfilerInfo profilerInfo, in Bundle testArguments,
             IInstrumentationWatcher testWatcher, IUiAutomationConnection uiAutomationConnection,
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index 746b8f7..f31132a 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -127,13 +127,16 @@
     // INotificationListener method.
     @UnsupportedAppUsage
     StatusBarNotification[] getActiveNotifications(String callingPkg);
+    @EnforcePermission("ACCESS_NOTIFICATIONS")
     StatusBarNotification[] getActiveNotificationsWithAttribution(String callingPkg,
             String callingAttributionTag);
     @UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553)
     StatusBarNotification[] getHistoricalNotifications(String callingPkg, int count, boolean includeSnoozed);
+    @EnforcePermission("ACCESS_NOTIFICATIONS")
     StatusBarNotification[] getHistoricalNotificationsWithAttribution(String callingPkg,
             String callingAttributionTag, int count, boolean includeSnoozed);
 
+    @EnforcePermission("ACCESS_NOTIFICATIONS")
     NotificationHistory getNotificationHistory(String callingPkg, String callingAttributionTag);
 
     void registerListener(in INotificationListener listener, in ComponentName component, int userid);
diff --git a/core/java/android/app/KeyguardManager.java b/core/java/android/app/KeyguardManager.java
index 09450f5..f71e78c 100644
--- a/core/java/android/app/KeyguardManager.java
+++ b/core/java/android/app/KeyguardManager.java
@@ -146,6 +146,15 @@
     public static final String EXTRA_CHECKBOX_LABEL = "android.app.extra.CHECKBOX_LABEL";
 
     /**
+     * A {@link StartLockscreenValidationRequest} extra to be sent along with
+     * {@link #ACTION_CONFIRM_REMOTE_DEVICE_CREDENTIAL} containing the data needed to prompt for
+     * a remote device's lock screen.
+     * @hide
+     */
+    public static final String EXTRA_START_LOCKSCREEN_VALIDATION_REQUEST =
+            "android.app.extra.START_LOCKSCREEN_VALIDATION_REQUEST";
+
+    /**
      * A {@link RemoteLockscreenValidationSession} extra to be sent along with
      * {@link #ACTION_CONFIRM_REMOTE_DEVICE_CREDENTIAL} containing the data needed to prompt for
      * a remote device's lock screen.
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index bf69531..dc197bd 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -1401,95 +1401,99 @@
         if (mApplication != null) {
             return mApplication;
         }
-        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "makeApplication");
 
-        synchronized (sApplications) {
-            final Application cached = sApplications.get(mPackageName);
-            if (cached != null) {
-                // Looks like this is always happening for the system server, because
-                // the LoadedApk created in systemMain() -> attach() isn't cached properly?
-                if (!"android".equals(mPackageName)) {
-                    Slog.wtfStack(TAG, "App instance already created for package=" + mPackageName
-                            + " instance=" + cached);
-                }
-                if (!allowDuplicateInstances) {
-                    mApplication = cached;
-                    return cached;
-                }
-                // Some apps intentionally call makeApplication() to create a new Application
-                // instance... Sigh...
-            }
-        }
 
-        Application app = null;
-
-        final String myProcessName = Process.myProcessName();
-        String appClass = mApplicationInfo.getCustomApplicationClassNameForProcess(
-                myProcessName);
-        if (forceDefaultAppClass || (appClass == null)) {
-            appClass = "android.app.Application";
+        if (Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) {
+            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "makeApplication");
         }
 
         try {
-            final java.lang.ClassLoader cl = getClassLoader();
-            if (!mPackageName.equals("android")) {
-                Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
-                        "initializeJavaContextClassLoader");
-                initializeJavaContextClassLoader();
-                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
-            }
-
-            // Rewrite the R 'constants' for all library apks.
-            SparseArray<String> packageIdentifiers = getAssets().getAssignedPackageIdentifiers(
-                    false, false);
-            for (int i = 0, n = packageIdentifiers.size(); i < n; i++) {
-                final int id = packageIdentifiers.keyAt(i);
-                if (id == 0x01 || id == 0x7f) {
-                    continue;
-                }
-
-                rewriteRValues(cl, packageIdentifiers.valueAt(i), id);
-            }
-
-            ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
-            // The network security config needs to be aware of multiple
-            // applications in the same process to handle discrepancies
-            NetworkSecurityConfigProvider.handleNewApplication(appContext);
-            app = mActivityThread.mInstrumentation.newApplication(
-                    cl, appClass, appContext);
-            appContext.setOuterContext(app);
-        } catch (Exception e) {
-            if (!mActivityThread.mInstrumentation.onException(app, e)) {
-                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
-                throw new RuntimeException(
-                    "Unable to instantiate application " + appClass
-                    + " package " + mPackageName + ": " + e.toString(), e);
-            }
-        }
-        mActivityThread.mAllApplications.add(app);
-        mApplication = app;
-        if (!allowDuplicateInstances) {
             synchronized (sApplications) {
-                sApplications.put(mPackageName, app);
-            }
-        }
-
-        if (instrumentation != null) {
-            try {
-                instrumentation.callApplicationOnCreate(app);
-            } catch (Exception e) {
-                if (!instrumentation.onException(app, e)) {
-                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
-                    throw new RuntimeException(
-                        "Unable to create application " + app.getClass().getName()
-                        + ": " + e.toString(), e);
+                final Application cached = sApplications.get(mPackageName);
+                if (cached != null) {
+                    // Looks like this is always happening for the system server, because
+                    // the LoadedApk created in systemMain() -> attach() isn't cached properly?
+                    if (!"android".equals(mPackageName)) {
+                        Slog.wtfStack(TAG, "App instance already created for package="
+                                + mPackageName + " instance=" + cached);
+                    }
+                    if (!allowDuplicateInstances) {
+                        mApplication = cached;
+                        return cached;
+                    }
+                    // Some apps intentionally call makeApplication() to create a new Application
+                    // instance... Sigh...
                 }
             }
+
+            Application app = null;
+
+            final String myProcessName = Process.myProcessName();
+            String appClass = mApplicationInfo.getCustomApplicationClassNameForProcess(
+                    myProcessName);
+            if (forceDefaultAppClass || (appClass == null)) {
+                appClass = "android.app.Application";
+            }
+
+            try {
+                final java.lang.ClassLoader cl = getClassLoader();
+                if (!mPackageName.equals("android")) {
+                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
+                            "initializeJavaContextClassLoader");
+                    initializeJavaContextClassLoader();
+                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
+                }
+
+                // Rewrite the R 'constants' for all library apks.
+                SparseArray<String> packageIdentifiers = getAssets().getAssignedPackageIdentifiers(
+                        false, false);
+                for (int i = 0, n = packageIdentifiers.size(); i < n; i++) {
+                    final int id = packageIdentifiers.keyAt(i);
+                    if (id == 0x01 || id == 0x7f) {
+                        continue;
+                    }
+
+                    rewriteRValues(cl, packageIdentifiers.valueAt(i), id);
+                }
+
+                ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
+                // The network security config needs to be aware of multiple
+                // applications in the same process to handle discrepancies
+                NetworkSecurityConfigProvider.handleNewApplication(appContext);
+                app = mActivityThread.mInstrumentation.newApplication(
+                        cl, appClass, appContext);
+                appContext.setOuterContext(app);
+            } catch (Exception e) {
+                if (!mActivityThread.mInstrumentation.onException(app, e)) {
+                    throw new RuntimeException(
+                        "Unable to instantiate application " + appClass
+                        + " package " + mPackageName + ": " + e.toString(), e);
+                }
+            }
+            mActivityThread.mAllApplications.add(app);
+            mApplication = app;
+            if (!allowDuplicateInstances) {
+                synchronized (sApplications) {
+                    sApplications.put(mPackageName, app);
+                }
+            }
+
+            if (instrumentation != null) {
+                try {
+                    instrumentation.callApplicationOnCreate(app);
+                } catch (Exception e) {
+                    if (!instrumentation.onException(app, e)) {
+                        throw new RuntimeException(
+                            "Unable to create application " + app.getClass().getName()
+                            + ": " + e.toString(), e);
+                    }
+                }
+            }
+
+            return app;
+        } finally {
+            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
         }
-
-        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
-
-        return app;
     }
 
     @UnsupportedAppUsage
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 7aedd30..63795cf 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -12055,10 +12055,7 @@
      * <p>TV extensions can be accessed on an existing notification by using the
      * {@code TvExtender(Notification)} constructor, and then using the {@code get} methods
      * to access values.
-     *
-     * @hide
      */
-    @SystemApi
     public static final class TvExtender implements Extender {
         private static final String TAG = "TvExtender";
 
@@ -12090,7 +12087,7 @@
          *
          * @param notif The notification from which to copy options.
          */
-        public TvExtender(Notification notif) {
+        public TvExtender(@NonNull Notification notif) {
             Bundle bundle = notif.extras == null ?
                 null : notif.extras.getBundle(EXTRA_TV_EXTENDER);
             if (bundle != null) {
@@ -12108,7 +12105,8 @@
          * method of {@link Notification.Builder}.
          */
         @Override
-        public Notification.Builder extend(Notification.Builder builder) {
+        @NonNull
+        public Notification.Builder extend(@NonNull Notification.Builder builder) {
             Bundle bundle = new Bundle();
 
             bundle.putInt(EXTRA_FLAGS, mFlags);
@@ -12127,7 +12125,7 @@
         }
 
         /**
-         * Returns true if this notification should be shown on TV. This method return true
+         * Returns true if this notification should be shown on TV. This method returns true
          * if the notification was extended with a TvExtender.
          */
         public boolean isAvailableOnTv() {
@@ -12137,8 +12135,11 @@
         /**
          * Specifies the channel the notification should be delivered on when shown on TV.
          * It can be different from the channel that the notification is delivered to when
-         * posting on a non-TV device.
+         * posting on a non-TV device. Prefer to use {@link setChannelId(String)}.
+         *
+         * @hide
          */
+        @SystemApi
         public TvExtender setChannel(String channelId) {
             mChannelId = channelId;
             return this;
@@ -12148,14 +12149,21 @@
          * Specifies the channel the notification should be delivered on when shown on TV.
          * It can be different from the channel that the notification is delivered to when
          * posting on a non-TV device.
+         *
+         * @return this object for method chaining
          */
-        public TvExtender setChannelId(String channelId) {
+        @NonNull
+        public TvExtender setChannelId(@Nullable String channelId) {
             mChannelId = channelId;
             return this;
         }
 
-        /** @removed */
+        /**
+         * @removed
+         * @hide
+         */
         @Deprecated
+        @SystemApi
         public String getChannel() {
             return mChannelId;
         }
@@ -12163,6 +12171,7 @@
         /**
          * Returns the id of the channel this notification posts to on TV.
          */
+        @Nullable
         public String getChannelId() {
             return mChannelId;
         }
@@ -12171,8 +12180,12 @@
          * Supplies a {@link PendingIntent} to be sent when the notification is selected on TV.
          * If provided, it is used instead of the content intent specified
          * at the level of Notification.
+         *
+         * @param intent the {@link PendingIntent} for the associated notification content
+         * @return this object for method chaining
          */
-        public TvExtender setContentIntent(PendingIntent intent) {
+        @NonNull
+        public TvExtender setContentIntent(@Nullable PendingIntent intent) {
             mContentIntent = intent;
             return this;
         }
@@ -12181,8 +12194,9 @@
          * Returns the TV-specific content intent.  If this method returns null, the
          * main content intent on the notification should be used.
          *
-         * @see {@link Notification#contentIntent}
+         * @see Notification#contentIntent
          */
+        @Nullable
         public PendingIntent getContentIntent() {
             return mContentIntent;
         }
@@ -12191,8 +12205,12 @@
          * Supplies a {@link PendingIntent} to send when the notification is cleared explicitly
          * by the user on TV.  If provided, it is used instead of the delete intent specified
          * at the level of Notification.
+         *
+         * @param intent the {@link PendingIntent} for the associated notification deletion
+         * @return this object for method chaining
          */
-        public TvExtender setDeleteIntent(PendingIntent intent) {
+        @NonNull
+        public TvExtender setDeleteIntent(@Nullable PendingIntent intent) {
             mDeleteIntent = intent;
             return this;
         }
@@ -12201,8 +12219,9 @@
          * Returns the TV-specific delete intent.  If this method returns null, the
          * main delete intent on the notification should be used.
          *
-         * @see {@link Notification#deleteIntent}
+         * @see Notification#deleteIntent
          */
+        @Nullable
         public PendingIntent getDeleteIntent() {
             return mDeleteIntent;
         }
@@ -12210,7 +12229,11 @@
         /**
          * Specifies whether this notification should suppress showing a message over top of apps
          * outside of the launcher.
+         *
+         * @param suppress whether the notification should suppress showing over apps.
+         * @return this object for method chaining
          */
+        @NonNull
         public TvExtender setSuppressShowOverApps(boolean suppress) {
             mSuppressShowOverApps = suppress;
             return this;
@@ -12219,10 +12242,21 @@
         /**
          * Returns true if this notification should not show messages over top of apps
          * outside of the launcher.
+         *
+         * @hide
          */
+        @SystemApi
         public boolean getSuppressShowOverApps() {
             return mSuppressShowOverApps;
         }
+
+        /**
+         * Returns true if this notification should not show messages over top of apps
+         * outside of the launcher.
+         */
+        public boolean isSuppressShowOverApps() {
+            return mSuppressShowOverApps;
+        }
     }
 
     /**
diff --git a/core/java/android/app/StartLockscreenValidationRequest.aidl b/core/java/android/app/StartLockscreenValidationRequest.aidl
new file mode 100644
index 0000000..367dfee
--- /dev/null
+++ b/core/java/android/app/StartLockscreenValidationRequest.aidl
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app;
+
+/** {@hide} */
+parcelable StartLockscreenValidationRequest;
diff --git a/core/java/android/app/StartLockscreenValidationRequest.java b/core/java/android/app/StartLockscreenValidationRequest.java
new file mode 100644
index 0000000..e818195
--- /dev/null
+++ b/core/java/android/app/StartLockscreenValidationRequest.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app;
+
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
+import android.app.KeyguardManager.LockTypes;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Objects;
+
+/**
+ * Provides information necessary to perform remote lock screen credentials check.
+ *
+ * @hide
+ */
+@SystemApi
+public final class StartLockscreenValidationRequest implements Parcelable {
+
+    @LockTypes
+    private int mLockscreenUiType;
+
+    private byte[] mSourcePublicKey;
+
+    private int mRemainingAttempts;
+
+    public static final @NonNull Parcelable.Creator<StartLockscreenValidationRequest> CREATOR = new
+            Parcelable.Creator<StartLockscreenValidationRequest>() {
+        @Override
+        public StartLockscreenValidationRequest createFromParcel(Parcel source) {
+            return new StartLockscreenValidationRequest(source);
+        }
+
+        @Override
+        public StartLockscreenValidationRequest[] newArray(int size) {
+            return new StartLockscreenValidationRequest[size];
+        }
+    };
+
+
+    /**
+     * Builder for {@code StartLockscreenValidationRequest}
+     */
+    public static final class Builder {
+        private StartLockscreenValidationRequest mInstance = new StartLockscreenValidationRequest();
+
+        /**
+         * Sets UI type.
+         * Default value is {@code LockTypes.PASSWORD}
+         *
+         * @param lockscreenUiType The UI format
+         * @return This builder.
+         */
+        public @NonNull Builder setLockscreenUiType(@LockTypes int lockscreenUiType) {
+            mInstance.mLockscreenUiType = lockscreenUiType;
+            return this;
+        }
+
+        /**
+         * Sets public key using secure box encoding
+         * @return This builder.
+         */
+        public @NonNull Builder setSourcePublicKey(@NonNull byte[] publicKey) {
+            mInstance.mSourcePublicKey = publicKey;
+            return this;
+        }
+
+        /**
+         * Sets the number of remaining credentials check
+         * Default value is {@code 0}
+         *
+         * @return This builder.
+         */
+        public @NonNull Builder setRemainingAttempts(int remainingAttempts) {
+            mInstance.mRemainingAttempts = remainingAttempts;
+            return this;
+        }
+
+        /**
+         * Creates {@code StartLockscreenValidationRequest}
+         *
+         * @throws NullPointerException if required fields are not set.
+         */
+        public @NonNull StartLockscreenValidationRequest build() {
+            Objects.requireNonNull(mInstance.mSourcePublicKey);
+            return mInstance;
+        }
+    }
+
+    /**
+     * Specifies lock screen credential type.
+     */
+    public @LockTypes int getLockscreenUiType() {
+        return mLockscreenUiType;
+    }
+
+    /**
+     * Public key used to send encrypted credentials.
+     */
+    public @NonNull byte[] getSourcePublicKey() {
+        return mSourcePublicKey;
+    }
+
+    /**
+     * Number of remaining attempts to verify credentials.
+     *
+     * <p>After correct guess counter is reset to {@code 5}.
+     */
+    public int getRemainingAttempts() {
+        return mRemainingAttempts;
+    }
+
+    @Override
+    public void writeToParcel(@NonNull Parcel out, int flags) {
+        out.writeInt(mLockscreenUiType);
+        out.writeByteArray(mSourcePublicKey);
+        out.writeInt(mRemainingAttempts);
+    }
+
+    private StartLockscreenValidationRequest() {
+    }
+
+    private StartLockscreenValidationRequest(Parcel in) {
+        mLockscreenUiType = in.readInt();
+        mSourcePublicKey = in.createByteArray();
+        mRemainingAttempts = in.readInt();
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+}
diff --git a/core/java/android/app/ambientcontext/IAmbientContextManager.aidl b/core/java/android/app/ambientcontext/IAmbientContextManager.aidl
index 8f06e76..a06bdd3 100644
--- a/core/java/android/app/ambientcontext/IAmbientContextManager.aidl
+++ b/core/java/android/app/ambientcontext/IAmbientContextManager.aidl
@@ -35,6 +35,7 @@
     void registerObserverWithCallback(in AmbientContextEventRequest request,
         String packageName,
         in IAmbientContextObserver observer);
+    @EnforcePermission("ACCESS_AMBIENT_CONTEXT_EVENT")
     void unregisterObserver(in String callingPackage);
     void queryServiceStatus(in int[] eventTypes, in String callingPackage,
         in RemoteCallback statusCallback);
diff --git a/core/java/android/attention/AttentionManagerInternal.java b/core/java/android/attention/AttentionManagerInternal.java
index 24fe0db..5d3889d 100644
--- a/core/java/android/attention/AttentionManagerInternal.java
+++ b/core/java/android/attention/AttentionManagerInternal.java
@@ -28,6 +28,11 @@
     public abstract boolean isAttentionServiceSupported();
 
     /**
+     * Returns {@code true} if proximity update is supported by the service.
+     */
+    public abstract boolean isProximitySupported();
+
+    /**
      * Checks whether user attention is at the screen and calls in the provided callback.
      *
      * @param timeoutMillis a budget for the attention check; if it takes longer - {@link
diff --git a/core/java/android/companion/virtual/VirtualDeviceManager.java b/core/java/android/companion/virtual/VirtualDeviceManager.java
index da6784b..8b6377a 100644
--- a/core/java/android/companion/virtual/VirtualDeviceManager.java
+++ b/core/java/android/companion/virtual/VirtualDeviceManager.java
@@ -669,7 +669,6 @@
          *   visibility is true.
          */
         @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE)
-        @NonNull
         public void setShowPointerIcon(boolean showPointerIcon) {
             mVirtualDeviceInternal.setShowPointerIcon(showPointerIcon);
         }
diff --git a/core/java/android/content/AttributionSource.java b/core/java/android/content/AttributionSource.java
index cd45f4d..193f623 100644
--- a/core/java/android/content/AttributionSource.java
+++ b/core/java/android/content/AttributionSource.java
@@ -662,7 +662,10 @@
 
         /**
          * The next app to receive the permission protected data.
+         *
+         * @deprecated Use {@link setNextAttributionSource} instead.
          */
+        @Deprecated
         public @NonNull Builder setNext(@Nullable AttributionSource value) {
             checkNotUsed();
             mBuilderFieldsSet |= 0x20;
@@ -671,6 +674,17 @@
             return this;
         }
 
+        /**
+         * The next app to receive the permission protected data.
+         */
+        public @NonNull Builder setNextAttributionSource(@NonNull AttributionSource value) {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x20;
+            mAttributionSourceState.next =
+                    new AttributionSourceState[]{value.mAttributionSourceState};
+            return this;
+        }
+
         /** Builds the instance. This builder should not be touched after calling this! */
         public @NonNull AttributionSource build() {
             checkNotUsed();
diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java
index 31c02b8..6255ad5 100644
--- a/core/java/android/content/ContentProvider.java
+++ b/core/java/android/content/ContentProvider.java
@@ -20,7 +20,7 @@
 import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
 import static android.os.Process.SYSTEM_UID;
 import static android.os.Process.myUserHandle;
-import static android.os.Trace.TRACE_TAG_DATABASE;
+import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER;
 
 import static com.android.internal.util.FrameworkStatsLog.GET_TYPE_ACCESSED_WITHOUT_PERMISSION;
 import static com.android.internal.util.FrameworkStatsLog.GET_TYPE_ACCESSED_WITHOUT_PERMISSION__LOCATION__PROVIDER_CHECK_URI_PERMISSION;
@@ -285,7 +285,7 @@
                 // Return an empty cursor for all columns.
                 return new MatrixCursor(cursor.getColumnNames(), 0);
             }
-            traceBegin(TRACE_TAG_DATABASE, "query: ", uri.getAuthority());
+            traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "query: ", uri.getAuthority());
             final AttributionSource original = setCallingAttributionSource(
                     attributionSource);
             try {
@@ -296,7 +296,7 @@
                 throw e.rethrowAsRuntimeException();
             } finally {
                 setCallingAttributionSource(original);
-                Trace.traceEnd(TRACE_TAG_DATABASE);
+                Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
             }
         }
 
@@ -304,7 +304,7 @@
         public String getType(AttributionSource attributionSource, Uri uri) {
             uri = validateIncomingUri(uri);
             uri = maybeGetUriWithoutUserId(uri);
-            traceBegin(TRACE_TAG_DATABASE, "getType: ", uri.getAuthority());
+            traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "getType: ", uri.getAuthority());
             final AttributionSource original = setCallingAttributionSource(
                     attributionSource);
             try {
@@ -348,7 +348,7 @@
                 throw e.rethrowAsRuntimeException();
             } finally {
                 setCallingAttributionSource(original);
-                Trace.traceEnd(TRACE_TAG_DATABASE);
+                Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
             }
         }
 
@@ -410,7 +410,7 @@
             // getCallingPackage() isn't available in getTypeAnonymous(), as the javadoc states.
             uri = validateIncomingUri(uri);
             uri = maybeGetUriWithoutUserId(uri);
-            traceBegin(TRACE_TAG_DATABASE, "getTypeAnonymous: ", uri.getAuthority());
+            traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "getTypeAnonymous: ", uri.getAuthority());
             final Bundle result = new Bundle();
             try {
                 result.putString(ContentResolver.REMOTE_CALLBACK_RESULT, getTypeAnonymous(uri));
@@ -419,7 +419,7 @@
                         new ParcelableException(e));
             } finally {
                 callback.sendResult(result);
-                Trace.traceEnd(TRACE_TAG_DATABASE);
+                Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
             }
         }
 
@@ -439,7 +439,7 @@
                     setCallingAttributionSource(original);
                 }
             }
-            traceBegin(TRACE_TAG_DATABASE, "insert: ", uri.getAuthority());
+            traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "insert: ", uri.getAuthority());
             final AttributionSource original = setCallingAttributionSource(
                     attributionSource);
             try {
@@ -448,7 +448,7 @@
                 throw e.rethrowAsRuntimeException();
             } finally {
                 setCallingAttributionSource(original);
-                Trace.traceEnd(TRACE_TAG_DATABASE);
+                Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
             }
         }
 
@@ -461,7 +461,7 @@
                     != PermissionChecker.PERMISSION_GRANTED) {
                 return 0;
             }
-            traceBegin(TRACE_TAG_DATABASE, "bulkInsert: ", uri.getAuthority());
+            traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "bulkInsert: ", uri.getAuthority());
             final AttributionSource original = setCallingAttributionSource(
                     attributionSource);
             try {
@@ -470,7 +470,7 @@
                 throw e.rethrowAsRuntimeException();
             } finally {
                 setCallingAttributionSource(original);
-                Trace.traceEnd(TRACE_TAG_DATABASE);
+                Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
             }
         }
 
@@ -507,7 +507,7 @@
                     }
                 }
             }
-            traceBegin(TRACE_TAG_DATABASE, "applyBatch: ", authority);
+            traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "applyBatch: ", authority);
             final AttributionSource original = setCallingAttributionSource(
                     attributionSource);
             try {
@@ -526,7 +526,7 @@
                 throw e.rethrowAsRuntimeException();
             } finally {
                 setCallingAttributionSource(original);
-                Trace.traceEnd(TRACE_TAG_DATABASE);
+                Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
             }
         }
 
@@ -539,7 +539,7 @@
                     != PermissionChecker.PERMISSION_GRANTED) {
                 return 0;
             }
-            traceBegin(TRACE_TAG_DATABASE, "delete: ", uri.getAuthority());
+            traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "delete: ", uri.getAuthority());
             final AttributionSource original = setCallingAttributionSource(
                     attributionSource);
             try {
@@ -548,7 +548,7 @@
                 throw e.rethrowAsRuntimeException();
             } finally {
                 setCallingAttributionSource(original);
-                Trace.traceEnd(TRACE_TAG_DATABASE);
+                Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
             }
         }
 
@@ -561,7 +561,7 @@
                     != PermissionChecker.PERMISSION_GRANTED) {
                 return 0;
             }
-            traceBegin(TRACE_TAG_DATABASE, "update: ", uri.getAuthority());
+            traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "update: ", uri.getAuthority());
             final AttributionSource original = setCallingAttributionSource(
                     attributionSource);
             try {
@@ -570,7 +570,7 @@
                 throw e.rethrowAsRuntimeException();
             } finally {
                 setCallingAttributionSource(original);
-                Trace.traceEnd(TRACE_TAG_DATABASE);
+                Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
             }
         }
 
@@ -581,7 +581,7 @@
             uri = validateIncomingUri(uri);
             uri = maybeGetUriWithoutUserId(uri);
             enforceFilePermission(attributionSource, uri, mode);
-            traceBegin(TRACE_TAG_DATABASE, "openFile: ", uri.getAuthority());
+            traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "openFile: ", uri.getAuthority());
             final AttributionSource original = setCallingAttributionSource(
                     attributionSource);
             try {
@@ -591,7 +591,7 @@
                 throw e.rethrowAsRuntimeException();
             } finally {
                 setCallingAttributionSource(original);
-                Trace.traceEnd(TRACE_TAG_DATABASE);
+                Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
             }
         }
 
@@ -602,7 +602,7 @@
             uri = validateIncomingUri(uri);
             uri = maybeGetUriWithoutUserId(uri);
             enforceFilePermission(attributionSource, uri, mode);
-            traceBegin(TRACE_TAG_DATABASE, "openAssetFile: ", uri.getAuthority());
+            traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "openAssetFile: ", uri.getAuthority());
             final AttributionSource original = setCallingAttributionSource(
                     attributionSource);
             try {
@@ -612,7 +612,7 @@
                 throw e.rethrowAsRuntimeException();
             } finally {
                 setCallingAttributionSource(original);
-                Trace.traceEnd(TRACE_TAG_DATABASE);
+                Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
             }
         }
 
@@ -621,7 +621,7 @@
                 String method, @Nullable String arg, @Nullable Bundle extras) {
             validateIncomingAuthority(authority);
             Bundle.setDefusable(extras, true);
-            traceBegin(TRACE_TAG_DATABASE, "call: ", authority);
+            traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "call: ", authority);
             final AttributionSource original = setCallingAttributionSource(
                     attributionSource);
             try {
@@ -630,7 +630,7 @@
                 throw e.rethrowAsRuntimeException();
             } finally {
                 setCallingAttributionSource(original);
-                Trace.traceEnd(TRACE_TAG_DATABASE);
+                Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
             }
         }
 
@@ -639,7 +639,7 @@
                 Uri uri, String mimeTypeFilter) {
             uri = validateIncomingUri(uri);
             uri = maybeGetUriWithoutUserId(uri);
-            traceBegin(TRACE_TAG_DATABASE, "getStreamTypes: ", uri.getAuthority());
+            traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "getStreamTypes: ", uri.getAuthority());
             final AttributionSource original = setCallingAttributionSource(
                     attributionSource);
             try {
@@ -648,7 +648,7 @@
                 throw e.rethrowAsRuntimeException();
             } finally {
                 setCallingAttributionSource(original);
-                Trace.traceEnd(TRACE_TAG_DATABASE);
+                Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
             }
         }
 
@@ -660,7 +660,7 @@
             uri = validateIncomingUri(uri);
             uri = maybeGetUriWithoutUserId(uri);
             enforceFilePermission(attributionSource, uri, "r");
-            traceBegin(TRACE_TAG_DATABASE, "openTypedAssetFile: ", uri.getAuthority());
+            traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "openTypedAssetFile: ", uri.getAuthority());
             final AttributionSource original = setCallingAttributionSource(
                     attributionSource);
             try {
@@ -670,7 +670,7 @@
                 throw e.rethrowAsRuntimeException();
             } finally {
                 setCallingAttributionSource(original);
-                Trace.traceEnd(TRACE_TAG_DATABASE);
+                Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
             }
         }
 
@@ -688,7 +688,7 @@
                     != PermissionChecker.PERMISSION_GRANTED) {
                 return null;
             }
-            traceBegin(TRACE_TAG_DATABASE, "canonicalize: ", uri.getAuthority());
+            traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "canonicalize: ", uri.getAuthority());
             final AttributionSource original = setCallingAttributionSource(
                     attributionSource);
             try {
@@ -697,7 +697,7 @@
                 throw e.rethrowAsRuntimeException();
             } finally {
                 setCallingAttributionSource(original);
-                Trace.traceEnd(TRACE_TAG_DATABASE);
+                Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
             }
         }
 
@@ -724,7 +724,7 @@
                     != PermissionChecker.PERMISSION_GRANTED) {
                 return null;
             }
-            traceBegin(TRACE_TAG_DATABASE, "uncanonicalize: ", uri.getAuthority());
+            traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "uncanonicalize: ", uri.getAuthority());
             final AttributionSource original = setCallingAttributionSource(
                     attributionSource);
             try {
@@ -733,7 +733,7 @@
                 throw e.rethrowAsRuntimeException();
             } finally {
                 setCallingAttributionSource(original);
-                Trace.traceEnd(TRACE_TAG_DATABASE);
+                Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
             }
         }
 
@@ -760,7 +760,7 @@
                     != PermissionChecker.PERMISSION_GRANTED) {
                 return false;
             }
-            traceBegin(TRACE_TAG_DATABASE, "refresh: ", uri.getAuthority());
+            traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "refresh: ", uri.getAuthority());
             final AttributionSource original = setCallingAttributionSource(
                     attributionSource);
             try {
@@ -768,7 +768,7 @@
                         CancellationSignal.fromTransport(cancellationSignal));
             } finally {
                 setCallingAttributionSource(original);
-                Trace.traceEnd(TRACE_TAG_DATABASE);
+                Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
             }
         }
 
@@ -777,7 +777,7 @@
                 int uid, int modeFlags) {
             uri = validateIncomingUri(uri);
             uri = maybeGetUriWithoutUserId(uri);
-            traceBegin(TRACE_TAG_DATABASE, "checkUriPermission: ", uri.getAuthority());
+            traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "checkUriPermission: ", uri.getAuthority());
             final AttributionSource original = setCallingAttributionSource(
                     attributionSource);
             try {
@@ -786,7 +786,7 @@
                 throw e.rethrowAsRuntimeException();
             } finally {
                 setCallingAttributionSource(original);
-                Trace.traceEnd(TRACE_TAG_DATABASE);
+                Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
             }
         }
 
diff --git a/core/java/android/content/IClipboard.aidl b/core/java/android/content/IClipboard.aidl
index fe7798f..e0fba1d 100644
--- a/core/java/android/content/IClipboard.aidl
+++ b/core/java/android/content/IClipboard.aidl
@@ -28,6 +28,7 @@
 interface IClipboard {
     void setPrimaryClip(in ClipData clip, String callingPackage, String attributionTag, int userId,
             int deviceId);
+    @EnforcePermission("SET_CLIP_SOURCE")
     void setPrimaryClipAsPackage(in ClipData clip, String callingPackage, String attributionTag,
             int userId, int deviceId, String sourcePackage);
     void clearPrimaryClip(String callingPackage, String attributionTag, int userId, int deviceId);
@@ -46,6 +47,7 @@
     boolean hasClipboardText(String callingPackage, String attributionTag, int userId,
             int deviceId);
 
+    @EnforcePermission("SET_CLIP_SOURCE")
     String getPrimaryClipSource(String callingPackage, String attributionTag, int userId,
             int deviceId);
 
diff --git a/core/java/android/content/IContentService.aidl b/core/java/android/content/IContentService.aidl
index 127466d..0d11c78 100644
--- a/core/java/android/content/IContentService.aidl
+++ b/core/java/android/content/IContentService.aidl
@@ -160,6 +160,7 @@
      * @param cname component to identify sync service, must be null if account/providerName are
      * non-null.
      */
+    @EnforcePermission("READ_SYNC_STATS")
     @UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553)
     boolean isSyncActive(in Account account, String authority, in ComponentName cname);
 
@@ -183,6 +184,7 @@
      * non-null.
      */
     boolean isSyncPending(in Account account, String authority, in ComponentName cname);
+    @EnforcePermission("READ_SYNC_STATS")
     boolean isSyncPendingAsUser(in Account account, String authority, in ComponentName cname,
             int userId);
 
diff --git a/core/java/android/content/SharedPreferences.java b/core/java/android/content/SharedPreferences.java
index de6dc22..5e5d4181 100644
--- a/core/java/android/content/SharedPreferences.java
+++ b/core/java/android/content/SharedPreferences.java
@@ -30,10 +30,27 @@
  * when they are committed to storage.  Objects that are returned from the
  * various <code>get</code> methods must be treated as immutable by the application.
  *
- * <p>Note: This class provides strong consistency guarantees. It is using expensive operations
- * which might slow down an app. Frequently changing properties or properties where loss can be
- * tolerated should use other mechanisms. For more details read the comments on
- * {@link Editor#commit()} and {@link Editor#apply()}.
+ * <p>SharedPreferences is best suited to storing data about how the user prefers
+ * to experience the app, for example, whether the user prefers a particular UI theme
+ * or whether they prefer viewing particular content in a list vs. a grid. To this end,
+ * SharedPreferences reflects changes {@link Editor#commit() committed} or
+ * {@link Editor#apply() applied} by {@link Editor}s <em>immediately</em>, potentially
+ * before those changes are durably persisted.
+ * Under some circumstances such as app crashes or termination these changes may be lost,
+ * even if an {@link OnSharedPreferenceChangeListener} reported the change was successful.
+ * SharedPreferences is not recommended for storing data that is sensitive to this
+ * kind of rollback to a prior state such as user security or privacy settings.
+ * For other high-level data persistence options, see
+ * <a href="https://d.android.com/room">Room</a> or
+ * <a href="https://d.android.com/datastore">DataStore</a>.
+ *
+ * <p><em>Note:</em> Common implementations guarantee that outstanding edits to preference
+ * files are persisted to disk when host Activities become stopped. In some situations
+ * (e.g. performing many {@link Editor#commit()} or {@link Editor#apply()}
+ * operations just prior to navigating away from the host Activity) this can lead
+ * to blocking the main thread during lifecycle transition events and associated
+ * ANR errors. For more details see the documentation for {@link Editor#commit()} and
+ * {@link Editor#apply()}.
  *
  * <p><em>Note: This class does not support use across multiple processes.</em>
  *
diff --git a/core/java/android/content/pm/IPackageInstaller.aidl b/core/java/android/content/pm/IPackageInstaller.aidl
index e3016a4..ebe2aa3 100644
--- a/core/java/android/content/pm/IPackageInstaller.aidl
+++ b/core/java/android/content/pm/IPackageInstaller.aidl
@@ -59,6 +59,7 @@
     void installExistingPackage(String packageName, int installFlags, int installReason,
             in IntentSender statusReceiver, int userId, in List<String> whiteListedPermissions);
 
+    @EnforcePermission("INSTALL_PACKAGES")
     void setPermissionsResult(int sessionId, boolean accepted);
 
     void bypassNextStagedInstallerCheck(boolean value);
diff --git a/core/java/android/content/pm/IPackageInstallerSession.aidl b/core/java/android/content/pm/IPackageInstallerSession.aidl
index 081f263..ea69a2b 100644
--- a/core/java/android/content/pm/IPackageInstallerSession.aidl
+++ b/core/java/android/content/pm/IPackageInstallerSession.aidl
@@ -49,8 +49,11 @@
     void seal();
     List<String> fetchPackageNames();
 
+    @EnforcePermission("USE_INSTALLER_V2")
     DataLoaderParamsParcel getDataLoaderParams();
+    @EnforcePermission("USE_INSTALLER_V2")
     void addFile(int location, String name, long lengthBytes, in byte[] metadata, in byte[] signature);
+    @EnforcePermission("USE_INSTALLER_V2")
     void removeFile(int location, String name);
 
     boolean isMultiPackage();
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 1ba84c5..1134110 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -159,6 +159,7 @@
      */
     ParceledListSlice getInstalledPackages(long flags, in int userId);
 
+    @EnforcePermission("GET_APP_METADATA")
     @nullable ParcelFileDescriptor getAppMetadataFd(String packageName,
                 int userId);
 
@@ -282,9 +283,11 @@
     void addCrossProfileIntentFilter(in IntentFilter intentFilter, String ownerPackage,
             int sourceUserId, int targetUserId, int flags);
 
+    @EnforcePermission("INTERACT_ACROSS_USERS_FULL")
     boolean removeCrossProfileIntentFilter(in IntentFilter intentFilter, String ownerPackage,
                 int sourceUserId, int targetUserId, int flags);
 
+    @EnforcePermission("INTERACT_ACROSS_USERS_FULL")
     void clearCrossProfileIntentFilters(int sourceUserId, String ownerPackage);
 
     String[] setDistractingPackageRestrictionsAsUser(in String[] packageNames, int restrictionFlags,
@@ -417,6 +420,7 @@
      * @param observer call back used to notify when
      * the operation is completed
      */
+     @EnforcePermission("CLEAR_APP_CACHE")
      void freeStorageAndNotify(in String volumeUuid, in long freeStorageSize,
              int storageFlags, IPackageDataObserver observer);
 
@@ -441,6 +445,7 @@
      * notify when the operation is completed.May be null
      * to indicate that no call back is desired.
      */
+     @EnforcePermission("CLEAR_APP_CACHE")
      void freeStorage(in String volumeUuid, in long freeStorageSize,
              int storageFlags, in IntentSender pi);
 
@@ -468,6 +473,7 @@
      * files need to be deleted
      * @param observer a callback used to notify when the operation is completed.
      */
+    @EnforcePermission("CLEAR_APP_USER_DATA")
     void clearApplicationUserData(in String packageName, IPackageDataObserver observer, int userId);
 
     /**
@@ -577,14 +583,20 @@
     boolean performDexOptSecondary(String packageName,
             String targetCompilerFilter, boolean force);
 
+    @EnforcePermission("MOUNT_UNMOUNT_FILESYSTEMS")
     int getMoveStatus(int moveId);
 
+    @EnforcePermission("MOUNT_UNMOUNT_FILESYSTEMS")
     void registerMoveCallback(in IPackageMoveObserver callback);
+    @EnforcePermission("MOUNT_UNMOUNT_FILESYSTEMS")
     void unregisterMoveCallback(in IPackageMoveObserver callback);
 
+    @EnforcePermission("MOVE_PACKAGE")
     int movePackage(in String packageName, in String volumeUuid);
+    @EnforcePermission("MOVE_PACKAGE")
     int movePrimaryStorage(in String volumeUuid);
 
+    @EnforcePermission("WRITE_SECURE_SETTINGS")
     boolean setInstallLocation(int loc);
     @UnsupportedAppUsage
     int getInstallLocation();
@@ -605,6 +617,7 @@
     ParceledListSlice getIntentFilterVerifications(String packageName);
     ParceledListSlice getAllIntentFilters(String packageName);
 
+    @EnforcePermission("PACKAGE_VERIFICATION_AGENT")
     VerifierDeviceIdentity getVerifierDeviceIdentity();
 
     boolean isFirstBoot();
@@ -614,6 +627,7 @@
     @UnsupportedAppUsage
     boolean isStorageLow();
 
+    @EnforcePermission("MANAGE_USERS")
     @UnsupportedAppUsage
     boolean setApplicationHiddenSettingAsUser(String packageName, boolean hidden, int userId);
     boolean getApplicationHiddenSettingAsUser(String packageName, int userId);
@@ -624,6 +638,7 @@
     @UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553)
     IPackageInstaller getPackageInstaller();
 
+    @EnforcePermission("DELETE_PACKAGES")
     boolean setBlockUninstallForUser(String packageName, boolean blockUninstall, int userId);
     @UnsupportedAppUsage
     boolean getBlockUninstallForUser(String packageName, int userId);
@@ -649,6 +664,7 @@
      * Sets whether or not an update is available. Ostensibly for instant apps
      * to force exteranl resolution.
      */
+    @EnforcePermission("INSTALL_PACKAGES")
     void setUpdateAvailable(String packageName, boolean updateAvaialble);
 
     @UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553)
@@ -676,6 +692,7 @@
 
     ComponentName getInstantAppInstallerComponent();
 
+    @EnforcePermission("ACCESS_INSTANT_APPS")
     String getInstantAppAndroidId(String packageName, int userId);
 
     IArtManager getArtManager();
@@ -774,6 +791,7 @@
 
     void makeProviderVisible(int recipientAppId, String visibleAuthority);
 
+    @EnforcePermission("MAKE_UID_VISIBLE")
     @JavaPassthrough(annotation = "@android.annotation.RequiresPermission(android.Manifest"
             + ".permission.MAKE_UID_VISIBLE)")
     void makeUidVisible(int recipientAppId, int visibleUid);
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index cb988df..77d32a5 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -334,17 +334,6 @@
     public static final String EXTRA_DATA_LOADER_TYPE = "android.content.pm.extra.DATA_LOADER_TYPE";
 
     /**
-     * Path to the validated base APK for this session, which may point at an
-     * APK inside the session (when the session defines the base), or it may
-     * point at the existing base APK (when adding splits to an existing app).
-     *
-     * @hide
-     */
-    @SystemApi
-    public static final String EXTRA_RESOLVED_BASE_PATH =
-            "android.content.pm.extra.RESOLVED_BASE_PATH";
-
-    /**
      * Streaming installation pending.
      * Caller should make sure DataLoader is able to prepare image and reinitiate the operation.
      *
@@ -3550,6 +3539,19 @@
         }
 
         /**
+         * @return the path to the validated base APK for this session, which may point at an
+         * APK inside the session (when the session defines the base), or it may
+         * point at the existing base APK (when adding splits to an existing app).
+         *
+         * @hide
+         */
+        @SystemApi
+        @RequiresPermission(Manifest.permission.READ_INSTALLED_SESSION_PATHS)
+        public @Nullable String getResolvedBaseApkPath() {
+            return resolvedBaseCodePath;
+        }
+
+        /**
          * Get the value set in {@link SessionParams#setGrantedRuntimePermissions(String[])}.
          *
          * @hide
diff --git a/core/java/android/content/res/AssetFileDescriptor.java b/core/java/android/content/res/AssetFileDescriptor.java
index d2a6f03..ac65933 100644
--- a/core/java/android/content/res/AssetFileDescriptor.java
+++ b/core/java/android/content/res/AssetFileDescriptor.java
@@ -21,20 +21,12 @@
 import android.os.Parcel;
 import android.os.ParcelFileDescriptor;
 import android.os.Parcelable;
-import android.system.ErrnoException;
-import android.system.Os;
 
 import java.io.Closeable;
 import java.io.FileDescriptor;
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
 import java.io.IOException;
-import java.nio.ByteBuffer;
-import java.nio.MappedByteBuffer;
-import java.nio.channels.FileChannel;
-import java.nio.channels.FileLock;
-import java.nio.channels.ReadableByteChannel;
-import java.nio.channels.WritableByteChannel;
 
 /**
  * File descriptor of an entry in the AssetManager.  This provides your own
@@ -211,26 +203,19 @@
      */
     public static class AutoCloseInputStream
             extends ParcelFileDescriptor.AutoCloseInputStream {
-        /** Size of current file. */
-        private long mTotalSize;
-        /** The absolute position of current file start point. */
-        private final long mFileOffset;
-        /** The relative position where input stream is against mFileOffset. */
-        private long mOffset;
-        private OffsetCorrectFileChannel mOffsetCorrectFileChannel;
+        private long mRemaining;
 
         public AutoCloseInputStream(AssetFileDescriptor fd) throws IOException {
             super(fd.getParcelFileDescriptor());
-            mTotalSize = fd.getLength();
-            mFileOffset = fd.getStartOffset();
+            super.skip(fd.getStartOffset());
+            mRemaining = (int) fd.getLength();
         }
 
         @Override
         public int available() throws IOException {
-            long available = mTotalSize - mOffset;
-            return available >= 0
-                    ? (available < 0x7fffffff ? (int) available : 0x7fffffff)
-                    : 0;
+            return mRemaining >= 0
+                    ? (mRemaining < 0x7fffffff ? (int) mRemaining : 0x7fffffff)
+                    : super.available();
         }
 
         @Override
@@ -242,24 +227,15 @@
 
         @Override
         public int read(byte[] buffer, int offset, int count) throws IOException {
-            int available = available();
-            if (available <= 0) {
-                return -1;
+            if (mRemaining >= 0) {
+                if (mRemaining == 0) return -1;
+                if (count > mRemaining) count = (int) mRemaining;
+                int res = super.read(buffer, offset, count);
+                if (res >= 0) mRemaining -= res;
+                return res;
             }
 
-            if (count > available) count = available;
-            try {
-                int res = Os.pread(getFD(), buffer, offset, count, mFileOffset + mOffset);
-                // pread returns 0 at end of file, while java's InputStream interface requires -1
-                if (res == 0) res = -1;
-                if (res > 0) {
-                    mOffset += res;
-                    updateChannelPosition(mOffset + mFileOffset);
-                }
-                return res;
-            } catch (ErrnoException e) {
-                throw new IOException(e);
-            }
+            return super.read(buffer, offset, count);
         }
 
         @Override
@@ -269,185 +245,41 @@
 
         @Override
         public long skip(long count) throws IOException {
-            int available = available();
-            if (available <= 0) {
-                return -1;
+            if (mRemaining >= 0) {
+                if (mRemaining == 0) return -1;
+                if (count > mRemaining) count = mRemaining;
+                long res = super.skip(count);
+                if (res >= 0) mRemaining -= res;
+                return res;
             }
 
-            if (count > available) count = available;
-            mOffset += count;
-            updateChannelPosition(mOffset + mFileOffset);
-            return count;
+            return super.skip(count);
         }
 
         @Override
         public void mark(int readlimit) {
-            // Not supported.
-            return;
+            if (mRemaining >= 0) {
+                // Not supported.
+                return;
+            }
+            super.mark(readlimit);
         }
 
         @Override
         public boolean markSupported() {
-            return false;
+            if (mRemaining >= 0) {
+                return false;
+            }
+            return super.markSupported();
         }
 
         @Override
         public synchronized void reset() throws IOException {
-            // Not supported.
-            return;
-        }
-
-        @Override
-        public FileChannel getChannel() {
-            if (mOffsetCorrectFileChannel == null) {
-                mOffsetCorrectFileChannel = new OffsetCorrectFileChannel(super.getChannel());
+            if (mRemaining >= 0) {
+                // Not supported.
+                return;
             }
-            try {
-                updateChannelPosition(mOffset + mFileOffset);
-            } catch (IOException e) {
-                throw new RuntimeException(e);
-            }
-            return mOffsetCorrectFileChannel;
-        }
-
-        /**
-         * Update the position of mOffsetCorrectFileChannel only after it is constructed.
-         *
-         * @param newPosition The absolute position mOffsetCorrectFileChannel needs to be moved to.
-         */
-        private void updateChannelPosition(long newPosition) throws IOException {
-            if (mOffsetCorrectFileChannel != null) {
-                mOffsetCorrectFileChannel.position(newPosition);
-            }
-        }
-
-        /**
-         * A FileChannel wrapper that will update mOffset of the AutoCloseInputStream
-         * to correct position when using FileChannel to read. All occurrence of position
-         * should be using absolute solution and each override method just do Delegation
-         * besides additional check. All methods related to write mode have been disabled
-         * and will throw UnsupportedOperationException with customized message.
-         */
-        private class OffsetCorrectFileChannel extends FileChannel {
-            private final FileChannel mDelegate;
-            private static final String METHOD_NOT_SUPPORTED_MESSAGE =
-                    "This Method is not supported in AutoCloseInputStream FileChannel.";
-
-            OffsetCorrectFileChannel(FileChannel fc) {
-                mDelegate = fc;
-            }
-
-            @Override
-            public int read(ByteBuffer dst) throws IOException {
-                if (available() <= 0) return -1;
-                int bytesRead = mDelegate.read(dst);
-                if (bytesRead != -1) mOffset += bytesRead;
-                return bytesRead;
-            }
-
-            @Override
-            public long read(ByteBuffer[] dsts, int offset, int length) throws IOException {
-                if (available() <= 0) return -1;
-                if (mOffset + length > mTotalSize) {
-                    length = (int) (mTotalSize - mOffset);
-                }
-                long bytesRead = mDelegate.read(dsts, offset, length);
-                if (bytesRead != -1) mOffset += bytesRead;
-                return bytesRead;
-            }
-
-            @Override
-            /**The only read method that does not move channel position*/
-            public int read(ByteBuffer dst, long position) throws IOException {
-                if (position - mFileOffset > mTotalSize) return -1;
-                return mDelegate.read(dst, position);
-            }
-
-            @Override
-            public long position() throws IOException {
-                return mDelegate.position();
-            }
-
-            @Override
-            public FileChannel position(long newPosition) throws IOException {
-                mOffset = newPosition - mFileOffset;
-                return mDelegate.position(newPosition);
-            }
-
-            @Override
-            public long size() throws IOException {
-                return mTotalSize;
-            }
-
-            @Override
-            public long transferTo(long position, long count, WritableByteChannel target)
-                    throws IOException {
-                if (position - mFileOffset > mTotalSize) {
-                    return 0;
-                }
-                if (position - mFileOffset + count > mTotalSize) {
-                    count = mTotalSize - (position - mFileOffset);
-                }
-                return mDelegate.transferTo(position, count, target);
-            }
-
-            @Override
-            public MappedByteBuffer map(MapMode mode, long position, long size) throws IOException {
-                if (position - mFileOffset > mTotalSize) {
-                    throw new IOException(
-                            "Cannot map to buffer because position exceed current file size.");
-                }
-                if (position - mFileOffset + size > mTotalSize) {
-                    size = mTotalSize - (position - mFileOffset);
-                }
-                return mDelegate.map(mode, position, size);
-            }
-
-            @Override
-            protected void implCloseChannel() throws IOException {
-                mDelegate.close();
-            }
-
-            @Override
-            public int write(ByteBuffer src) throws IOException {
-                throw new UnsupportedOperationException(METHOD_NOT_SUPPORTED_MESSAGE);
-            }
-
-            @Override
-            public long write(ByteBuffer[] srcs, int offset, int length) throws IOException {
-                throw new UnsupportedOperationException(METHOD_NOT_SUPPORTED_MESSAGE);
-            }
-
-            @Override
-            public int write(ByteBuffer src, long position) throws IOException {
-                throw new UnsupportedOperationException(METHOD_NOT_SUPPORTED_MESSAGE);
-            }
-
-            @Override
-            public long transferFrom(ReadableByteChannel src, long position, long count)
-                    throws IOException {
-                throw new UnsupportedOperationException(METHOD_NOT_SUPPORTED_MESSAGE);
-            }
-
-            @Override
-            public FileChannel truncate(long size) throws IOException {
-                throw new UnsupportedOperationException(METHOD_NOT_SUPPORTED_MESSAGE);
-            }
-
-            @Override
-            public void force(boolean metaData) throws IOException {
-                throw new UnsupportedOperationException(METHOD_NOT_SUPPORTED_MESSAGE);
-            }
-
-            @Override
-            public FileLock lock(long position, long size, boolean shared) throws IOException {
-                throw new UnsupportedOperationException(METHOD_NOT_SUPPORTED_MESSAGE);
-            }
-
-            @Override
-            public FileLock tryLock(long position, long size, boolean shared) throws IOException {
-                throw new UnsupportedOperationException(METHOD_NOT_SUPPORTED_MESSAGE);
-            }
+            super.reset();
         }
     }
 
diff --git a/core/java/android/content/res/AssetManager.java b/core/java/android/content/res/AssetManager.java
index ef3842a..0f284f4 100644
--- a/core/java/android/content/res/AssetManager.java
+++ b/core/java/android/content/res/AssetManager.java
@@ -528,6 +528,10 @@
         if (!mOpen) {
             throw new RuntimeException("AssetManager has been closed");
         }
+        // Let's still check if the native object exists, given all the memory corruptions.
+        if (mObject == 0) {
+            throw new RuntimeException("AssetManager is open but the native object is gone");
+        }
     }
 
     /**
@@ -1153,6 +1157,7 @@
     int[] getAttributeResolutionStack(long themePtr, @AttrRes int defStyleAttr,
             @StyleRes int defStyleRes, @StyleRes int xmlStyle) {
         synchronized (this) {
+            ensureValidLocked();
             return nativeAttributeResolutionStack(
                     mObject, themePtr, xmlStyle, defStyleAttr, defStyleRes);
         }
diff --git a/core/java/android/content/res/StringBlock.java b/core/java/android/content/res/StringBlock.java
index 6c07356..c143acb 100644
--- a/core/java/android/content/res/StringBlock.java
+++ b/core/java/android/content/res/StringBlock.java
@@ -62,7 +62,7 @@
     private static final String TAG = "AssetManager";
     private static final boolean localLOGV = false;
 
-    private final long mNative;
+    private long mNative;   // final, but gets modified when closed
     private final boolean mUseSparse;
     private final boolean mOwnsNative;
 
@@ -207,6 +207,7 @@
                 if (mOwnsNative) {
                     nativeDestroy(mNative);
                 }
+                mNative = 0;
             }
         }
     }
diff --git a/core/java/android/content/res/XmlBlock.java b/core/java/android/content/res/XmlBlock.java
index 3915a6c..16fd1f7 100644
--- a/core/java/android/content/res/XmlBlock.java
+++ b/core/java/android/content/res/XmlBlock.java
@@ -73,7 +73,9 @@
     private void decOpenCountLocked() {
         mOpenCount--;
         if (mOpenCount == 0) {
+            mStrings.close();
             nativeDestroy(mNative);
+            mNative = 0;
             if (mAssets != null) {
                 mAssets.xmlBlockGone(hashCode());
             }
@@ -621,7 +623,7 @@
     }
 
     private @Nullable final AssetManager mAssets;
-    private final long mNative;
+    private long mNative;   // final, but gets reset on close
     /*package*/ final StringBlock mStrings;
     private boolean mOpen = true;
     private int mOpenCount = 1;
diff --git a/core/java/android/credentials/CredentialProviderInfo.java b/core/java/android/credentials/CredentialProviderInfo.java
index c224f01..c4f8b08 100644
--- a/core/java/android/credentials/CredentialProviderInfo.java
+++ b/core/java/android/credentials/CredentialProviderInfo.java
@@ -29,9 +29,7 @@
 
 import java.util.ArrayList;
 import java.util.Collections;
-import java.util.HashSet;
 import java.util.List;
-import java.util.Set;
 
 /**
  * {@link ServiceInfo} and meta-data about a credential provider.
@@ -41,7 +39,7 @@
 @TestApi
 public final class CredentialProviderInfo implements Parcelable {
     @NonNull private final ServiceInfo mServiceInfo;
-    @NonNull private final Set<String> mCapabilities = new HashSet<>();
+    @NonNull private final List<String> mCapabilities = new ArrayList<>();
     @Nullable private final CharSequence mOverrideLabel;
     @Nullable private CharSequence mSettingsSubtitle = null;
     private final boolean mIsSystemProvider;
@@ -96,11 +94,7 @@
     /** Returns a list of capabilities this provider service can support. */
     @NonNull
     public List<String> getCapabilities() {
-        List<String> capabilities = new ArrayList<>();
-        for (String capability : mCapabilities) {
-            capabilities.add(capability);
-        }
-        return Collections.unmodifiableList(capabilities);
+        return Collections.unmodifiableList(mCapabilities);
     }
 
     /** Returns whether the provider is enabled by the user. */
@@ -124,12 +118,10 @@
     public void writeToParcel(@NonNull Parcel dest, int flags) {
         dest.writeTypedObject(mServiceInfo, flags);
         dest.writeBoolean(mIsSystemProvider);
+        dest.writeStringList(mCapabilities);
         dest.writeBoolean(mIsEnabled);
         TextUtils.writeToParcel(mOverrideLabel, dest, flags);
         TextUtils.writeToParcel(mSettingsSubtitle, dest, flags);
-
-        List<String> capabilities = getCapabilities();
-        dest.writeStringList(capabilities);
     }
 
     @Override
@@ -163,13 +155,10 @@
     private CredentialProviderInfo(@NonNull Parcel in) {
         mServiceInfo = in.readTypedObject(ServiceInfo.CREATOR);
         mIsSystemProvider = in.readBoolean();
+        in.readStringList(mCapabilities);
         mIsEnabled = in.readBoolean();
         mOverrideLabel = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
         mSettingsSubtitle = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
-
-        List<String> capabilities = new ArrayList<>();
-        in.readStringList(capabilities);
-        mCapabilities.addAll(capabilities);
     }
 
     public static final @NonNull Parcelable.Creator<CredentialProviderInfo> CREATOR =
@@ -189,7 +178,7 @@
     public static final class Builder {
 
         @NonNull private ServiceInfo mServiceInfo;
-        @NonNull private Set<String> mCapabilities = new HashSet<>();
+        @NonNull private List<String> mCapabilities = new ArrayList<>();
         private boolean mIsSystemProvider = false;
         @Nullable private CharSequence mSettingsSubtitle = null;
         private boolean mIsEnabled = false;
@@ -232,16 +221,6 @@
             return this;
         }
 
-        /**
-         * Sets a list of capabilities this provider service can support.
-         *
-         * @hide
-         */
-        public @NonNull Builder addCapabilities(@NonNull Set<String> capabilities) {
-            mCapabilities.addAll(capabilities);
-            return this;
-        }
-
         /** Sets whether it is enabled by the user. */
         public @NonNull Builder setEnabled(boolean isEnabled) {
             mIsEnabled = isEnabled;
diff --git a/core/java/android/database/sqlite/SQLiteDatabase.java b/core/java/android/database/sqlite/SQLiteDatabase.java
index c08294f..87fc8c4 100644
--- a/core/java/android/database/sqlite/SQLiteDatabase.java
+++ b/core/java/android/database/sqlite/SQLiteDatabase.java
@@ -675,6 +675,30 @@
     }
 
     /**
+     * Begins a transaction in DEFERRED mode.
+     * <p>
+     * Transactions can be nested. When the outer transaction is ended all of the work done in
+     * that transaction and all of the nested transactions will be committed or rolled back. The
+     * changes will be rolled back if any transaction is ended without being marked as clean (by
+     * calling setTransactionSuccessful). Otherwise they will be committed.
+     * <p>
+     * Here is the standard idiom for transactions:
+     *
+     * <pre>
+     *   db.beginTransactionDeferred();
+     *   try {
+     *     ...
+     *     db.setTransactionSuccessful();
+     *   } finally {
+     *     db.endTransaction();
+     *   }
+     * </pre>
+     */
+    public void beginTransactionDeferred() {
+        beginTransactionWithListenerDeferred(null);
+    }
+
+    /**
      * Begins a transaction in EXCLUSIVE mode.
      * <p>
      * Transactions can be nested.
@@ -699,7 +723,8 @@
      * commits, or is rolled back, either explicitly or by a call to
      * {@link #yieldIfContendedSafely}.
      */
-    public void beginTransactionWithListener(SQLiteTransactionListener transactionListener) {
+    public void beginTransactionWithListener(
+            @Nullable SQLiteTransactionListener transactionListener) {
         beginTransaction(transactionListener, true);
     }
 
@@ -728,19 +753,53 @@
      *            explicitly or by a call to {@link #yieldIfContendedSafely}.
      */
     public void beginTransactionWithListenerNonExclusive(
-            SQLiteTransactionListener transactionListener) {
+            @Nullable SQLiteTransactionListener transactionListener) {
         beginTransaction(transactionListener, false);
     }
 
+    /**
+     * Begins a transaction in DEFERRED mode.
+     * <p>
+     * Transactions can be nested. When the outer transaction is ended all of the work done in
+     * that transaction and all of the nested transactions will be committed or rolled back. The
+     * changes will be rolled back if any transaction is ended without being marked as clean (by
+     * calling setTransactionSuccessful). Otherwise they will be committed.
+     * <p>
+     * Here is the standard idiom for transactions:
+     *
+     * <pre>
+     *   db.beginTransactionDeferred();
+     *   try {
+     *     ...
+     *     db.setTransactionSuccessful();
+     *   } finally {
+     *     db.endTransaction();
+     *   }
+     * </pre>
+     */
+    public void beginTransactionWithListenerDeferred(
+            @Nullable SQLiteTransactionListener transactionListener) {
+        beginTransaction(transactionListener, SQLiteSession.TRANSACTION_MODE_DEFERRED);
+    }
+
     @UnsupportedAppUsage
     private void beginTransaction(SQLiteTransactionListener transactionListener,
             boolean exclusive) {
+        beginTransaction(transactionListener,
+                exclusive ? SQLiteSession.TRANSACTION_MODE_EXCLUSIVE :
+                SQLiteSession.TRANSACTION_MODE_IMMEDIATE);
+    }
+
+    /**
+     * Begin a transaction with the specified mode.  Valid modes are
+     * {@link SquLiteSession.TRANSACTION_MODE_DEFERRED},
+     * {@link SquLiteSession.TRANSACTION_MODE_IMMEDIATE}, and
+     * {@link SquLiteSession.TRANSACTION_MODE_EXCLUSIVE}.
+     */
+    private void beginTransaction(@Nullable SQLiteTransactionListener listener, int mode) {
         acquireReference();
         try {
-            getThreadSession().beginTransaction(
-                    exclusive ? SQLiteSession.TRANSACTION_MODE_EXCLUSIVE :
-                            SQLiteSession.TRANSACTION_MODE_IMMEDIATE,
-                    transactionListener,
+            getThreadSession().beginTransaction(mode, listener,
                     getThreadDefaultConnectionFlags(false /*readOnly*/), null);
         } finally {
             releaseReference();
@@ -3113,4 +3172,3 @@
         ContentResolver.onDbCorruption(tag, message, stacktrace);
     }
 }
-
diff --git a/core/java/android/database/sqlite/SQLiteSession.java b/core/java/android/database/sqlite/SQLiteSession.java
index 24b62b8..8811dd4 100644
--- a/core/java/android/database/sqlite/SQLiteSession.java
+++ b/core/java/android/database/sqlite/SQLiteSession.java
@@ -325,7 +325,12 @@
                         mConnection.execute("BEGIN EXCLUSIVE;", null,
                                 cancellationSignal); // might throw
                         break;
+                    case TRANSACTION_MODE_DEFERRED:
+                        mConnection.execute("BEGIN DEFERRED;", null,
+                                cancellationSignal); // might throw
+                        break;
                     default:
+                        // Per SQLite documentation, this executes in DEFERRED mode.
                         mConnection.execute("BEGIN;", null, cancellationSignal); // might throw
                         break;
                 }
diff --git a/core/java/android/ddm/DdmHandleHello.java b/core/java/android/ddm/DdmHandleHello.java
index 4160029..a51a740 100644
--- a/core/java/android/ddm/DdmHandleHello.java
+++ b/core/java/android/ddm/DdmHandleHello.java
@@ -16,6 +16,7 @@
 
 package android.ddm;
 
+import android.os.DdmSyncState;
 import android.os.Debug;
 import android.os.UserHandle;
 import android.util.Log;
@@ -44,6 +45,7 @@
     private static final String[] FRAMEWORK_FEATURES = new String[] {
         "opengl-tracing",
         "view-hierarchy",
+        "support_boot_stages"
     };
 
     /* singleton, do not instantiate */
@@ -145,7 +147,9 @@
                             + instructionSetDescription.length() * 2
                             + vmFlags.length() * 2
                             + 1
-                            + pkgName.length() * 2);
+                            + pkgName.length() * 2
+                            // STAG id (int)
+                            + Integer.BYTES);
         out.order(ChunkHandler.CHUNK_ORDER);
         out.putInt(CLIENT_PROTOCOL_VERSION);
         out.putInt(android.os.Process.myPid());
@@ -162,6 +166,10 @@
         out.putInt(pkgName.length());
         putString(out, pkgName);
 
+        // Added API 34 (and advertised via FEAT ddm packet)
+        // Send the current boot stage in ActivityThread
+        out.putInt(DdmSyncState.getStage().toInt());
+
         Chunk reply = new Chunk(CHUNK_HELO, out);
 
         /*
diff --git a/core/java/android/hardware/HardwareBuffer.java b/core/java/android/hardware/HardwareBuffer.java
index ddbfb9e..889a43c 100644
--- a/core/java/android/hardware/HardwareBuffer.java
+++ b/core/java/android/hardware/HardwareBuffer.java
@@ -40,7 +40,7 @@
  * HardwareBuffer wraps a native <code>AHardwareBuffer</code> object, which is a low-level object
  * representing a memory buffer accessible by various hardware units. HardwareBuffer allows sharing
  * buffers across different application processes. In particular, HardwareBuffers may be mappable
- * to memory accessibly to various hardware systems, such as the GPU, a sensor or context hub, or
+ * to memory accessible to various hardware systems, such as the GPU, a sensor or context hub, or
  * other auxiliary processing units.
  *
  * For more information, see the NDK documentation for <code>AHardwareBuffer</code>.
diff --git a/core/java/android/hardware/devicestate/IDeviceStateManager.aidl b/core/java/android/hardware/devicestate/IDeviceStateManager.aidl
index 0993160..0d73a11 100644
--- a/core/java/android/hardware/devicestate/IDeviceStateManager.aidl
+++ b/core/java/android/hardware/devicestate/IDeviceStateManager.aidl
@@ -111,6 +111,7 @@
     *
     * This should only be called from the overlay itself.
     */
+    @EnforcePermission("CONTROL_DEVICE_STATE")
     @JavaPassthrough(annotation=
         "@android.annotation.RequiresPermission(android.Manifest.permission.CONTROL_DEVICE_STATE)")
     void onStateRequestOverlayDismissed(boolean shouldCancelRequest);
diff --git a/core/java/android/hardware/display/IColorDisplayManager.aidl b/core/java/android/hardware/display/IColorDisplayManager.aidl
index 200cf736..77dfb47 100644
--- a/core/java/android/hardware/display/IColorDisplayManager.aidl
+++ b/core/java/android/hardware/display/IColorDisplayManager.aidl
@@ -32,26 +32,36 @@
     int getTransformCapabilities();
 
     boolean isNightDisplayActivated();
+    @EnforcePermission("CONTROL_DISPLAY_COLOR_TRANSFORMS")
     boolean setNightDisplayActivated(boolean activated);
     int getNightDisplayColorTemperature();
+    @EnforcePermission("CONTROL_DISPLAY_COLOR_TRANSFORMS")
     boolean setNightDisplayColorTemperature(int temperature);
+    @EnforcePermission("CONTROL_DISPLAY_COLOR_TRANSFORMS")
     int getNightDisplayAutoMode();
     int getNightDisplayAutoModeRaw();
+    @EnforcePermission("CONTROL_DISPLAY_COLOR_TRANSFORMS")
     boolean setNightDisplayAutoMode(int autoMode);
     Time getNightDisplayCustomStartTime();
+    @EnforcePermission("CONTROL_DISPLAY_COLOR_TRANSFORMS")
     boolean setNightDisplayCustomStartTime(in Time time);
     Time getNightDisplayCustomEndTime();
+    @EnforcePermission("CONTROL_DISPLAY_COLOR_TRANSFORMS")
     boolean setNightDisplayCustomEndTime(in Time time);
 
     int getColorMode();
+    @EnforcePermission("CONTROL_DISPLAY_COLOR_TRANSFORMS")
     void setColorMode(int colorMode);
 
     boolean isDisplayWhiteBalanceEnabled();
+    @EnforcePermission("CONTROL_DISPLAY_COLOR_TRANSFORMS")
     boolean setDisplayWhiteBalanceEnabled(boolean enabled);
 
     boolean isReduceBrightColorsActivated();
+    @EnforcePermission("CONTROL_DISPLAY_COLOR_TRANSFORMS")
     boolean setReduceBrightColorsActivated(boolean activated);
     int getReduceBrightColorsStrength();
+    @EnforcePermission("CONTROL_DISPLAY_COLOR_TRANSFORMS")
     boolean setReduceBrightColorsStrength(int strength);
     float getReduceBrightColorsOffsetFactor();
 }
\ No newline at end of file
diff --git a/core/java/android/hardware/display/IDisplayManager.aidl b/core/java/android/hardware/display/IDisplayManager.aidl
index a3b7b51..18edbdb 100644
--- a/core/java/android/hardware/display/IDisplayManager.aidl
+++ b/core/java/android/hardware/display/IDisplayManager.aidl
@@ -47,9 +47,11 @@
 
     // Requires CONFIGURE_WIFI_DISPLAY permission.
     // The process must have previously registered a callback.
+    @EnforcePermission("CONFIGURE_WIFI_DISPLAY")
     void startWifiDisplayScan();
 
     // Requires CONFIGURE_WIFI_DISPLAY permission.
+    @EnforcePermission("CONFIGURE_WIFI_DISPLAY")
     void stopWifiDisplayScan();
 
     // Requires CONFIGURE_WIFI_DISPLAY permission.
@@ -65,18 +67,22 @@
     void forgetWifiDisplay(String address);
 
     // Requires CONFIGURE_WIFI_DISPLAY permission.
+    @EnforcePermission("CONFIGURE_WIFI_DISPLAY")
     void pauseWifiDisplay();
 
     // Requires CONFIGURE_WIFI_DISPLAY permission.
+    @EnforcePermission("CONFIGURE_WIFI_DISPLAY")
     void resumeWifiDisplay();
 
     // No permissions required.
     WifiDisplayStatus getWifiDisplayStatus();
 
     // Requires WRITE_SECURE_SETTINGS permission.
+    @EnforcePermission("WRITE_SECURE_SETTINGS")
     void setUserDisabledHdrTypes(in int[] userDisabledTypes);
 
     // Requires WRITE_SECURE_SETTINGS permission.
+    @EnforcePermission("WRITE_SECURE_SETTINGS")
     void setAreUserDisabledHdrTypesAllowed(boolean areUserDisabledHdrTypesAllowed);
 
     // No permissions required.
@@ -89,6 +95,7 @@
     void overrideHdrTypes(int displayId, in int[] modes);
 
     // Requires CONFIGURE_DISPLAY_COLOR_MODE
+    @EnforcePermission("CONFIGURE_DISPLAY_COLOR_MODE")
     void requestColorMode(int displayId, int colorMode);
 
     // Requires CAPTURE_VIDEO_OUTPUT, CAPTURE_SECURE_VIDEO_OUTPUT, or an appropriate
@@ -114,24 +121,29 @@
     Point getStableDisplaySize();
 
     // Requires BRIGHTNESS_SLIDER_USAGE permission.
+    @EnforcePermission("BRIGHTNESS_SLIDER_USAGE")
     ParceledListSlice getBrightnessEvents(String callingPackage);
 
     // Requires ACCESS_AMBIENT_LIGHT_STATS permission.
+    @EnforcePermission("ACCESS_AMBIENT_LIGHT_STATS")
     ParceledListSlice getAmbientBrightnessStats();
 
     // Sets the global brightness configuration for a given user. Requires
     // CONFIGURE_DISPLAY_BRIGHTNESS, and INTERACT_ACROSS_USER if the user being configured is not
     // the same as the calling user.
+    @EnforcePermission("CONFIGURE_DISPLAY_BRIGHTNESS")
     void setBrightnessConfigurationForUser(in BrightnessConfiguration c, int userId,
             String packageName);
 
     // Sets the global brightness configuration for a given display. Requires
     // CONFIGURE_DISPLAY_BRIGHTNESS.
+    @EnforcePermission("CONFIGURE_DISPLAY_BRIGHTNESS")
     void setBrightnessConfigurationForDisplay(in BrightnessConfiguration c, String uniqueDisplayId,
             int userId, String packageName);
 
     // Gets the brightness configuration for a given display. Requires
     // CONFIGURE_DISPLAY_BRIGHTNESS.
+    @EnforcePermission("CONFIGURE_DISPLAY_BRIGHTNESS")
     BrightnessConfiguration getBrightnessConfigurationForDisplay(String uniqueDisplayId,
             int userId);
 
@@ -141,27 +153,32 @@
     BrightnessConfiguration getBrightnessConfigurationForUser(int userId);
 
     // Gets the default brightness configuration if configured.
+    @EnforcePermission("CONFIGURE_DISPLAY_BRIGHTNESS")
     BrightnessConfiguration getDefaultBrightnessConfiguration();
 
     // Gets the last requested minimal post processing settings for display with displayId.
     boolean isMinimalPostProcessingRequested(int displayId);
 
     // Temporarily sets the display brightness.
+    @EnforcePermission("CONTROL_DISPLAY_BRIGHTNESS")
     void setTemporaryBrightness(int displayId, float brightness);
 
     // Saves the display brightness.
+    @EnforcePermission("CONTROL_DISPLAY_BRIGHTNESS")
     void setBrightness(int displayId, float brightness);
 
     // Retrieves the display brightness.
     float getBrightness(int displayId);
 
     // Temporarily sets the auto brightness adjustment factor.
+    @EnforcePermission("CONTROL_DISPLAY_BRIGHTNESS")
     void setTemporaryAutoBrightnessAdjustment(float adjustment);
 
     // Get the minimum brightness curve.
     Curve getMinimumBrightnessCurve();
 
     // Get Brightness Information for the specified display.
+    @EnforcePermission("CONTROL_DISPLAY_BRIGHTNESS")
     BrightnessInfo getBrightnessInfo(int displayId);
 
     // Gets the id of the preferred wide gamut color space for all displays.
@@ -171,6 +188,7 @@
 
     // Sets the user preferred display mode.
     // Requires MODIFY_USER_PREFERRED_DISPLAY_MODE permission.
+    @EnforcePermission("MODIFY_USER_PREFERRED_DISPLAY_MODE")
     void setUserPreferredDisplayMode(int displayId, in Mode mode);
     Mode getUserPreferredDisplayMode(int displayId);
     Mode getSystemPreferredDisplayMode(int displayId);
@@ -187,10 +205,13 @@
     // When enabled the app requested display resolution and refresh rate is always selected
     // in DisplayModeDirector regardless of user settings and policies for low brightness, low
     // battery etc.
+    @EnforcePermission("OVERRIDE_DISPLAY_MODE_REQUESTS")
     void setShouldAlwaysRespectAppRequestedMode(boolean enabled);
+    @EnforcePermission("OVERRIDE_DISPLAY_MODE_REQUESTS")
     boolean shouldAlwaysRespectAppRequestedMode();
 
     // Sets the refresh rate switching type.
+    @EnforcePermission("MODIFY_REFRESH_RATE_SWITCHING_TYPE")
     void setRefreshRateSwitchingType(int newValue);
 
     // Returns the refresh rate switching type.
diff --git a/core/java/android/hardware/input/VirtualTouchEvent.java b/core/java/android/hardware/input/VirtualTouchEvent.java
index 73da5d9..2695a79 100644
--- a/core/java/android/hardware/input/VirtualTouchEvent.java
+++ b/core/java/android/hardware/input/VirtualTouchEvent.java
@@ -272,7 +272,8 @@
         public @NonNull Builder setAction(@Action int action) {
             if (action != ACTION_DOWN && action != ACTION_UP && action != ACTION_MOVE
                     && action != ACTION_CANCEL) {
-                throw new IllegalArgumentException("Unsupported touch event action type");
+                throw new IllegalArgumentException(
+                        "Unsupported touch event action type: " + action);
             }
             mAction = action;
             return this;
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index 244632a..2e05b8d 100755
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -1223,6 +1223,11 @@
          * Upside Down Cake.
          */
         public static final int UPSIDE_DOWN_CAKE = CUR_DEVELOPMENT;
+
+        /**
+         * Vanilla Ice Cream.
+         */
+        public static final int VANILLA_ICE_CREAM = CUR_DEVELOPMENT;
     }
 
     /** The type of build, like "user" or "eng". */
diff --git a/core/java/android/os/DdmSyncStageUpdater.java b/core/java/android/os/DdmSyncStageUpdater.java
new file mode 100644
index 0000000..90f7076
--- /dev/null
+++ b/core/java/android/os/DdmSyncStageUpdater.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os;
+
+import android.os.DdmSyncState.Stage;
+import android.util.Slog;
+
+import org.apache.harmony.dalvik.ddmc.Chunk;
+import org.apache.harmony.dalvik.ddmc.ChunkHandler;
+import org.apache.harmony.dalvik.ddmc.DdmServer;
+
+import java.nio.ByteBuffer;
+
+/**
+ * @hide
+ */
+// Making it public so ActivityThread can access it.
+public class DdmSyncStageUpdater {
+
+    private static final String TAG = "DdmSyncStageUpdater";
+
+    private static final int CHUNK_STAGE = ChunkHandler.type("STAG");
+
+    /**
+     * @hide
+     */
+    public DdmSyncStageUpdater() {
+    }
+
+    /**
+     * @hide
+     */
+    // Making it public so ActivityThread can access it.
+    public synchronized void next(Stage stage) {
+        try {
+            DdmSyncState.next(stage);
+
+            // Request DDMServer to send a STAG chunk
+            ByteBuffer data = ByteBuffer.allocate(Integer.BYTES);
+            data.putInt(stage.toInt());
+            Chunk stagChunk = new Chunk(CHUNK_STAGE, data);
+            DdmServer.sendChunk(stagChunk);
+        } catch (Exception e) {
+            // Catch everything to make sure we don't impact ActivityThread
+            Slog.w(TAG, "Unable to go to next stage" + stage, e);
+        }
+    }
+
+}
diff --git a/core/java/android/os/DdmSyncState.java b/core/java/android/os/DdmSyncState.java
new file mode 100644
index 0000000..09c9ef2
--- /dev/null
+++ b/core/java/android/os/DdmSyncState.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os;
+
+import java.util.Arrays;
+
+/**
+ * Keep track of an app boot state. The main purpose is to stream back DDM packet so a DDM client
+ * can synchronize with the app state.
+ *
+ * The state is static so it can be accessed from HELO handler.
+ *
+ * @hide
+ **/
+public final class DdmSyncState {
+
+    /**
+     * @hide
+     */
+    public enum Stage {
+        // From zygote to attach
+        Boot("BOOT"),
+
+        // From attach to handleBindApplication
+        Attach("ATCH"),
+
+        // When handleBindApplication is finally reached
+        Bind("BIND"),
+
+        // When the actual package name is known (not the early "<preinitalized>" value).
+        Named("NAMD"),
+
+        // Can be skipped if the app is not debugged.
+        Debugger("DEBG"),
+
+        // App is in RunLoop
+        Running("A_GO");
+
+        final String mLabel;
+
+        Stage(String label) {
+            if (label.length() != 4) {
+                throw new IllegalStateException(
+                    "Bad stage id '" + label + "'. Must be four letters");
+            }
+            this.mLabel = label;
+        }
+
+        /**
+         * To be included in a DDM packet payload, the stage is encoded in a big-endian int
+         * @hide
+         */
+        public int toInt() {
+            int result = 0;
+            for (int i = 0; i < 4; ++i) {
+                result = ((result << 8) | (mLabel.charAt(i) & 0xff));
+            }
+            return result;
+        }
+    }
+
+    private static int sCurrentStageIndex = 0;
+
+    /**
+     * @hide
+     */
+    public static synchronized Stage getStage() {
+        return Stage.values()[sCurrentStageIndex];
+    }
+
+    /**
+     * @hide
+     */
+    public static void reset() {
+        sCurrentStageIndex = 0;
+    }
+
+    /**
+     * Search for the next level down the list of Stage. Only succeed if the next stage
+     * if a later stage (no cycling allowed).
+     *
+     * @hide
+     */
+    public static synchronized void next(Stage nextStage) {
+        Stage[] stages = Stage.values();
+        // Search for the requested next stage
+        int rover = sCurrentStageIndex;
+        while (rover < stages.length && stages[rover] != nextStage) {
+            rover++;
+        }
+
+        if (rover == stages.length || stages[rover] != nextStage) {
+            throw new IllegalStateException(
+                "Cannot go to " + nextStage + " from:" + getInternalState());
+        }
+
+        sCurrentStageIndex = rover;
+    }
+
+    /**
+     * Use to build error messages
+     * @hide
+     */
+    private static String getInternalState() {
+        StringBuilder sb = new StringBuilder("\n");
+        sb.append("level = ").append(sCurrentStageIndex);
+        sb.append("\n");
+        sb.append("stages = ");
+        sb.append(Arrays.toString(Arrays.stream(Stage.values()).map(Enum::name).toArray()));
+        sb.append("\n");
+        return sb.toString();
+    }
+}
diff --git a/core/java/android/os/IRecoverySystem.aidl b/core/java/android/os/IRecoverySystem.aidl
index 88bdb7f..b3628ff 100644
--- a/core/java/android/os/IRecoverySystem.aidl
+++ b/core/java/android/os/IRecoverySystem.aidl
@@ -23,6 +23,7 @@
 /** @hide */
 
 interface IRecoverySystem {
+    @EnforcePermission("RECOVERY")
     boolean allocateSpaceForUpdate(in String packageFilePath);
     boolean uncrypt(in String packageFile, IRecoverySystemProgressListener listener);
     boolean setupBcb(in String command);
@@ -31,6 +32,7 @@
     boolean requestLskf(in String packageName, in IntentSender sender);
     boolean clearLskf(in String packageName);
     boolean isLskfCaptured(in String packageName);
+    @EnforcePermission("RECOVERY")
     int rebootWithLskfAssumeSlotSwitch(in String packageName, in String reason);
     int rebootWithLskf(in String packageName, in String reason, in boolean slotSwitch);
 }
diff --git a/core/java/android/os/ISystemUpdateManager.aidl b/core/java/android/os/ISystemUpdateManager.aidl
index f7f5079..cda2fa1 100644
--- a/core/java/android/os/ISystemUpdateManager.aidl
+++ b/core/java/android/os/ISystemUpdateManager.aidl
@@ -23,5 +23,6 @@
 /** @hide */
 interface ISystemUpdateManager {
     Bundle retrieveSystemUpdateInfo();
+    @EnforcePermission("RECOVERY")
     void updateSystemUpdateInfo(in PersistableBundle data);
 }
diff --git a/core/java/android/os/IVibratorManagerService.aidl b/core/java/android/os/IVibratorManagerService.aidl
index fb9752f..6275352 100644
--- a/core/java/android/os/IVibratorManagerService.aidl
+++ b/core/java/android/os/IVibratorManagerService.aidl
@@ -25,8 +25,11 @@
 interface IVibratorManagerService {
     int[] getVibratorIds();
     VibratorInfo getVibratorInfo(int vibratorId);
+    @EnforcePermission("ACCESS_VIBRATOR_STATE")
     boolean isVibrating(int vibratorId);
+    @EnforcePermission("ACCESS_VIBRATOR_STATE")
     boolean registerVibratorStateListener(int vibratorId, in IVibratorStateListener listener);
+    @EnforcePermission("ACCESS_VIBRATOR_STATE")
     boolean unregisterVibratorStateListener(int vibratorId, in IVibratorStateListener listener);
     boolean setAlwaysOnEffect(int uid, String opPkg, int alwaysOnId,
             in CombinedVibration vibration, in VibrationAttributes attributes);
diff --git a/core/java/android/os/OWNERS b/core/java/android/os/OWNERS
index e9a3254..69889c5 100644
--- a/core/java/android/os/OWNERS
+++ b/core/java/android/os/OWNERS
@@ -79,3 +79,7 @@
 
 # ART
 per-file ArtModuleServiceManager.java = file:platform/art:/OWNERS
+
+# DDM Protocol
+per-file DdmSyncState.java = sanglardf@google.com, rpaquay@google.com
+per-file DdmSyncStageUpdater.java = sanglardf@google.com, rpaquay@google.com
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
index e784c26..d52d758 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -362,6 +362,22 @@
     // see libbinder's binder/Status.h
     private static final int EX_TRANSACTION_FAILED = -129;
 
+    // Allow limit of 1 MB for allocating arrays
+    private static final int ARRAY_ALLOCATION_LIMIT = 1000000;
+
+    // Following type size are used to determine allocation size while creating arrays
+    private static final int SIZE_BYTE = 1;
+    private static final int SIZE_CHAR = 2;
+    private static final int SIZE_SHORT = 2;
+    private static final int SIZE_BOOLEAN = 4;
+    private static final int SIZE_INT = 4;
+    private static final int SIZE_FLOAT = 4;
+    private static final int SIZE_DOUBLE = 8;
+    private static final int SIZE_LONG = 8;
+
+    // Assume the least possible size for complex objects
+    private static final int SIZE_COMPLEX_TYPE = 1;
+
     @CriticalNative
     private static native void nativeMarkSensitive(long nativePtr);
     @FastNative
@@ -1502,9 +1518,63 @@
         }
     }
 
+    private static <T> int getItemTypeSize(@NonNull Class<T> arrayClass) {
+        final Class<?> componentType = arrayClass.getComponentType();
+        // typeSize has been referred from respective create*Array functions
+        if (componentType == boolean.class) {
+            return SIZE_BOOLEAN;
+        } else if (componentType == byte.class) {
+            return SIZE_BYTE;
+        } else if (componentType == char.class) {
+            return SIZE_CHAR;
+        } else if (componentType == int.class) {
+            return SIZE_INT;
+        } else if (componentType == long.class) {
+            return SIZE_LONG;
+        } else if (componentType == float.class) {
+            return SIZE_FLOAT;
+        } else if (componentType == double.class) {
+            return SIZE_DOUBLE;
+        }
+
+        return SIZE_COMPLEX_TYPE;
+    }
+
+    private void ensureWithinMemoryLimit(int typeSize, @NonNull int... dimensions) {
+        // For Multidimensional arrays, Calculate total object
+        // which will be allocated.
+        int totalObjects = 1;
+        try {
+            for (int dimension : dimensions) {
+                totalObjects = Math.multiplyExact(totalObjects, dimension);
+            }
+        } catch (ArithmeticException e) {
+            Log.e(TAG, "ArithmeticException occurred while multiplying dimensions " + e);
+        }
+        ensureWithinMemoryLimit(typeSize, totalObjects);
+    }
+
+    private void ensureWithinMemoryLimit(int typeSize, @NonNull int length) {
+        int estimatedAllocationSize = 0;
+        try {
+            estimatedAllocationSize = Math.multiplyExact(typeSize, length);
+        } catch (ArithmeticException e) {
+            Log.e(TAG, "ArithmeticException occurred while multiplying values " + typeSize
+                    + " and "  + length + " Exception: " + e);
+        }
+
+        boolean isInBinderTransaction = Binder.isDirectlyHandlingTransaction();
+        if (isInBinderTransaction && (estimatedAllocationSize > ARRAY_ALLOCATION_LIMIT)) {
+            Log.e(TAG, "Trying to Allocate " + estimatedAllocationSize
+                    + " memory, In Binder Transaction : " + isInBinderTransaction);
+        }
+    }
+
     @Nullable
     public final boolean[] createBooleanArray() {
         int N = readInt();
+        // Assuming size of 4 byte for boolean.
+        ensureWithinMemoryLimit(SIZE_BOOLEAN, N);
         // >>2 as a fast divide-by-4 works in the create*Array() functions
         // because dataAvail() will never return a negative number.  4 is
         // the size of a stored boolean in the stream.
@@ -1547,6 +1617,8 @@
     @Nullable
     public short[] createShortArray() {
         int n = readInt();
+        // Assuming size of 2 byte for short.
+        ensureWithinMemoryLimit(SIZE_SHORT, n);
         if (n >= 0 && n <= (dataAvail() >> 2)) {
             short[] val = new short[n];
             for (int i = 0; i < n; i++) {
@@ -1585,6 +1657,8 @@
     @Nullable
     public final char[] createCharArray() {
         int N = readInt();
+        // Assuming size of 2 byte for char.
+        ensureWithinMemoryLimit(SIZE_CHAR, N);
         if (N >= 0 && N <= (dataAvail() >> 2)) {
             char[] val = new char[N];
             for (int i=0; i<N; i++) {
@@ -1622,6 +1696,8 @@
     @Nullable
     public final int[] createIntArray() {
         int N = readInt();
+        // Assuming size of 4 byte for int.
+        ensureWithinMemoryLimit(SIZE_INT, N);
         if (N >= 0 && N <= (dataAvail() >> 2)) {
             int[] val = new int[N];
             for (int i=0; i<N; i++) {
@@ -1659,6 +1735,8 @@
     @Nullable
     public final long[] createLongArray() {
         int N = readInt();
+        // Assuming size of 8 byte for long.
+        ensureWithinMemoryLimit(SIZE_LONG, N);
         // >>3 because stored longs are 64 bits
         if (N >= 0 && N <= (dataAvail() >> 3)) {
             long[] val = new long[N];
@@ -1697,6 +1775,8 @@
     @Nullable
     public final float[] createFloatArray() {
         int N = readInt();
+        // Assuming size of 4 byte for float.
+        ensureWithinMemoryLimit(SIZE_FLOAT, N);
         // >>2 because stored floats are 4 bytes
         if (N >= 0 && N <= (dataAvail() >> 2)) {
             float[] val = new float[N];
@@ -1735,6 +1815,8 @@
     @Nullable
     public final double[] createDoubleArray() {
         int N = readInt();
+        // Assuming size of 8 byte for double.
+        ensureWithinMemoryLimit(SIZE_DOUBLE, N);
         // >>3 because stored doubles are 8 bytes
         if (N >= 0 && N <= (dataAvail() >> 3)) {
             double[] val = new double[N];
@@ -1788,6 +1870,7 @@
     @Nullable
     public final String[] createString8Array() {
         int N = readInt();
+        ensureWithinMemoryLimit(SIZE_COMPLEX_TYPE, N);
         if (N >= 0) {
             String[] val = new String[N];
             for (int i=0; i<N; i++) {
@@ -1828,6 +1911,7 @@
     @Nullable
     public final String[] createString16Array() {
         int N = readInt();
+        ensureWithinMemoryLimit(SIZE_COMPLEX_TYPE, N);
         if (N >= 0) {
             String[] val = new String[N];
             for (int i=0; i<N; i++) {
@@ -1920,6 +2004,7 @@
     @Nullable
     public final IBinder[] createBinderArray() {
         int N = readInt();
+        ensureWithinMemoryLimit(SIZE_COMPLEX_TYPE, N);
         if (N >= 0) {
             IBinder[] val = new IBinder[N];
             for (int i=0; i<N; i++) {
@@ -1954,6 +2039,7 @@
     public final <T extends IInterface> T[] createInterfaceArray(
             @NonNull IntFunction<T[]> newArray, @NonNull Function<IBinder, T> asInterface) {
         int N = readInt();
+        ensureWithinMemoryLimit(SIZE_COMPLEX_TYPE, N);
         if (N >= 0) {
             T[] val = newArray.apply(N);
             for (int i=0; i<N; i++) {
@@ -3200,6 +3286,7 @@
         if (N < 0) {
             return null;
         }
+        ensureWithinMemoryLimit(SIZE_COMPLEX_TYPE, N);
         FileDescriptor[] f = new FileDescriptor[N];
         for (int i = 0; i < N; i++) {
             f[i] = readRawFileDescriptor();
@@ -3666,6 +3753,7 @@
         if (N < 0) {
             return null;
         }
+        ensureWithinMemoryLimit(SIZE_COMPLEX_TYPE, N);
         ArrayList<T> l = new ArrayList<T>(N);
         while (N > 0) {
             l.add(readTypedObject(c));
@@ -3717,6 +3805,7 @@
         if (count < 0) {
             return null;
         }
+        ensureWithinMemoryLimit(SIZE_COMPLEX_TYPE, count);
         final SparseArray<T> array = new SparseArray<>(count);
         for (int i = 0; i < count; i++) {
             final int index = readInt();
@@ -3745,6 +3834,7 @@
         if (count < 0) {
             return null;
         }
+        ensureWithinMemoryLimit(SIZE_COMPLEX_TYPE, count);
         final ArrayMap<String, T> map = new ArrayMap<>(count);
         for (int i = 0; i < count; i++) {
             final String key = readString();
@@ -3771,6 +3861,7 @@
         if (N < 0) {
             return null;
         }
+        ensureWithinMemoryLimit(SIZE_COMPLEX_TYPE, N);
         ArrayList<String> l = new ArrayList<String>(N);
         while (N > 0) {
             l.add(readString());
@@ -3796,6 +3887,7 @@
         if (N < 0) {
             return null;
         }
+        ensureWithinMemoryLimit(SIZE_COMPLEX_TYPE, N);
         ArrayList<IBinder> l = new ArrayList<IBinder>(N);
         while (N > 0) {
             l.add(readStrongBinder());
@@ -3822,6 +3914,7 @@
         if (N < 0) {
             return null;
         }
+        ensureWithinMemoryLimit(SIZE_COMPLEX_TYPE, N);
         ArrayList<T> l = new ArrayList<T>(N);
         while (N > 0) {
             l.add(asInterface.apply(readStrongBinder()));
@@ -3981,6 +4074,7 @@
         if (N < 0) {
             return null;
         }
+        ensureWithinMemoryLimit(SIZE_COMPLEX_TYPE, N);
         T[] l = c.newArray(N);
         for (int i=0; i<N; i++) {
             l[i] = readTypedObject(c);
@@ -4209,6 +4303,10 @@
             while (innermost.isArray()) {
                 innermost = innermost.getComponentType();
             }
+
+            int typeSize = getItemTypeSize(innermost);
+            ensureWithinMemoryLimit(typeSize, dimensions);
+
             val = (T) Array.newInstance(innermost, dimensions);
             for (int i = 0; i < length; i++) {
                 readFixedArray(Array.get(val, i));
@@ -4265,6 +4363,10 @@
             while (innermost.isArray()) {
                 innermost = innermost.getComponentType();
             }
+
+            int typeSize = getItemTypeSize(innermost);
+            ensureWithinMemoryLimit(typeSize, dimensions);
+
             val = (T) Array.newInstance(innermost, dimensions);
             for (int i = 0; i < length; i++) {
                 readFixedArray(Array.get(val, i), asInterface);
@@ -4320,6 +4422,10 @@
             while (innermost.isArray()) {
                 innermost = innermost.getComponentType();
             }
+
+            int typeSize = getItemTypeSize(innermost);
+            ensureWithinMemoryLimit(typeSize, dimensions);
+
             val = (T) Array.newInstance(innermost, dimensions);
             for (int i = 0; i < length; i++) {
                 readFixedArray(Array.get(val, i), c);
@@ -5076,6 +5182,7 @@
         if (n < 0) {
             return null;
         }
+        ensureWithinMemoryLimit(SIZE_COMPLEX_TYPE, n);
         T[] p = (T[]) ((clazz == null) ? new Parcelable[n] : Array.newInstance(clazz, n));
         for (int i = 0; i < n; i++) {
             p[i] = readParcelableInternal(loader, clazz);
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index b2208d1..35e390f 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -1118,19 +1118,6 @@
     public static final native void setProcessFrozen(int pid, int uid, boolean frozen);
 
     /**
-     * Enable or disable the freezer. When enable == false all frozen processes are unfrozen,
-     * but aren't removed from the freezer. While in this state, processes can be added or removed
-     * by using setProcessFrozen, but they won't actually be frozen until the freezer is enabled
-     * again. If enable == true the freezer is enabled again, and all processes
-     * in the freezer (including the ones added while the freezer was disabled) are frozen.
-     *
-     * @param enable Specify whether to enable (true) or disable (false) the freezer.
-     *
-     * @hide
-     */
-    public static final native void enableFreezer(boolean enable);
-
-    /**
      * Return the scheduling group of requested process.
      *
      * @hide
diff --git a/core/java/android/os/RemoteCallbackList.java b/core/java/android/os/RemoteCallbackList.java
index d89c3d5..2c58021 100644
--- a/core/java/android/os/RemoteCallbackList.java
+++ b/core/java/android/os/RemoteCallbackList.java
@@ -273,7 +273,7 @@
      * handle such an exception by simply ignoring it.
      *
      * @param index Which of the registered callbacks you would like to
-     * retrieve.  Ranges from 0 to 1-{@link #beginBroadcast}.
+     * retrieve.  Ranges from 0 to {@link #beginBroadcast}-1, inclusive.
      *
      * @return Returns the callback interface that you can call.  This will
      * always be non-null.
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index b3604da..7337b37 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -1818,6 +1818,13 @@
     public static final int REMOVE_RESULT_ALREADY_BEING_REMOVED = 2;
 
     /**
+     * A response code indicating that the specified user is removable.
+     *
+     * @hide
+     */
+    public static final int REMOVE_RESULT_USER_IS_REMOVABLE = 3;
+
+    /**
      * A response code from {@link #removeUserWhenPossible(UserHandle, boolean)} indicating that
      * an unknown error occurred that prevented the user from being removed or set as ephemeral.
      *
@@ -1872,6 +1879,7 @@
             REMOVE_RESULT_REMOVED,
             REMOVE_RESULT_DEFERRED,
             REMOVE_RESULT_ALREADY_BEING_REMOVED,
+            REMOVE_RESULT_USER_IS_REMOVABLE,
             REMOVE_RESULT_ERROR_USER_RESTRICTION,
             REMOVE_RESULT_ERROR_USER_NOT_FOUND,
             REMOVE_RESULT_ERROR_SYSTEM_USER,
@@ -2574,7 +2582,8 @@
             enabledSinceTargetSdkVersion = Build.VERSION_CODES.TIRAMISU,
             requiresAnyOfPermissionsIfNotCaller = {
                     android.Manifest.permission.MANAGE_USERS,
-                    android.Manifest.permission.CREATE_USERS}
+                    android.Manifest.permission.CREATE_USERS,
+                    android.Manifest.permission.QUERY_USERS}
     )
     public boolean isLinkedUser() {
         return isRestrictedProfile();
@@ -2592,7 +2601,8 @@
             enabledSinceTargetSdkVersion = Build.VERSION_CODES.TIRAMISU,
             requiresAnyOfPermissionsIfNotCaller = {
                     android.Manifest.permission.MANAGE_USERS,
-                    android.Manifest.permission.CREATE_USERS}
+                    android.Manifest.permission.CREATE_USERS,
+                    android.Manifest.permission.QUERY_USERS}
     )
     public boolean isRestrictedProfile() {
         try {
@@ -2613,7 +2623,8 @@
     @SystemApi
     @RequiresPermission(anyOf = {
             Manifest.permission.MANAGE_USERS,
-            Manifest.permission.CREATE_USERS},
+            Manifest.permission.CREATE_USERS,
+            Manifest.permission.QUERY_USERS},
             conditional = true)
     public boolean isRestrictedProfile(@NonNull UserHandle user) {
         try {
diff --git a/core/java/android/os/VibrationEffect.java b/core/java/android/os/VibrationEffect.java
index 4366c28..8edb821 100644
--- a/core/java/android/os/VibrationEffect.java
+++ b/core/java/android/os/VibrationEffect.java
@@ -578,6 +578,30 @@
     }
 
     /**
+     * Ensures that the effect is repeating indefinitely or not. This is a lossy operation and
+     * should only be applied once to an original effect - it shouldn't be applied to the
+     * result of this method.
+     *
+     * <p>Non-repeating effects will be made repeating by looping the entire effect with the
+     * specified delay between each loop. The delay is added irrespective of whether the effect
+     * already has a delay at the beginning or end.
+     *
+     * <p>Repeating effects will be left with their native repeating portion if it should be
+     * repeating, and otherwise the loop index is removed, so that the entire effect plays once.
+     *
+     * @param wantRepeating Whether the effect is required to be repeating or not.
+     * @param loopDelayMs The milliseconds to pause between loops, if repeating is to be added to
+     *                    the effect. Ignored if {@code repeating==false} or the effect is already
+     *                    repeating itself. No delay is added if <= 0.
+     * @return this if the effect already satifies the repeating requirement, or a copy of this
+     *         adjusted to repeat or not repeat as appropriate.
+     * @hide
+     */
+    @NonNull
+    public abstract <T extends VibrationEffect> T applyRepeatingIndefinitely(
+            boolean wantRepeating, int loopDelayMs);
+
+    /**
      * Scale given vibration intensity by the given factor.
      *
      * @param intensity   relative intensity of the effect, must be between 0 and 1
@@ -859,6 +883,30 @@
             return scaled;
         }
 
+        /** @hide */
+        @NonNull
+        @Override
+        public Composed applyRepeatingIndefinitely(boolean wantRepeating, int loopDelayMs) {
+            boolean isRepeating = mRepeatIndex >= 0;
+            if (isRepeating == wantRepeating) {
+                return this;
+            } else if (!wantRepeating) {
+                return new Composed(mSegments, -1);
+            } else if (loopDelayMs <= 0) {
+                // Loop with no delay: repeat at index zero.
+                return new Composed(mSegments, 0);
+            } else {
+                // Append a delay and loop. It doesn't matter that there's a delay on the
+                // end because the looping is always indefinite until cancelled.
+                ArrayList<VibrationEffectSegment> loopingSegments =
+                        new ArrayList<>(mSegments.size() + 1);
+                loopingSegments.addAll(mSegments);
+                loopingSegments.add(
+                        new StepSegment(/* amplitude= */ 0, /* frequencyHz= */ 0, loopDelayMs));
+                return new Composed(loopingSegments, 0);
+            }
+        }
+
         @Override
         public boolean equals(@Nullable Object o) {
             if (!(o instanceof Composed)) {
diff --git a/core/java/android/permission/IPermissionManager.aidl b/core/java/android/permission/IPermissionManager.aidl
index 16ae3bc..d19fd8f 100644
--- a/core/java/android/permission/IPermissionManager.aidl
+++ b/core/java/android/permission/IPermissionManager.aidl
@@ -76,6 +76,7 @@
 
     List<SplitPermissionInfoParcelable> getSplitPermissions();
 
+    @EnforcePermission("MANAGE_ONE_TIME_PERMISSION_SESSIONS")
     void startOneTimePermissionSession(String packageName, int userId, long timeout,
             long revokeAfterKilledDelay);
 
diff --git a/core/java/android/permission/PermissionControllerManager.java b/core/java/android/permission/PermissionControllerManager.java
index b494c7f..319a0ea 100644
--- a/core/java/android/permission/PermissionControllerManager.java
+++ b/core/java/android/permission/PermissionControllerManager.java
@@ -701,6 +701,8 @@
         }, executor);
     }
 
+    // TODO(b/272129940): Remove this API and device profile role description when we drop T
+    //  support.
     /**
      * Gets the description of the privileges associated with the given device profiles
      *
@@ -708,8 +710,11 @@
      * @param executor Executor on which to invoke the callback
      * @param callback Callback to receive the result
      *
+     * @deprecated Device profile privilege descriptions have been bundled in CDM APK since T.
+     *
      * @hide
      */
+    @Deprecated
     @RequiresPermission(Manifest.permission.MANAGE_COMPANION_DEVICES)
     public void getPrivilegesDescriptionStringForProfile(
             @NonNull String profileName,
diff --git a/core/java/android/permission/PermissionControllerService.java b/core/java/android/permission/PermissionControllerService.java
index 4efffc5a..11005a6 100644
--- a/core/java/android/permission/PermissionControllerService.java
+++ b/core/java/android/permission/PermissionControllerService.java
@@ -348,6 +348,8 @@
         throw new AbstractMethodError("Must be overridden in implementing class");
     }
 
+    // TODO(b/272129940): Remove this API and device profile role description when we drop T
+    //  support.
     /**
      * Get a user-readable sentence, describing the set of privileges that are to be granted to a
      * companion app managing a device of the given profile.
@@ -355,8 +357,11 @@
      * @param deviceProfileName the
      *      {@link android.companion.AssociationRequest.DeviceProfile device profile} name
      *
+     * @deprecated Device profile privilege descriptions have been bundled in CDM APK since T.
+     *
      * @hide
      */
+    @Deprecated
     @SystemApi
     @RequiresPermission(Manifest.permission.MANAGE_COMPANION_DEVICES)
     @NonNull
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index c473d3f..ee91901 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -2428,6 +2428,24 @@
             "android.settings.REQUEST_SET_AUTOFILL_SERVICE";
 
     /**
+     * Activity Action: Show screen that let user enable a Credential Manager provider.
+     * <p>
+     * Input: Intent's data URI set with an application name, using the
+     * "package" schema (like "package:com.my.app").
+     *
+     * <p>
+     * Output: {@link android.app.Activity#RESULT_OK} if user selected a provider belonging
+     * to the caller package.
+     * <p>
+     * <b>NOTE: </b> Applications should call
+     * {@link android.credentials.CredentialManager#isEnabledCredentialProviderService()}
+     * and only use this action to start an activity if they return {@code false}.
+     */
+    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+    public static final String ACTION_CREDENTIAL_PROVIDER =
+            "android.settings.CREDENTIAL_PROVIDER";
+
+    /**
      * Activity Action: Show screen for controlling the Quick Access Wallet.
      * <p>
      * In some cases, a matching Activity may not exist, so ensure you
@@ -4390,6 +4408,16 @@
                 = "wear_accessibility_gesture_enabled";
 
         /**
+         * If the triple press gesture for toggling accessibility is enabled during OOBE.
+         * Set to 1 for true and 0 for false.
+         *
+         * This setting is used only internally.
+         * @hide
+         */
+        public static final String WEAR_ACCESSIBILITY_GESTURE_ENABLED_DURING_OOBE =
+                "wear_accessibility_gesture_enabled_during_oobe";
+
+        /**
          * @deprecated Use {@link android.provider.Settings.Global#AIRPLANE_MODE_ON} instead
          */
         @Deprecated
@@ -5801,6 +5829,7 @@
             PRIVATE_SETTINGS.add(END_BUTTON_BEHAVIOR);
             PRIVATE_SETTINGS.add(ADVANCED_SETTINGS);
             PRIVATE_SETTINGS.add(WEAR_ACCESSIBILITY_GESTURE_ENABLED);
+            PRIVATE_SETTINGS.add(WEAR_ACCESSIBILITY_GESTURE_ENABLED_DURING_OOBE);
             PRIVATE_SETTINGS.add(SCREEN_AUTO_BRIGHTNESS_ADJ);
             PRIVATE_SETTINGS.add(VIBRATE_INPUT_DEVICES);
             PRIVATE_SETTINGS.add(VOLUME_MASTER);
@@ -18669,6 +18698,13 @@
              * @hide
              */
             public static final int UPGRADE_DATA_MIGRATION_DONE = 2;
+
+            /**
+             * Whether to disable AOD while plugged.
+             * (0 = false, 1 = true)
+             * @hide
+             */
+            public static final String DISABLE_AOD_WHILE_PLUGGED = "disable_aod_while_plugged";
         }
     }
 
diff --git a/core/java/android/service/credentials/CredentialProviderInfoFactory.java b/core/java/android/service/credentials/CredentialProviderInfoFactory.java
index d2a4a66..34c06e9 100644
--- a/core/java/android/service/credentials/CredentialProviderInfoFactory.java
+++ b/core/java/android/service/credentials/CredentialProviderInfoFactory.java
@@ -46,8 +46,8 @@
 import android.util.Slog;
 import android.util.Xml;
 
-import com.android.internal.R;
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.R;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
@@ -134,8 +134,8 @@
     }
 
     /**
-     * Constructs an information instance of the credential provider for testing purposes. Does not
-     * run any verifications and passes parameters as is.
+     * Constructs an information instance of the credential provider for testing purposes. Does
+     * not run any verifications and passes parameters as is.
      */
     @VisibleForTesting
     public static CredentialProviderInfo createForTests(
@@ -150,6 +150,7 @@
                 .setSystemProvider(isSystemProvider)
                 .addCapabilities(capabilities)
                 .build();
+
     }
 
     private static void verifyProviderPermission(ServiceInfo serviceInfo) throws SecurityException {
@@ -220,7 +221,7 @@
 
         // 4. Extract the XML metadata.
         try {
-            builder = extractXmlMetadata(context, builder, serviceInfo, pm, resources);
+            builder = extractXmlMetadata(context, serviceInfo, pm, resources);
         } catch (Exception e) {
             Log.e(TAG, "Failed to get XML metadata", e);
         }
@@ -230,10 +231,11 @@
 
     private static CredentialProviderInfo.Builder extractXmlMetadata(
             @NonNull Context context,
-            @NonNull CredentialProviderInfo.Builder builder,
             @NonNull ServiceInfo serviceInfo,
             @NonNull PackageManager pm,
             @NonNull Resources resources) {
+        final CredentialProviderInfo.Builder builder =
+                new CredentialProviderInfo.Builder(serviceInfo);
         final XmlResourceParser parser =
                 serviceInfo.loadXmlMetaData(pm, CredentialProviderService.SERVICE_META_DATA);
         if (parser == null) {
@@ -276,9 +278,9 @@
         return builder;
     }
 
-    private static Set<String> parseXmlProviderOuterCapabilities(
+    private static List<String> parseXmlProviderOuterCapabilities(
             XmlPullParser parser, Resources resources) throws IOException, XmlPullParserException {
-        final Set<String> capabilities = new HashSet<>();
+        final List<String> capabilities = new ArrayList<>();
         final int outerDepth = parser.getDepth();
         int type;
         while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
diff --git a/core/java/android/service/voice/AlwaysOnHotwordDetector.java b/core/java/android/service/voice/AlwaysOnHotwordDetector.java
index 8688a18..a987773 100644
--- a/core/java/android/service/voice/AlwaysOnHotwordDetector.java
+++ b/core/java/android/service/voice/AlwaysOnHotwordDetector.java
@@ -556,8 +556,7 @@
         }
 
         /**
-         * Timestamp of when the trigger event from SoundTriggerHal was received by the system
-         * server.
+         * Timestamp of when the trigger event from SoundTriggerHal was received by the framework.
          *
          * Clock monotonic including suspend time or its equivalent on the system,
          * in the same units and timebase as {@link SystemClock#elapsedRealtime()}.
diff --git a/core/java/android/transition/ChangeBounds.java b/core/java/android/transition/ChangeBounds.java
index 59a05ac..3c185b1 100644
--- a/core/java/android/transition/ChangeBounds.java
+++ b/core/java/android/transition/ChangeBounds.java
@@ -22,6 +22,8 @@
 import android.animation.ObjectAnimator;
 import android.animation.PropertyValuesHolder;
 import android.animation.RectEvaluator;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.res.TypedArray;
@@ -274,9 +276,11 @@
         return parentMatches;
     }
 
+    @Nullable
     @Override
-    public Animator createAnimator(final ViewGroup sceneRoot, TransitionValues startValues,
-            TransitionValues endValues) {
+    public Animator createAnimator(@NonNull final ViewGroup sceneRoot,
+            @Nullable TransitionValues startValues,
+            @Nullable TransitionValues endValues) {
         if (startValues == null || endValues == null) {
             return null;
         }
diff --git a/core/java/android/transition/ChangeClipBounds.java b/core/java/android/transition/ChangeClipBounds.java
index a6398d3..bc2dfdc 100644
--- a/core/java/android/transition/ChangeClipBounds.java
+++ b/core/java/android/transition/ChangeClipBounds.java
@@ -19,6 +19,8 @@
 import android.animation.AnimatorListenerAdapter;
 import android.animation.ObjectAnimator;
 import android.animation.RectEvaluator;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.content.Context;
 import android.graphics.Rect;
 import android.util.AttributeSet;
@@ -75,9 +77,11 @@
         captureValues(transitionValues);
     }
 
+    @Nullable
     @Override
-    public Animator createAnimator(final ViewGroup sceneRoot, TransitionValues startValues,
-            TransitionValues endValues) {
+    public Animator createAnimator(@NonNull final ViewGroup sceneRoot,
+            @Nullable TransitionValues startValues,
+            @Nullable TransitionValues endValues) {
         if (startValues == null || endValues == null
                 || !startValues.values.containsKey(PROPNAME_CLIP)
                 || !endValues.values.containsKey(PROPNAME_CLIP)) {
diff --git a/core/java/android/transition/ChangeImageTransform.java b/core/java/android/transition/ChangeImageTransform.java
index 9fa9961..f12515f 100644
--- a/core/java/android/transition/ChangeImageTransform.java
+++ b/core/java/android/transition/ChangeImageTransform.java
@@ -18,6 +18,8 @@
 import android.animation.Animator;
 import android.animation.ObjectAnimator;
 import android.animation.TypeEvaluator;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.content.Context;
 import android.graphics.Matrix;
 import android.graphics.Rect;
@@ -135,9 +137,11 @@
      * @return An Animator to move an ImageView or null if the View is not an ImageView,
      * the Drawable changed, the View is not VISIBLE, or there was no change.
      */
+    @Nullable
     @Override
-    public Animator createAnimator(ViewGroup sceneRoot, TransitionValues startValues,
-            TransitionValues endValues) {
+    public Animator createAnimator(@NonNull ViewGroup sceneRoot,
+            @Nullable TransitionValues startValues,
+            @Nullable TransitionValues endValues) {
         if (startValues == null || endValues == null) {
             return null;
         }
diff --git a/core/java/android/transition/ChangeScroll.java b/core/java/android/transition/ChangeScroll.java
index 8a3fd1c..054bcd7 100644
--- a/core/java/android/transition/ChangeScroll.java
+++ b/core/java/android/transition/ChangeScroll.java
@@ -18,6 +18,8 @@
 
 import android.animation.Animator;
 import android.animation.ObjectAnimator;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.content.Context;
 import android.util.AttributeSet;
 import android.view.View;
@@ -63,9 +65,11 @@
         transitionValues.values.put(PROPNAME_SCROLL_Y, transitionValues.view.getScrollY());
     }
 
+    @Nullable
     @Override
-    public Animator createAnimator(ViewGroup sceneRoot, TransitionValues startValues,
-            TransitionValues endValues) {
+    public Animator createAnimator(@NonNull ViewGroup sceneRoot,
+            @Nullable TransitionValues startValues,
+            @Nullable TransitionValues endValues) {
         if (startValues == null || endValues == null) {
             return null;
         }
diff --git a/core/java/android/transition/ChangeText.java b/core/java/android/transition/ChangeText.java
index d609763..b5cd46d 100644
--- a/core/java/android/transition/ChangeText.java
+++ b/core/java/android/transition/ChangeText.java
@@ -20,6 +20,8 @@
 import android.animation.AnimatorListenerAdapter;
 import android.animation.AnimatorSet;
 import android.animation.ValueAnimator;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.graphics.Color;
 import android.util.Log;
 import android.view.ViewGroup;
@@ -151,9 +153,11 @@
         captureValues(transitionValues);
     }
 
+    @Nullable
     @Override
-    public Animator createAnimator(ViewGroup sceneRoot, TransitionValues startValues,
-            TransitionValues endValues) {
+    public Animator createAnimator(@NonNull ViewGroup sceneRoot,
+            @Nullable TransitionValues startValues,
+            @Nullable TransitionValues endValues) {
         if (startValues == null || endValues == null ||
                 !(startValues.view instanceof TextView) || !(endValues.view instanceof TextView)) {
             return null;
diff --git a/core/java/android/transition/ChangeTransform.java b/core/java/android/transition/ChangeTransform.java
index 02d0a6a..2e0b95d 100644
--- a/core/java/android/transition/ChangeTransform.java
+++ b/core/java/android/transition/ChangeTransform.java
@@ -20,6 +20,7 @@
 import android.animation.FloatArrayEvaluator;
 import android.animation.ObjectAnimator;
 import android.animation.PropertyValuesHolder;
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.Context;
 import android.content.res.TypedArray;
@@ -223,9 +224,11 @@
         captureValues(transitionValues);
     }
 
+    @Nullable
     @Override
-    public Animator createAnimator(ViewGroup sceneRoot, TransitionValues startValues,
-            TransitionValues endValues) {
+    public Animator createAnimator(@NonNull ViewGroup sceneRoot,
+            @Nullable TransitionValues startValues,
+            @Nullable TransitionValues endValues) {
         if (startValues == null || endValues == null ||
                 !startValues.values.containsKey(PROPNAME_PARENT) ||
                 !endValues.values.containsKey(PROPNAME_PARENT)) {
diff --git a/core/java/android/transition/Crossfade.java b/core/java/android/transition/Crossfade.java
index 69ce872..f13b8fe 100644
--- a/core/java/android/transition/Crossfade.java
+++ b/core/java/android/transition/Crossfade.java
@@ -22,6 +22,8 @@
 import android.animation.ObjectAnimator;
 import android.animation.RectEvaluator;
 import android.animation.ValueAnimator;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.Rect;
@@ -163,9 +165,11 @@
         return mResizeBehavior;
     }
 
+    @Nullable
     @Override
-    public Animator createAnimator(ViewGroup sceneRoot, TransitionValues startValues,
-            TransitionValues endValues) {
+    public Animator createAnimator(@NonNull ViewGroup sceneRoot,
+            @Nullable TransitionValues startValues,
+            @Nullable TransitionValues endValues) {
         if (startValues == null || endValues == null) {
             return null;
         }
diff --git a/core/java/android/transition/Recolor.java b/core/java/android/transition/Recolor.java
index 1a6864a..bc93d00 100644
--- a/core/java/android/transition/Recolor.java
+++ b/core/java/android/transition/Recolor.java
@@ -18,6 +18,8 @@
 
 import android.animation.Animator;
 import android.animation.ObjectAnimator;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.content.Context;
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
@@ -66,9 +68,11 @@
         captureValues(transitionValues);
     }
 
+    @Nullable
     @Override
-    public Animator createAnimator(ViewGroup sceneRoot, TransitionValues startValues,
-            TransitionValues endValues) {
+    public Animator createAnimator(@NonNull ViewGroup sceneRoot,
+            @Nullable TransitionValues startValues,
+            @Nullable TransitionValues endValues) {
         if (startValues == null || endValues == null) {
             return null;
         }
diff --git a/core/java/android/transition/Rotate.java b/core/java/android/transition/Rotate.java
index ad1720ca..4b60568 100644
--- a/core/java/android/transition/Rotate.java
+++ b/core/java/android/transition/Rotate.java
@@ -18,6 +18,8 @@
 
 import android.animation.Animator;
 import android.animation.ObjectAnimator;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.view.View;
 import android.view.ViewGroup;
 
@@ -41,9 +43,11 @@
         transitionValues.values.put(PROPNAME_ROTATION, transitionValues.view.getRotation());
     }
 
+    @Nullable
     @Override
-    public Animator createAnimator(ViewGroup sceneRoot, TransitionValues startValues,
-            TransitionValues endValues) {
+    public Animator createAnimator(@NonNull ViewGroup sceneRoot,
+            @Nullable TransitionValues startValues,
+            @Nullable TransitionValues endValues) {
         if (startValues == null || endValues == null) {
             return null;
         }
diff --git a/core/java/android/transition/Transition.java b/core/java/android/transition/Transition.java
index a204630..95841e0 100644
--- a/core/java/android/transition/Transition.java
+++ b/core/java/android/transition/Transition.java
@@ -19,6 +19,7 @@
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.TimeInterpolator;
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.Context;
@@ -464,14 +465,17 @@
      *
      *
      * @param sceneRoot The root of the transition hierarchy.
-     * @param startValues The values for a specific target in the start scene.
-     * @param endValues The values for the target in the end scene.
-     * @return A Animator to be started at the appropriate time in the
-     * overall transition for this scene change. A null value means no animation
-     * should be run.
+     * @param startValues The values for a specific target in the start scene, or {@code null} if
+     *                   the target doesn't exist in the start scene.
+     * @param endValues The values for the target in the end scene, or {@code null} if the target
+     *                 doesn't exist in the end scene.
+     * @return an {@link Animator} to be started at the appropriate time in the overall transition
+     * for this scene change. A {@code null} value means no animation should be run.
      */
-    public Animator createAnimator(ViewGroup sceneRoot, TransitionValues startValues,
-            TransitionValues endValues) {
+    @Nullable
+    public Animator createAnimator(@NonNull ViewGroup sceneRoot,
+            @Nullable TransitionValues startValues,
+            @Nullable TransitionValues endValues) {
         return null;
     }
 
diff --git a/core/java/android/transition/Visibility.java b/core/java/android/transition/Visibility.java
index 3c4b8c3..6b4608f 100644
--- a/core/java/android/transition/Visibility.java
+++ b/core/java/android/transition/Visibility.java
@@ -20,6 +20,8 @@
 import android.animation.Animator.AnimatorListener;
 import android.animation.Animator.AnimatorPauseListener;
 import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.content.Context;
 import android.content.res.TypedArray;
 import android.util.AttributeSet;
@@ -242,9 +244,11 @@
         return visInfo;
     }
 
+    @Nullable
     @Override
-    public Animator createAnimator(ViewGroup sceneRoot, TransitionValues startValues,
-            TransitionValues endValues) {
+    public Animator createAnimator(@NonNull ViewGroup sceneRoot,
+            @Nullable TransitionValues startValues,
+            @Nullable TransitionValues endValues) {
         VisibilityInfo visInfo = getVisibilityChangeInfo(startValues, endValues);
         if (visInfo.visibilityChange
                 && (visInfo.startParent != null || visInfo.endParent != null)) {
diff --git a/core/java/android/util/NtpTrustedTime.java b/core/java/android/util/NtpTrustedTime.java
index 5aa0f59..3adbd68 100644
--- a/core/java/android/util/NtpTrustedTime.java
+++ b/core/java/android/util/NtpTrustedTime.java
@@ -216,19 +216,36 @@
 
     private static NtpTrustedTime sSingleton;
 
+    /** A lock to prevent multiple refreshes taking place at the same time. */
+    private final Object mRefreshLock = new Object();
+
+    /** A lock to ensure safe read/writes to configuration. */
+    private final Object mConfigLock = new Object();
+
     /** An in-memory config override for use during tests. */
-    @GuardedBy("this")
+    @GuardedBy("mConfigLock")
     @Nullable
     private NtpConfig mNtpConfigForTests;
 
-    @GuardedBy("this")
+    /**
+     * The latest time result.
+     *
+     * <p>Written when holding {@link #mRefreshLock} but declared volatile and can be read outside
+     * synchronized blocks to avoid blocking dump() during {@link #forceRefresh}.
+     */
     @Nullable
-    private URI mLastSuccessfulNtpServerUri;
-
-    // Declared volatile and accessed outside synchronized blocks to avoid blocking reads during
-    // forceRefresh().
     private volatile TimeResult mTimeResult;
 
+    /**
+     * The last successful NTP server URI, i.e. the one used to obtain {@link #mTimeResult} when it
+     * is non-null.
+     *
+     * <p>Written when holding {@link #mRefreshLock} but declared volatile and can be read outside
+     * synchronized blocks to avoid blocking dump() during {@link #forceRefresh}.
+     */
+    @Nullable
+    private volatile URI mLastSuccessfulNtpServerUri;
+
     protected NtpTrustedTime() {
     }
 
@@ -246,7 +263,7 @@
      * test value, i.e. so the normal value will be used next time.
      */
     public void setServerConfigForTests(@NonNull NtpConfig ntpConfig) {
-        synchronized (this) {
+        synchronized (mConfigLock) {
             mNtpConfigForTests = ntpConfig;
         }
     }
@@ -254,7 +271,7 @@
     /** Forces a refresh using the default network. */
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
     public boolean forceRefresh() {
-        synchronized (this) {
+        synchronized (mRefreshLock) {
             Network network = getDefaultNetwork();
             if (network == null) {
                 if (LOGD) Log.d(TAG, "forceRefresh: no network available");
@@ -269,12 +286,13 @@
     public boolean forceRefresh(@NonNull Network network) {
         Objects.requireNonNull(network);
 
-        synchronized (this) {
+        synchronized (mRefreshLock) {
+            // Prevent concurrent refreshes.
             return forceRefreshLocked(network);
         }
     }
 
-    @GuardedBy("this")
+    @GuardedBy("mRefreshLock")
     private boolean forceRefreshLocked(@NonNull Network network) {
         Objects.requireNonNull(network);
 
@@ -349,12 +367,13 @@
         return false;
     }
 
-    @GuardedBy("this")
     private NtpConfig getNtpConfig() {
-        if (mNtpConfigForTests != null) {
-            return mNtpConfigForTests;
+        synchronized (mConfigLock) {
+            if (mNtpConfigForTests != null) {
+                return mNtpConfigForTests;
+            }
+            return getNtpConfigInternal();
         }
-        return getNtpConfigInternal();
     }
 
     /**
@@ -363,6 +382,7 @@
      *
      * <p>This method has been made public for easy replacement during tests.
      */
+    @GuardedBy("mConfigLock")
     @VisibleForTesting
     @Nullable
     public abstract NtpConfig getNtpConfigInternal();
@@ -479,14 +499,14 @@
 
     /** Sets the last received NTP time. Intended for use during tests. */
     public void setCachedTimeResult(TimeResult timeResult) {
-        synchronized (this) {
+        synchronized (mRefreshLock) {
             mTimeResult = timeResult;
         }
     }
 
     /** Clears the last received NTP time. Intended for use during tests. */
     public void clearCachedTimeResult() {
-        synchronized (this) {
+        synchronized (mRefreshLock) {
             mTimeResult = null;
         }
     }
@@ -585,15 +605,18 @@
 
     /** Prints debug information. */
     public void dump(PrintWriter pw) {
-        synchronized (this) {
+        synchronized (mConfigLock) {
             pw.println("getNtpConfig()=" + getNtpConfig());
             pw.println("mNtpConfigForTests=" + mNtpConfigForTests);
-            pw.println("mLastSuccessfulNtpServerUri=" + mLastSuccessfulNtpServerUri);
-            pw.println("mTimeResult=" + mTimeResult);
-            if (mTimeResult != null) {
-                pw.println("mTimeResult.getAgeMillis()="
-                        + Duration.ofMillis(mTimeResult.getAgeMillis()));
-            }
+        }
+
+        pw.println("mLastSuccessfulNtpServerUri=" + mLastSuccessfulNtpServerUri);
+
+        TimeResult timeResult = mTimeResult;
+        pw.println("mTimeResult=" + timeResult);
+        if (timeResult != null) {
+            pw.println("mTimeResult.getAgeMillis()="
+                    + Duration.ofMillis(timeResult.getAgeMillis()));
         }
     }
 
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 209729b..48ae59b 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -112,14 +112,19 @@
     void getInitialDisplaySize(int displayId, out Point size);
     @UnsupportedAppUsage
     void getBaseDisplaySize(int displayId, out Point size);
+    @EnforcePermission("WRITE_SECURE_SETTINGS")
     void setForcedDisplaySize(int displayId, int width, int height);
+    @EnforcePermission("WRITE_SECURE_SETTINGS")
     void clearForcedDisplaySize(int displayId);
     @UnsupportedAppUsage
     int getInitialDisplayDensity(int displayId);
     int getBaseDisplayDensity(int displayId);
     int getDisplayIdByUniqueId(String uniqueId);
+    @EnforcePermission("WRITE_SECURE_SETTINGS")
     void setForcedDisplayDensityForUser(int displayId, int density, int userId);
+    @EnforcePermission("WRITE_SECURE_SETTINGS")
     void clearForcedDisplayDensityForUser(int displayId, int userId);
+    @EnforcePermission("WRITE_SECURE_SETTINGS")
     void setForcedDisplayScalingMode(int displayId, int mode); // 0 = auto, 1 = disable
 
     // These can only be called when holding the MANAGE_APP_TOKENS permission.
@@ -159,6 +164,7 @@
      * @param shellRootLayer The container's layer. See WindowManager#ShellRootLayer.
      * @return a SurfaceControl to add things to.
      */
+    @EnforcePermission("MANAGE_APP_TOKENS")
     SurfaceControl addShellRoot(int displayId, IWindow client, int shellRootLayer);
 
     /**
@@ -167,6 +173,7 @@
      *
      * @param target The IWindow that accessibility service interfaces with.
      */
+    @EnforcePermission("MANAGE_APP_TOKENS")
     void setShellRootAccessibilityWindow(int displayId, int shellRootLayer, IWindow target);
 
     /**
@@ -197,6 +204,7 @@
     void disableKeyguard(IBinder token, String tag, int userId);
     /** @deprecated use Activity.setShowWhenLocked instead. */
     void reenableKeyguard(IBinder token, int userId);
+    @EnforcePermission("DISABLE_KEYGUARD")
     void exitKeyguardSecurely(IOnKeyguardExitResult callback);
     @UnsupportedAppUsage
     boolean isKeyguardLocked();
@@ -417,6 +425,7 @@
     /**
      * Called by System UI to enable or disable haptic feedback on the navigation bar buttons.
      */
+    @EnforcePermission("STATUS_BAR")
     @UnsupportedAppUsage
     void setNavBarVirtualKeyHapticFeedbackEnabled(boolean enabled);
 
@@ -504,6 +513,7 @@
     /**
      * Return the touch region for the current IME window, or an empty region if there is none.
      */
+    @EnforcePermission("RESTRICTED_VR_ACCESS")
     Region getCurrentImeTouchRegion();
 
     /**
@@ -713,6 +723,7 @@
      * When in multi-window mode, the provided displayWindowInsetsController will control insets
      * animations.
      */
+    @EnforcePermission("MANAGE_APP_TOKENS")
     void setDisplayWindowInsetsController(
             int displayId, in IDisplayWindowInsetsController displayWindowInsetsController);
 
@@ -720,6 +731,7 @@
      * Called when a remote process updates the requested visibilities of insets on a display window
      * container.
      */
+    @EnforcePermission("MANAGE_APP_TOKENS")
     void updateDisplayWindowRequestedVisibleTypes(int displayId, int requestedVisibleTypes);
 
     /**
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 152fa08..7606724 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -7091,7 +7091,11 @@
                 final MotionEvent event = (MotionEvent)q.mEvent;
                 final int source = event.getSource();
                 if ((source & InputDevice.SOURCE_CLASS_TRACKBALL) != 0) {
-                    mTrackball.process(event);
+                    // Do not synthesize events for relative mouse movement. If apps opt into
+                    // relative mouse movement they must be prepared to handle the events.
+                    if (!event.isFromSource(InputDevice.SOURCE_MOUSE_RELATIVE)) {
+                        mTrackball.process(event);
+                    }
                     return FINISH_HANDLED;
                 } else if ((source & InputDevice.SOURCE_CLASS_JOYSTICK) != 0) {
                     mJoystick.process(event);
diff --git a/core/java/android/view/accessibility/AccessibilityEvent.java b/core/java/android/view/accessibility/AccessibilityEvent.java
index 0acc022..e08d7fd 100644
--- a/core/java/android/view/accessibility/AccessibilityEvent.java
+++ b/core/java/android/view/accessibility/AccessibilityEvent.java
@@ -454,33 +454,35 @@
     @Deprecated
     public static final int MAX_TEXT_LENGTH = 500;
 
+    // Event types.
+
     /**
      * Represents the event of clicking on a {@link android.view.View} like
      * {@link android.widget.Button}, {@link android.widget.CompoundButton}, etc.
      */
-    public static final int TYPE_VIEW_CLICKED = 0x00000001;
+    public static final int TYPE_VIEW_CLICKED = 1 /* << 0 */;;
 
     /**
      * Represents the event of long clicking on a {@link android.view.View} like
      * {@link android.widget.Button}, {@link android.widget.CompoundButton}, etc.
      */
-    public static final int TYPE_VIEW_LONG_CLICKED = 0x00000002;
+    public static final int TYPE_VIEW_LONG_CLICKED = 1 << 1;
 
     /**
      * Represents the event of selecting an item usually in the context of an
      * {@link android.widget.AdapterView}.
      */
-    public static final int TYPE_VIEW_SELECTED = 0x00000004;
+    public static final int TYPE_VIEW_SELECTED = 1 << 2;
 
     /**
      * Represents the event of setting input focus of a {@link android.view.View}.
      */
-    public static final int TYPE_VIEW_FOCUSED = 0x00000008;
+    public static final int TYPE_VIEW_FOCUSED = 1 << 3;
 
     /**
      * Represents the event of changing the text of an {@link android.widget.EditText}.
      */
-    public static final int TYPE_VIEW_TEXT_CHANGED = 0x00000010;
+    public static final int TYPE_VIEW_TEXT_CHANGED = 1 << 4;
 
     /**
      * Represents the event of a change to a visually distinct section of the user interface.
@@ -488,49 +490,49 @@
      * accessibility pane titles, and replaces {@link #TYPE_WINDOW_CONTENT_CHANGED} for those
      * sources. Details about the change are available from {@link #getContentChangeTypes()}.
      */
-    public static final int TYPE_WINDOW_STATE_CHANGED = 0x00000020;
+    public static final int TYPE_WINDOW_STATE_CHANGED = 1 << 5;
 
     /**
      * Represents the event showing a {@link android.app.Notification}.
      */
-    public static final int TYPE_NOTIFICATION_STATE_CHANGED = 0x00000040;
+    public static final int TYPE_NOTIFICATION_STATE_CHANGED = 1 << 6;
 
     /**
      * Represents the event of a hover enter over a {@link android.view.View}.
      */
-    public static final int TYPE_VIEW_HOVER_ENTER = 0x00000080;
+    public static final int TYPE_VIEW_HOVER_ENTER = 1 << 7;
 
     /**
      * Represents the event of a hover exit over a {@link android.view.View}.
      */
-    public static final int TYPE_VIEW_HOVER_EXIT = 0x00000100;
+    public static final int TYPE_VIEW_HOVER_EXIT = 1 << 8;
 
     /**
      * Represents the event of starting a touch exploration gesture.
      */
-    public static final int TYPE_TOUCH_EXPLORATION_GESTURE_START = 0x00000200;
+    public static final int TYPE_TOUCH_EXPLORATION_GESTURE_START = 1 << 9;
 
     /**
      * Represents the event of ending a touch exploration gesture.
      */
-    public static final int TYPE_TOUCH_EXPLORATION_GESTURE_END = 0x00000400;
+    public static final int TYPE_TOUCH_EXPLORATION_GESTURE_END = 1 << 10;
 
     /**
      * Represents the event of changing the content of a window and more
      * specifically the sub-tree rooted at the event's source.
      */
-    public static final int TYPE_WINDOW_CONTENT_CHANGED = 0x00000800;
+    public static final int TYPE_WINDOW_CONTENT_CHANGED = 1 << 11;
 
     /**
      * Represents the event of scrolling a view. This event type is generally not sent directly.
      * @see android.view.View#onScrollChanged(int, int, int, int)
      */
-    public static final int TYPE_VIEW_SCROLLED = 0x00001000;
+    public static final int TYPE_VIEW_SCROLLED = 1 << 12;
 
     /**
      * Represents the event of changing the selection in an {@link android.widget.EditText}.
      */
-    public static final int TYPE_VIEW_TEXT_SELECTION_CHANGED = 0x00002000;
+    public static final int TYPE_VIEW_TEXT_SELECTION_CHANGED = 1 << 13;
 
     /**
      * Represents the event of an application making an announcement.
@@ -538,58 +540,58 @@
      * In general, follow the practices described in
      * {@link View#announceForAccessibility(CharSequence)}.
      */
-    public static final int TYPE_ANNOUNCEMENT = 0x00004000;
+    public static final int TYPE_ANNOUNCEMENT = 1 << 14;
 
     /**
      * Represents the event of gaining accessibility focus.
      */
-    public static final int TYPE_VIEW_ACCESSIBILITY_FOCUSED = 0x00008000;
+    public static final int TYPE_VIEW_ACCESSIBILITY_FOCUSED = 1 << 15;
 
     /**
      * Represents the event of clearing accessibility focus.
      */
-    public static final int TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED = 0x00010000;
+    public static final int TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED = 1 << 16;
 
     /**
      * Represents the event of traversing the text of a view at a given movement granularity.
      */
-    public static final int TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY = 0x00020000;
+    public static final int TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY = 1 << 17;
 
     /**
      * Represents the event of beginning gesture detection.
      */
-    public static final int TYPE_GESTURE_DETECTION_START = 0x00040000;
+    public static final int TYPE_GESTURE_DETECTION_START = 1 << 18;
 
     /**
      * Represents the event of ending gesture detection.
      */
-    public static final int TYPE_GESTURE_DETECTION_END = 0x00080000;
+    public static final int TYPE_GESTURE_DETECTION_END = 1 << 19;
 
     /**
      * Represents the event of the user starting to touch the screen.
      */
-    public static final int TYPE_TOUCH_INTERACTION_START = 0x00100000;
+    public static final int TYPE_TOUCH_INTERACTION_START = 1 << 20;
 
     /**
      * Represents the event of the user ending to touch the screen.
      */
-    public static final int TYPE_TOUCH_INTERACTION_END = 0x00200000;
+    public static final int TYPE_TOUCH_INTERACTION_END = 1 << 21;
 
     /**
      * Represents the event change in the system windows shown on the screen. This event type should
      * only be dispatched by the system.
      */
-    public static final int TYPE_WINDOWS_CHANGED = 0x00400000;
+    public static final int TYPE_WINDOWS_CHANGED = 1 << 22;
 
     /**
      * Represents the event of a context click on a {@link android.view.View}.
      */
-    public static final int TYPE_VIEW_CONTEXT_CLICKED = 0x00800000;
+    public static final int TYPE_VIEW_CONTEXT_CLICKED = 1 << 23;
 
     /**
      * Represents the event of the assistant currently reading the users screen context.
      */
-    public static final int TYPE_ASSIST_READING_CONTEXT = 0x01000000;
+    public static final int TYPE_ASSIST_READING_CONTEXT = 1 << 24;
 
     /**
      * Represents a change in the speech state defined by the speech state change types.
@@ -607,37 +609,39 @@
      * @see #getSpeechStateChangeTypes
      * @see #setSpeechStateChangeTypes
      */
-    public static final int TYPE_SPEECH_STATE_CHANGE = 0x02000000;
+    public static final int TYPE_SPEECH_STATE_CHANGE = 1 << 25;
 
     /**
      * Represents the event of a scroll having completed and brought the target node on screen.
      */
-    public static final int TYPE_VIEW_TARGETED_BY_SCROLL = 0x04000000;
+    public static final int TYPE_VIEW_TARGETED_BY_SCROLL = 1 << 26;
+
+    // Content change types.
 
     /**
      * Change type for {@link #TYPE_WINDOW_CONTENT_CHANGED} event: The type of change is not
      * defined.
      */
-    public static final int CONTENT_CHANGE_TYPE_UNDEFINED = 0x00000000;
+    public static final int CONTENT_CHANGE_TYPE_UNDEFINED = 0;
 
     /**
      * Change type for {@link #TYPE_WINDOW_CONTENT_CHANGED} event:
      * One or more content changes occurred in the the subtree rooted at the source node,
      * or the subtree's structure changed when a node was added or removed.
      */
-    public static final int CONTENT_CHANGE_TYPE_SUBTREE = 0x00000001;
+    public static final int CONTENT_CHANGE_TYPE_SUBTREE = 1 /* << 0 */;
 
     /**
      * Change type for {@link #TYPE_WINDOW_CONTENT_CHANGED} event:
      * The node's text changed.
      */
-    public static final int CONTENT_CHANGE_TYPE_TEXT = 0x00000002;
+    public static final int CONTENT_CHANGE_TYPE_TEXT = 1 << 1;
 
     /**
      * Change type for {@link #TYPE_WINDOW_CONTENT_CHANGED} event:
      * The node's content description changed.
      */
-    public static final int CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION = 0x00000004;
+    public static final int CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION = 1 << 2;
 
     /**
      * Change type for {@link #TYPE_WINDOW_STATE_CHANGED} event:
@@ -648,14 +652,14 @@
      * is sent.
      *
      */
-    public static final int CONTENT_CHANGE_TYPE_PANE_TITLE = 0x00000008;
+    public static final int CONTENT_CHANGE_TYPE_PANE_TITLE = 1 << 3;
 
     /**
      * Change type for {@link #TYPE_WINDOW_STATE_CHANGED} event:
      * The node has a pane title, and either just appeared or just was assigned a title when it
      * had none before.
      */
-    public static final int CONTENT_CHANGE_TYPE_PANE_APPEARED = 0x00000010;
+    public static final int CONTENT_CHANGE_TYPE_PANE_APPEARED = 1 << 4;
 
     /**
      * Change type for {@link #TYPE_WINDOW_STATE_CHANGED} event:
@@ -666,7 +670,7 @@
      * clear for the user, the first entry in {@link #getText()} will return the value that would
      * have been returned by {@code getSource().getPaneTitle()}.
      */
-    public static final int CONTENT_CHANGE_TYPE_PANE_DISAPPEARED = 0x00000020;
+    public static final int CONTENT_CHANGE_TYPE_PANE_DISAPPEARED = 1 << 5;
 
     /**
      * Change type for {@link #TYPE_WINDOW_CONTENT_CHANGED} event:
@@ -676,7 +680,7 @@
      * changed from "on, wifi signal full" to "on, wifi three bars", "wifi three bars" can be put
      * into the event text.
      */
-    public static final int CONTENT_CHANGE_TYPE_STATE_DESCRIPTION = 0x00000040;
+    public static final int CONTENT_CHANGE_TYPE_STATE_DESCRIPTION = 1 << 6;
 
     /**
      * Change type for {@link #TYPE_WINDOW_CONTENT_CHANGED} event:
@@ -686,7 +690,7 @@
      *
      * @see AccessibilityNodeInfo.AccessibilityAction#ACTION_DRAG_START
      */
-    public static final int CONTENT_CHANGE_TYPE_DRAG_STARTED = 0x00000080;
+    public static final int CONTENT_CHANGE_TYPE_DRAG_STARTED = 1 << 7;
 
     /**
      * Change type for {@link #TYPE_WINDOW_CONTENT_CHANGED} event:
@@ -695,7 +699,7 @@
      *
      * @see AccessibilityNodeInfo.AccessibilityAction#ACTION_DRAG_DROP
      */
-    public static final int CONTENT_CHANGE_TYPE_DRAG_DROPPED = 0x00000100;
+    public static final int CONTENT_CHANGE_TYPE_DRAG_DROPPED = 1 << 8;
 
     /**
      * Change type for {@link #TYPE_WINDOW_CONTENT_CHANGED} event:
@@ -706,7 +710,7 @@
      *
      * @see AccessibilityNodeInfo.AccessibilityAction#ACTION_DRAG_CANCEL
      */
-    public static final int CONTENT_CHANGE_TYPE_DRAG_CANCELLED = 0x0000200;
+    public static final int CONTENT_CHANGE_TYPE_DRAG_CANCELLED = 1 << 9;
 
     /**
      * Change type for {@link #TYPE_WINDOW_CONTENT_CHANGED} event:
@@ -718,7 +722,7 @@
      * @see AccessibilityNodeInfo#isContentInvalid
      * @see AccessibilityNodeInfo#setContentInvalid
      */
-    public static final int CONTENT_CHANGE_TYPE_CONTENT_INVALID = 0x0000400;
+    public static final int CONTENT_CHANGE_TYPE_CONTENT_INVALID = 1 << 10;
 
     /**
      * Change type for {@link #TYPE_WINDOW_CONTENT_CHANGED} event:
@@ -730,7 +734,7 @@
      * @see AccessibilityNodeInfo#getError
      * @see AccessibilityNodeInfo#setError
      */
-    public static final int CONTENT_CHANGE_TYPE_ERROR = 0x0000800;
+    public static final int CONTENT_CHANGE_TYPE_ERROR = 1 << 11;
 
     /**
      * Change type for {@link #TYPE_WINDOW_CONTENT_CHANGED} event:
@@ -744,44 +748,48 @@
      */
     public static final int CONTENT_CHANGE_TYPE_ENABLED = 1 << 12;
 
+    // Speech state change types.
+
     /** Change type for {@link #TYPE_SPEECH_STATE_CHANGE} event: another service is speaking. */
-    public static final int SPEECH_STATE_SPEAKING_START = 0x00000001;
+    public static final int SPEECH_STATE_SPEAKING_START = 1 /* << 0 */;;
 
     /**
      * Change type for {@link #TYPE_SPEECH_STATE_CHANGE} event: another service is no longer
      * speaking.
      */
-    public static final int SPEECH_STATE_SPEAKING_END = 0x00000002;
+    public static final int SPEECH_STATE_SPEAKING_END = 1 << 1;
 
     /**
      * Change type for {@link #TYPE_SPEECH_STATE_CHANGE} event: another service is listening to the
      * microphone.
      */
-    public static final int SPEECH_STATE_LISTENING_START = 0x00000004;
+    public static final int SPEECH_STATE_LISTENING_START = 1 << 2;
 
     /**
      * Change type for {@link #TYPE_SPEECH_STATE_CHANGE} event: another service is no longer
      * listening to the microphone.
      */
-    public static final int SPEECH_STATE_LISTENING_END = 0x00000008;
+    public static final int SPEECH_STATE_LISTENING_END = 1 << 3;
+
+    // Windows change types.
 
     /**
      * Change type for {@link #TYPE_WINDOWS_CHANGED} event:
      * The window was added.
      */
-    public static final int WINDOWS_CHANGE_ADDED = 0x00000001;
+    public static final int WINDOWS_CHANGE_ADDED = 1 /* << 0 */;;
 
     /**
      * Change type for {@link #TYPE_WINDOWS_CHANGED} event:
      * A window was removed.
      */
-    public static final int WINDOWS_CHANGE_REMOVED = 0x00000002;
+    public static final int WINDOWS_CHANGE_REMOVED = 1 << 1;
 
     /**
      * Change type for {@link #TYPE_WINDOWS_CHANGED} event:
      * The window's title changed.
      */
-    public static final int WINDOWS_CHANGE_TITLE = 0x00000004;
+    public static final int WINDOWS_CHANGE_TITLE = 1 << 2;
 
     /**
      * Change type for {@link #TYPE_WINDOWS_CHANGED} event:
@@ -791,49 +799,49 @@
      * region changed. It's also possible that region changed but bounds doesn't.
      * </p>
      */
-    public static final int WINDOWS_CHANGE_BOUNDS = 0x00000008;
+    public static final int WINDOWS_CHANGE_BOUNDS = 1 << 3;
 
     /**
      * Change type for {@link #TYPE_WINDOWS_CHANGED} event:
      * The window's layer changed.
      */
-    public static final int WINDOWS_CHANGE_LAYER = 0x00000010;
+    public static final int WINDOWS_CHANGE_LAYER = 1 << 4;
 
     /**
      * Change type for {@link #TYPE_WINDOWS_CHANGED} event:
      * The window's {@link AccessibilityWindowInfo#isActive()} changed.
      */
-    public static final int WINDOWS_CHANGE_ACTIVE = 0x00000020;
+    public static final int WINDOWS_CHANGE_ACTIVE = 1 << 5;
 
     /**
      * Change type for {@link #TYPE_WINDOWS_CHANGED} event:
      * The window's {@link AccessibilityWindowInfo#isFocused()} changed.
      */
-    public static final int WINDOWS_CHANGE_FOCUSED = 0x00000040;
+    public static final int WINDOWS_CHANGE_FOCUSED = 1 << 6;
 
     /**
      * Change type for {@link #TYPE_WINDOWS_CHANGED} event:
      * The window's {@link AccessibilityWindowInfo#isAccessibilityFocused()} changed.
      */
-    public static final int WINDOWS_CHANGE_ACCESSIBILITY_FOCUSED = 0x00000080;
+    public static final int WINDOWS_CHANGE_ACCESSIBILITY_FOCUSED = 1 << 7;
 
     /**
      * Change type for {@link #TYPE_WINDOWS_CHANGED} event:
      * The window's parent changed.
      */
-    public static final int WINDOWS_CHANGE_PARENT = 0x00000100;
+    public static final int WINDOWS_CHANGE_PARENT = 1 << 8;
 
     /**
      * Change type for {@link #TYPE_WINDOWS_CHANGED} event:
      * The window's children changed.
      */
-    public static final int WINDOWS_CHANGE_CHILDREN = 0x00000200;
+    public static final int WINDOWS_CHANGE_CHILDREN = 1 << 9;
 
     /**
      * Change type for {@link #TYPE_WINDOWS_CHANGED} event:
      * The window either entered or exited picture-in-picture mode.
      */
-    public static final int WINDOWS_CHANGE_PIP = 0x00000400;
+    public static final int WINDOWS_CHANGE_PIP = 1 << 10;
 
     /** @hide */
     @Retention(RetentionPolicy.SOURCE)
@@ -889,6 +897,7 @@
     public @interface SpeechStateChangeTypes {}
 
     /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
     @IntDef(
             flag = true,
             prefix = {"TYPE_"},
@@ -921,7 +930,6 @@
                 TYPE_SPEECH_STATE_CHANGE,
                 TYPE_VIEW_TARGETED_BY_SCROLL
             })
-    @Retention(RetentionPolicy.SOURCE)
     public @interface EventType {}
 
     /**
@@ -942,6 +950,8 @@
      * @see #TYPE_VIEW_SCROLLED
      * @see #TYPE_VIEW_TEXT_SELECTION_CHANGED
      * @see #TYPE_ANNOUNCEMENT
+     * @see #TYPE_VIEW_ACCESSIBILITY_FOCUSED
+     * @see #TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED
      * @see #TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
      * @see #TYPE_GESTURE_DETECTION_START
      * @see #TYPE_GESTURE_DETECTION_END
@@ -949,12 +959,15 @@
      * @see #TYPE_TOUCH_INTERACTION_END
      * @see #TYPE_WINDOWS_CHANGED
      * @see #TYPE_VIEW_CONTEXT_CLICKED
+     * @see #TYPE_ASSIST_READING_CONTEXT
+     * @see #TYPE_SPEECH_STATE_CHANGE
      * @see #TYPE_VIEW_TARGETED_BY_SCROLL
      */
     public static final int TYPES_ALL_MASK = 0xFFFFFFFF;
 
     @UnsupportedAppUsage
-    private @EventType int mEventType;
+    @EventType
+    private int mEventType;
     private CharSequence mPackageName;
     private long mEventTime;
     int mMovementGranularity;
@@ -1021,10 +1034,8 @@
         mEventTime = event.mEventTime;
         mPackageName = event.mPackageName;
         if (event.mRecords != null) {
-            final int recordCount = event.mRecords.size();
-            mRecords = new ArrayList<>(recordCount);
-            for (int i = 0; i < recordCount; i++) {
-                final AccessibilityRecord record = event.mRecords.get(i);
+            mRecords = new ArrayList<>(event.mRecords.size());
+            for (AccessibilityRecord record : event.mRecords) {
                 final AccessibilityRecord recordClone = new AccessibilityRecord(record);
                 mRecords.add(recordClone);
             }
@@ -1044,9 +1055,7 @@
         super.setSealed(sealed);
         final List<AccessibilityRecord> records = mRecords;
         if (records != null) {
-            final int recordCount = records.size();
-            for (int i = 0; i < recordCount; i++) {
-                AccessibilityRecord record = records.get(i);
+            for (AccessibilityRecord record : records) {
                 record.setSealed(sealed);
             }
         }
@@ -1094,7 +1103,8 @@
      *
      * @return The event type.
      */
-    public @EventType int getEventType() {
+    @EventType
+    public int getEventType() {
         return mEventType;
     }
 
@@ -1113,6 +1123,12 @@
      *         <li>{@link #CONTENT_CHANGE_TYPE_UNDEFINED}
      *         <li>{@link #CONTENT_CHANGE_TYPE_PANE_APPEARED}
      *         <li>{@link #CONTENT_CHANGE_TYPE_PANE_DISAPPEARED}
+     *         <li>{@link #CONTENT_CHANGE_TYPE_DRAG_STARTED}
+     *         <li>{@link #CONTENT_CHANGE_TYPE_DRAG_DROPPED}
+     *         <li>{@link #CONTENT_CHANGE_TYPE_DRAG_CANCELLED}
+     *         <li>{@link #CONTENT_CHANGE_TYPE_CONTENT_INVALID}
+     *         <li>{@link #CONTENT_CHANGE_TYPE_ERROR}
+     *         <li>{@link #CONTENT_CHANGE_TYPE_ENABLED}
      *         </ul>
      */
     @ContentChangeTypes
@@ -1203,7 +1219,9 @@
     }
 
     /**
-     * Gets the bit mask of the speech state signaled by a {@link #TYPE_SPEECH_STATE_CHANGE} event
+     * Gets the bit mask of the speech state signaled by a {@link #TYPE_SPEECH_STATE_CHANGE} event.
+     *
+     * @return The bit mask of speech change types.
      *
      * @see #SPEECH_STATE_SPEAKING_START
      * @see #SPEECH_STATE_SPEAKING_END
@@ -1256,6 +1274,18 @@
      * single event may represent multiple change types.
      *
      * @return The bit mask of change types.
+     *
+     * @see #WINDOWS_CHANGE_ADDED
+     * @see #WINDOWS_CHANGE_REMOVED
+     * @see #WINDOWS_CHANGE_TITLE
+     * @see #WINDOWS_CHANGE_BOUNDS
+     * @see #WINDOWS_CHANGE_LAYER
+     * @see #WINDOWS_CHANGE_ACTIVE
+     * @see #WINDOWS_CHANGE_FOCUSED
+     * @see #WINDOWS_CHANGE_ACCESSIBILITY_FOCUSED
+     * @see #WINDOWS_CHANGE_PARENT
+     * @see #WINDOWS_CHANGE_CHILDREN
+     * @see #WINDOWS_CHANGE_PIP
      */
     @WindowsChangeTypes
     public int getWindowChanges() {
@@ -1375,6 +1405,21 @@
      * <li>{@link AccessibilityNodeInfo#ACTION_CLEAR_FOCUS}
      * <li>{@link AccessibilityNodeInfo#ACTION_CLEAR_SELECTION}
      * <li>{@link AccessibilityNodeInfo#ACTION_CLICK}
+     * <li>{@link AccessibilityNodeInfo#ACTION_LONG_CLICK}
+     * <li>{@link AccessibilityNodeInfo#ACTION_NEXT_AT_MOVEMENT_GRANULARITY}
+     * <li>{@link AccessibilityNodeInfo#ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY}
+     * <li>{@link AccessibilityNodeInfo#ACTION_NEXT_HTML_ELEMENT}
+     * <li>{@link AccessibilityNodeInfo#ACTION_PREVIOUS_HTML_ELEMENT}
+     * <li>{@link AccessibilityNodeInfo#ACTION_SCROLL_FORWARD}
+     * <li>{@link AccessibilityNodeInfo#ACTION_SCROLL_BACKWARD}
+     * <li>{@link AccessibilityNodeInfo#ACTION_COPY}
+     * <li>{@link AccessibilityNodeInfo#ACTION_PASTE}
+     * <li>{@link AccessibilityNodeInfo#ACTION_CUT}
+     * <li>{@link AccessibilityNodeInfo#ACTION_SET_SELECTION}
+     * <li>{@link AccessibilityNodeInfo#ACTION_EXPAND}
+     * <li>{@link AccessibilityNodeInfo#ACTION_COLLAPSE}
+     * <li>{@link AccessibilityNodeInfo#ACTION_DISMISS}
+     * <li>{@link AccessibilityNodeInfo#ACTION_SET_TEXT}
      * <li>etc.
      * </ul>
      *
@@ -1758,7 +1803,8 @@
     /**
      * @see Parcelable.Creator
      */
-    public static final @android.annotation.NonNull Parcelable.Creator<AccessibilityEvent> CREATOR =
+    @NonNull
+    public static final Parcelable.Creator<AccessibilityEvent> CREATOR =
             new Parcelable.Creator<AccessibilityEvent>() {
         public AccessibilityEvent createFromParcel(Parcel parcel) {
             AccessibilityEvent event = new AccessibilityEvent();
diff --git a/core/java/android/view/accessibility/AccessibilityManager.java b/core/java/android/view/accessibility/AccessibilityManager.java
index efa2a01..11b0d5f 100644
--- a/core/java/android/view/accessibility/AccessibilityManager.java
+++ b/core/java/android/view/accessibility/AccessibilityManager.java
@@ -99,30 +99,30 @@
     private static final String LOG_TAG = "AccessibilityManager";
 
     /** @hide */
-    public static final int STATE_FLAG_ACCESSIBILITY_ENABLED = 0x00000001;
+    public static final int STATE_FLAG_ACCESSIBILITY_ENABLED = 1 /* << 0 */;
 
     /** @hide */
-    public static final int STATE_FLAG_TOUCH_EXPLORATION_ENABLED = 0x00000002;
+    public static final int STATE_FLAG_TOUCH_EXPLORATION_ENABLED = 1 << 1;
 
     /** @hide */
-    public static final int STATE_FLAG_HIGH_TEXT_CONTRAST_ENABLED = 0x00000004;
+    public static final int STATE_FLAG_HIGH_TEXT_CONTRAST_ENABLED = 1 << 2;
 
     /** @hide */
-    public static final int STATE_FLAG_DISPATCH_DOUBLE_TAP = 0x00000008;
+    public static final int STATE_FLAG_DISPATCH_DOUBLE_TAP = 1 << 3;
 
     /** @hide */
-    public static final int STATE_FLAG_REQUEST_MULTI_FINGER_GESTURES = 0x00000010;
+    public static final int STATE_FLAG_REQUEST_MULTI_FINGER_GESTURES = 1 << 4;
 
     /** @hide */
-    public static final int STATE_FLAG_TRACE_A11Y_INTERACTION_CONNECTION_ENABLED = 0x00000100;
+    public static final int STATE_FLAG_TRACE_A11Y_INTERACTION_CONNECTION_ENABLED = 1 << 8;
     /** @hide */
-    public static final int STATE_FLAG_TRACE_A11Y_INTERACTION_CONNECTION_CB_ENABLED = 0x00000200;
+    public static final int STATE_FLAG_TRACE_A11Y_INTERACTION_CONNECTION_CB_ENABLED = 1 << 9;
     /** @hide */
-    public static final int STATE_FLAG_TRACE_A11Y_INTERACTION_CLIENT_ENABLED = 0x00000400;
+    public static final int STATE_FLAG_TRACE_A11Y_INTERACTION_CLIENT_ENABLED = 1 << 10;
     /** @hide */
-    public static final int STATE_FLAG_TRACE_A11Y_SERVICE_ENABLED = 0x00000800;
+    public static final int STATE_FLAG_TRACE_A11Y_SERVICE_ENABLED = 1 << 11;
     /** @hide */
-    public static final int STATE_FLAG_AUDIO_DESCRIPTION_BY_DEFAULT_ENABLED = 0x00001000;
+    public static final int STATE_FLAG_AUDIO_DESCRIPTION_BY_DEFAULT_ENABLED = 1 << 12;
 
     /** @hide */
     public static final int DALTONIZER_DISABLED = -1;
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index ddd7734..aef75a0 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -136,6 +136,8 @@
     public static final long LEASHED_NODE_ID = makeNodeId(LEASHED_ITEM_ID,
             AccessibilityNodeProvider.HOST_VIEW_ID);
 
+    // Prefetch flags.
+
     /**
      * Prefetching strategy that prefetches the ancestors of the requested node.
      * <p> Ancestors will be prefetched before siblings and descendants.
@@ -146,7 +148,7 @@
      * @see AccessibilityService#getRootInActiveWindow(int)
      * @see AccessibilityEvent#getSource(int)
      */
-    public static final int FLAG_PREFETCH_ANCESTORS = 0x00000001;
+    public static final int FLAG_PREFETCH_ANCESTORS = 1 /* << 0 */;
 
     /**
      * Prefetching strategy that prefetches the siblings of the requested node.
@@ -155,7 +157,7 @@
      *
      * @see #FLAG_PREFETCH_ANCESTORS for where to use these flags.
      */
-    public static final int FLAG_PREFETCH_SIBLINGS = 0x00000002;
+    public static final int FLAG_PREFETCH_SIBLINGS = 1 << 1;
 
     /**
      * Prefetching strategy that prefetches the descendants in a hybrid depth first and breadth
@@ -167,7 +169,7 @@
      *
      * @see #FLAG_PREFETCH_ANCESTORS for where to use these flags.
      */
-    public static final int FLAG_PREFETCH_DESCENDANTS_HYBRID = 0x00000004;
+    public static final int FLAG_PREFETCH_DESCENDANTS_HYBRID = 1 << 2;
 
     /**
      * Prefetching strategy that prefetches the descendants of the requested node depth-first.
@@ -177,7 +179,7 @@
      *
      * @see #FLAG_PREFETCH_ANCESTORS for where to use these flags.
      */
-    public static final int FLAG_PREFETCH_DESCENDANTS_DEPTH_FIRST = 0x00000008;
+    public static final int FLAG_PREFETCH_DESCENDANTS_DEPTH_FIRST = 1 << 3;
 
     /**
      * Prefetching strategy that prefetches the descendants of the requested node breadth-first.
@@ -187,7 +189,7 @@
      *
      * @see #FLAG_PREFETCH_ANCESTORS for where to use these flags.
      */
-    public static final int FLAG_PREFETCH_DESCENDANTS_BREADTH_FIRST = 0x00000010;
+    public static final int FLAG_PREFETCH_DESCENDANTS_BREADTH_FIRST = 1 << 4;
 
     /**
      * Prefetching flag that specifies prefetching should not be interrupted by a request to
@@ -195,12 +197,31 @@
      *
      * @see #FLAG_PREFETCH_ANCESTORS for where to use these flags.
      */
-    public static final int FLAG_PREFETCH_UNINTERRUPTIBLE = 0x00000020;
+    public static final int FLAG_PREFETCH_UNINTERRUPTIBLE = 1 << 5;
 
-    /** @hide */
-    public static final int FLAG_PREFETCH_MASK = 0x0000003f;
+    /**
+     * Mask for {@link PrefetchingStrategy} all types.
+     *
+     * @see #FLAG_PREFETCH_ANCESTORS
+     * @see #FLAG_PREFETCH_SIBLINGS
+     * @see #FLAG_PREFETCH_DESCENDANTS_HYBRID
+     * @see #FLAG_PREFETCH_DESCENDANTS_DEPTH_FIRST
+     * @see #FLAG_PREFETCH_DESCENDANTS_BREADTH_FIRST
+     * @see #FLAG_PREFETCH_UNINTERRUPTIBLE
+     *
+     * @hide
+     */
+    public static final int FLAG_PREFETCH_MASK = 0x0000003F;
 
-    /** @hide */
+    /**
+     * Mask for {@link PrefetchingStrategy} that includes only descendants-related strategies.
+     *
+     * @see #FLAG_PREFETCH_DESCENDANTS_HYBRID
+     * @see #FLAG_PREFETCH_DESCENDANTS_DEPTH_FIRST
+     * @see #FLAG_PREFETCH_DESCENDANTS_BREADTH_FIRST
+     *
+     * @hide
+     */
     public static final int FLAG_PREFETCH_DESCENDANTS_MASK = 0x0000001C;
 
     /**
@@ -210,6 +231,7 @@
     public static final int MAX_NUMBER_OF_PREFETCHED_NODES = 50;
 
     /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
     @IntDef(flag = true, prefix = { "FLAG_PREFETCH" }, value = {
             FLAG_PREFETCH_ANCESTORS,
             FLAG_PREFETCH_SIBLINGS,
@@ -218,28 +240,33 @@
             FLAG_PREFETCH_DESCENDANTS_BREADTH_FIRST,
             FLAG_PREFETCH_UNINTERRUPTIBLE
     })
-    @Retention(RetentionPolicy.SOURCE)
     public @interface PrefetchingStrategy {}
 
+    // Service flags.
+
     /**
      * @see AccessibilityServiceInfo#FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
      * @hide
      */
-    public static final int FLAG_SERVICE_REQUESTS_INCLUDE_NOT_IMPORTANT_VIEWS = 0x00000080;
+    public static final int FLAG_SERVICE_REQUESTS_INCLUDE_NOT_IMPORTANT_VIEWS = 1 << 7;
 
     /**
      * @see AccessibilityServiceInfo#FLAG_REPORT_VIEW_IDS
      * @hide
      */
-    public static final int FLAG_SERVICE_REQUESTS_REPORT_VIEW_IDS = 0x00000100;
+    public static final int FLAG_SERVICE_REQUESTS_REPORT_VIEW_IDS = 1 << 8;
 
     /**
      * @see AccessibilityServiceInfo#isAccessibilityTool()
      * @hide
      */
-    public static final int FLAG_SERVICE_IS_ACCESSIBILITY_TOOL = 0x00000200;
+    public static final int FLAG_SERVICE_IS_ACCESSIBILITY_TOOL = 1 << 9;
 
-    /** @hide */
+    /**
+     * Mask for all types of additional view data exposed to services.
+     *
+     * @hide
+     */
     public static final int FLAG_REPORT_MASK =
             FLAG_SERVICE_REQUESTS_INCLUDE_NOT_IMPORTANT_VIEWS
                     | FLAG_SERVICE_REQUESTS_REPORT_VIEW_IDS
@@ -250,46 +277,46 @@
     /**
      * Action that gives input focus to the node.
      */
-    public static final int ACTION_FOCUS =  0x00000001;
+    public static final int ACTION_FOCUS =  1 /* << 0 */;
 
     /**
      * Action that clears input focus of the node.
      */
-    public static final int ACTION_CLEAR_FOCUS = 0x00000002;
+    public static final int ACTION_CLEAR_FOCUS = 1 << 1;
 
     /**
      * Action that selects the node.
      */
-    public static final int ACTION_SELECT = 0x00000004;
+    public static final int ACTION_SELECT = 1 << 2;
 
     /**
      * Action that deselects the node.
      */
-    public static final int ACTION_CLEAR_SELECTION = 0x00000008;
+    public static final int ACTION_CLEAR_SELECTION = 1 << 3;
 
     /**
      * Action that clicks on the node info.
      *
      * See {@link AccessibilityAction#ACTION_CLICK}
      */
-    public static final int ACTION_CLICK = 0x00000010;
+    public static final int ACTION_CLICK = 1 << 4;
 
     /**
      * Action that long clicks on the node.
      *
      * <p>It does not support coordinate information for anchoring.</p>
      */
-    public static final int ACTION_LONG_CLICK = 0x00000020;
+    public static final int ACTION_LONG_CLICK = 1 << 5;
 
     /**
      * Action that gives accessibility focus to the node.
      */
-    public static final int ACTION_ACCESSIBILITY_FOCUS = 0x00000040;
+    public static final int ACTION_ACCESSIBILITY_FOCUS = 1 << 6;
 
     /**
      * Action that clears accessibility focus of the node.
      */
-    public static final int ACTION_CLEAR_ACCESSIBILITY_FOCUS = 0x00000080;
+    public static final int ACTION_CLEAR_ACCESSIBILITY_FOCUS = 1 << 7;
 
     /**
      * Action that requests to go to the next entity in this node's text
@@ -321,7 +348,7 @@
      * @see #MOVEMENT_GRANULARITY_PARAGRAPH
      * @see #MOVEMENT_GRANULARITY_PAGE
      */
-    public static final int ACTION_NEXT_AT_MOVEMENT_GRANULARITY = 0x00000100;
+    public static final int ACTION_NEXT_AT_MOVEMENT_GRANULARITY = 1 << 8;
 
     /**
      * Action that requests to go to the previous entity in this node's text
@@ -354,7 +381,7 @@
      * @see #MOVEMENT_GRANULARITY_PARAGRAPH
      * @see #MOVEMENT_GRANULARITY_PAGE
      */
-    public static final int ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY = 0x00000200;
+    public static final int ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY = 1 << 9;
 
     /**
      * Action to move to the next HTML element of a given type. For example, move
@@ -369,7 +396,7 @@
      * </code></pre></p>
      * </p>
      */
-    public static final int ACTION_NEXT_HTML_ELEMENT = 0x00000400;
+    public static final int ACTION_NEXT_HTML_ELEMENT = 1 << 10;
 
     /**
      * Action to move to the previous HTML element of a given type. For example, move
@@ -384,32 +411,32 @@
      * </code></pre></p>
      * </p>
      */
-    public static final int ACTION_PREVIOUS_HTML_ELEMENT = 0x00000800;
+    public static final int ACTION_PREVIOUS_HTML_ELEMENT = 1 << 11;
 
     /**
      * Action to scroll the node content forward.
      */
-    public static final int ACTION_SCROLL_FORWARD = 0x00001000;
+    public static final int ACTION_SCROLL_FORWARD = 1 << 12;
 
     /**
      * Action to scroll the node content backward.
      */
-    public static final int ACTION_SCROLL_BACKWARD = 0x00002000;
+    public static final int ACTION_SCROLL_BACKWARD = 1 << 13;
 
     /**
      * Action to copy the current selection to the clipboard.
      */
-    public static final int ACTION_COPY = 0x00004000;
+    public static final int ACTION_COPY = 1 << 14;
 
     /**
      * Action to paste the current clipboard content.
      */
-    public static final int ACTION_PASTE = 0x00008000;
+    public static final int ACTION_PASTE = 1 << 15;
 
     /**
      * Action to cut the current selection and place it to the clipboard.
      */
-    public static final int ACTION_CUT = 0x00010000;
+    public static final int ACTION_CUT = 1 << 16;
 
     /**
      * Action to set the selection. Performing this action with no arguments
@@ -430,22 +457,22 @@
      * @see #ACTION_ARGUMENT_SELECTION_START_INT
      * @see #ACTION_ARGUMENT_SELECTION_END_INT
      */
-    public static final int ACTION_SET_SELECTION = 0x00020000;
+    public static final int ACTION_SET_SELECTION = 1 << 17;
 
     /**
      * Action to expand an expandable node.
      */
-    public static final int ACTION_EXPAND = 0x00040000;
+    public static final int ACTION_EXPAND = 1 << 18;
 
     /**
      * Action to collapse an expandable node.
      */
-    public static final int ACTION_COLLAPSE = 0x00080000;
+    public static final int ACTION_COLLAPSE = 1 << 19;
 
     /**
      * Action to dismiss a dismissable node.
      */
-    public static final int ACTION_DISMISS = 0x00100000;
+    public static final int ACTION_DISMISS = 1 << 20;
 
     /**
      * Action that sets the text of the node. Performing the action without argument, using <code>
@@ -462,17 +489,30 @@
      *   info.performAction(AccessibilityNodeInfo.ACTION_SET_TEXT, arguments);
      * </code></pre></p>
      */
-    public static final int ACTION_SET_TEXT = 0x00200000;
+    public static final int ACTION_SET_TEXT = 1 << 21;
 
     /** @hide */
     public static final int LAST_LEGACY_STANDARD_ACTION = ACTION_SET_TEXT;
 
     /**
-     * Mask to see if the value is larger than the largest ACTION_ constant
+     * Mask to verify if a given value is a combination of the existing ACTION_ constants.
+     *
+     * The smallest possible action is 1, and the largest is 1 << 21, or {@link ACTION_SET_TEXT}. A
+     * node can have any combination of actions present, so a node's max action int is:
+     *
+     *   0000 0000 0011 1111 1111 1111 1111 1111
+     *
+     * Therefore, if an action has any of the following bits flipped, it will be invalid:
+     *
+     *   1111 1111 11-- ---- ---- ---- ---- ----
+     *
+     * This can be represented in hexadecimal as 0xFFC00000.
+     *
+     * @see AccessibilityNodeInfo#addAction(int)
      */
-    private static final int ACTION_TYPE_MASK = 0xFF000000;
+    private static final int INVALID_ACTIONS_MASK = 0xFFC00000;
 
-    // Action arguments
+    // Action arguments.
 
     /**
      * Argument for which movement granularity to be used when traversing the node text.
@@ -678,7 +718,7 @@
     public static final String ACTION_ARGUMENT_DIRECTION_INT =
             "android.view.accessibility.action.ARGUMENT_DIRECTION_INT";
 
-    // Focus types
+    // Focus types.
 
     /**
      * The input focus.
@@ -690,32 +730,34 @@
      */
     public static final int FOCUS_ACCESSIBILITY = 2;
 
-    // Movement granularities
+    // Movement granularities.
 
     /**
      * Movement granularity bit for traversing the text of a node by character.
      */
-    public static final int MOVEMENT_GRANULARITY_CHARACTER = 0x00000001;
+    public static final int MOVEMENT_GRANULARITY_CHARACTER = 1 /* << 0 */;
 
     /**
      * Movement granularity bit for traversing the text of a node by word.
      */
-    public static final int MOVEMENT_GRANULARITY_WORD = 0x00000002;
+    public static final int MOVEMENT_GRANULARITY_WORD = 1 << 1;
 
     /**
      * Movement granularity bit for traversing the text of a node by line.
      */
-    public static final int MOVEMENT_GRANULARITY_LINE = 0x00000004;
+    public static final int MOVEMENT_GRANULARITY_LINE = 1 << 2;
 
     /**
      * Movement granularity bit for traversing the text of a node by paragraph.
      */
-    public static final int MOVEMENT_GRANULARITY_PARAGRAPH = 0x00000008;
+    public static final int MOVEMENT_GRANULARITY_PARAGRAPH = 1 << 3;
 
     /**
      * Movement granularity bit for traversing the text of a node by page.
      */
-    public static final int MOVEMENT_GRANULARITY_PAGE = 0x00000010;
+    public static final int MOVEMENT_GRANULARITY_PAGE = 1 << 4;
+
+    // Extra data arguments.
 
     /**
      * Key used to request and locate extra data for text character location. This key requests that
@@ -746,7 +788,7 @@
 
     /**
      * Integer argument specifying the end index of the requested text location data. Must be
-     * positive and no larger than {@link #EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_LENGTH}.
+     * positive and no larger than {@link #EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_MAX_LENGTH}.
      *
      * @see #EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY
      */
@@ -782,53 +824,53 @@
 
     // Boolean attributes.
 
-    private static final int BOOLEAN_PROPERTY_CHECKABLE = 0x00000001;
+    private static final int BOOLEAN_PROPERTY_CHECKABLE = 1 /* << 0 */;
 
-    private static final int BOOLEAN_PROPERTY_CHECKED = 0x00000002;
+    private static final int BOOLEAN_PROPERTY_CHECKED = 1 << 1;
 
-    private static final int BOOLEAN_PROPERTY_FOCUSABLE = 0x00000004;
+    private static final int BOOLEAN_PROPERTY_FOCUSABLE = 1 << 2;
 
-    private static final int BOOLEAN_PROPERTY_FOCUSED = 0x00000008;
+    private static final int BOOLEAN_PROPERTY_FOCUSED = 1 << 3;
 
-    private static final int BOOLEAN_PROPERTY_SELECTED = 0x00000010;
+    private static final int BOOLEAN_PROPERTY_SELECTED = 1 << 4;
 
-    private static final int BOOLEAN_PROPERTY_CLICKABLE = 0x00000020;
+    private static final int BOOLEAN_PROPERTY_CLICKABLE = 1 << 5;
 
-    private static final int BOOLEAN_PROPERTY_LONG_CLICKABLE = 0x00000040;
+    private static final int BOOLEAN_PROPERTY_LONG_CLICKABLE = 1 << 6;
 
-    private static final int BOOLEAN_PROPERTY_ENABLED = 0x00000080;
+    private static final int BOOLEAN_PROPERTY_ENABLED = 1 << 7;
 
-    private static final int BOOLEAN_PROPERTY_PASSWORD = 0x00000100;
+    private static final int BOOLEAN_PROPERTY_PASSWORD = 1 << 8;
 
-    private static final int BOOLEAN_PROPERTY_SCROLLABLE = 0x00000200;
+    private static final int BOOLEAN_PROPERTY_SCROLLABLE = 1 << 9;
 
-    private static final int BOOLEAN_PROPERTY_ACCESSIBILITY_FOCUSED = 0x00000400;
+    private static final int BOOLEAN_PROPERTY_ACCESSIBILITY_FOCUSED = 1 << 10;
 
-    private static final int BOOLEAN_PROPERTY_VISIBLE_TO_USER = 0x00000800;
+    private static final int BOOLEAN_PROPERTY_VISIBLE_TO_USER = 1 << 11;
 
-    private static final int BOOLEAN_PROPERTY_EDITABLE = 0x00001000;
+    private static final int BOOLEAN_PROPERTY_EDITABLE = 1 << 12;
 
-    private static final int BOOLEAN_PROPERTY_OPENS_POPUP = 0x00002000;
+    private static final int BOOLEAN_PROPERTY_OPENS_POPUP = 1 << 13;
 
-    private static final int BOOLEAN_PROPERTY_DISMISSABLE = 0x00004000;
+    private static final int BOOLEAN_PROPERTY_DISMISSABLE = 1 << 14;
 
-    private static final int BOOLEAN_PROPERTY_MULTI_LINE = 0x00008000;
+    private static final int BOOLEAN_PROPERTY_MULTI_LINE = 1 << 15;
 
-    private static final int BOOLEAN_PROPERTY_CONTENT_INVALID = 0x00010000;
+    private static final int BOOLEAN_PROPERTY_CONTENT_INVALID = 1 << 16;
 
-    private static final int BOOLEAN_PROPERTY_CONTEXT_CLICKABLE = 0x00020000;
+    private static final int BOOLEAN_PROPERTY_CONTEXT_CLICKABLE = 1 << 17;
 
-    private static final int BOOLEAN_PROPERTY_IMPORTANCE = 0x0040000;
+    private static final int BOOLEAN_PROPERTY_IMPORTANCE = 1 << 18;
 
-    private static final int BOOLEAN_PROPERTY_SCREEN_READER_FOCUSABLE = 0x0080000;
+    private static final int BOOLEAN_PROPERTY_SCREEN_READER_FOCUSABLE = 1 << 19;
 
-    private static final int BOOLEAN_PROPERTY_IS_SHOWING_HINT = 0x0100000;
+    private static final int BOOLEAN_PROPERTY_IS_SHOWING_HINT = 1 << 20;
 
-    private static final int BOOLEAN_PROPERTY_IS_HEADING = 0x0200000;
+    private static final int BOOLEAN_PROPERTY_IS_HEADING = 1 << 21;
 
-    private static final int BOOLEAN_PROPERTY_IS_TEXT_ENTRY_KEY = 0x0400000;
+    private static final int BOOLEAN_PROPERTY_IS_TEXT_ENTRY_KEY = 1 << 22;
 
-    private static final int BOOLEAN_PROPERTY_IS_TEXT_SELECTABLE = 0x0800000;
+    private static final int BOOLEAN_PROPERTY_IS_TEXT_SELECTABLE = 1 << 23;
 
     private static final int BOOLEAN_PROPERTY_REQUEST_INITIAL_ACCESSIBILITY_FOCUS = 1 << 24;
 
@@ -1528,7 +1570,7 @@
     public void addAction(int action) {
         enforceNotSealed();
 
-        if ((action & ACTION_TYPE_MASK) != 0) {
+        if ((action & INVALID_ACTIONS_MASK) != 0) {
             throw new IllegalArgumentException("Action is not a combination of the standard " +
                     "actions: " + action);
         }
@@ -6466,7 +6508,7 @@
         /**
          * @see android.os.Parcelable.Creator
          */
-        public static final @android.annotation.NonNull Parcelable.Creator<TouchDelegateInfo> CREATOR =
+        public static final @NonNull Parcelable.Creator<TouchDelegateInfo> CREATOR =
                 new Parcelable.Creator<TouchDelegateInfo>() {
             @Override
             public TouchDelegateInfo createFromParcel(Parcel parcel) {
@@ -6638,7 +6680,7 @@
     /**
      * @see android.os.Parcelable.Creator
      */
-    public static final @android.annotation.NonNull Parcelable.Creator<AccessibilityNodeInfo> CREATOR =
+    public static final @NonNull Parcelable.Creator<AccessibilityNodeInfo> CREATOR =
             new Parcelable.Creator<AccessibilityNodeInfo>() {
         @Override
         public AccessibilityNodeInfo createFromParcel(Parcel parcel) {
diff --git a/core/java/android/view/accessibility/AccessibilityRecord.java b/core/java/android/view/accessibility/AccessibilityRecord.java
index 38b564a..11fd1c5 100644
--- a/core/java/android/view/accessibility/AccessibilityRecord.java
+++ b/core/java/android/view/accessibility/AccessibilityRecord.java
@@ -66,13 +66,13 @@
 
     private static final int UNDEFINED = -1;
 
-    private static final int PROPERTY_CHECKED = 0x00000001;
-    private static final int PROPERTY_ENABLED = 0x00000002;
-    private static final int PROPERTY_PASSWORD = 0x00000004;
-    private static final int PROPERTY_FULL_SCREEN = 0x00000080;
-    private static final int PROPERTY_SCROLLABLE = 0x00000100;
-    private static final int PROPERTY_IMPORTANT_FOR_ACCESSIBILITY = 0x00000200;
-    private static final int PROPERTY_ACCESSIBILITY_DATA_SENSITIVE = 0x00000400;
+    private static final int PROPERTY_CHECKED = 1 /* << 0 */;
+    private static final int PROPERTY_ENABLED = 1 << 1;
+    private static final int PROPERTY_PASSWORD = 1 << 2;
+    private static final int PROPERTY_FULL_SCREEN = 1 << 7;
+    private static final int PROPERTY_SCROLLABLE = 1 << 8;
+    private static final int PROPERTY_IMPORTANT_FOR_ACCESSIBILITY = 1 << 9;
+    private static final int PROPERTY_ACCESSIBILITY_DATA_SENSITIVE = 1 << 10;
 
     private static final int GET_SOURCE_PREFETCH_FLAGS =
             AccessibilityNodeInfo.FLAG_PREFETCH_ANCESTORS
@@ -198,8 +198,7 @@
      *
      * @see AccessibilityNodeInfo#getParent(int) for a description of prefetching.
      */
-    @Nullable
-    public AccessibilityNodeInfo getSource(
+    public @Nullable AccessibilityNodeInfo getSource(
             @AccessibilityNodeInfo.PrefetchingStrategy int prefetchingStrategy) {
         enforceSealed();
         if ((mConnectionId == UNDEFINED)
diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java
index 801b13a..1ef7afc 100644
--- a/core/java/android/view/autofill/AutofillManager.java
+++ b/core/java/android/view/autofill/AutofillManager.java
@@ -2322,10 +2322,7 @@
      *
      * @param executor specifies the thread upon which the callbacks will be invoked.
      * @param callback which handles autofill request to provide client's suggestions.
-     *
-     * @hide
      */
-    @TestApi
     @RequiresPermission(PROVIDE_OWN_AUTOFILL_SUGGESTIONS)
     public void setAutofillRequestCallback(@NonNull @CallbackExecutor Executor executor,
             @NonNull AutofillRequestCallback callback) {
@@ -2342,10 +2339,7 @@
 
     /**
      * clears the client's suggestions callback for autofill.
-     *
-     * @hide
      */
-    @TestApi
     public void clearAutofillRequestCallback() {
         synchronized (mLock) {
             mRequestCallbackExecutor = null;
diff --git a/core/java/android/view/autofill/AutofillRequestCallback.java b/core/java/android/view/autofill/AutofillRequestCallback.java
index 10a088b..e632a58 100644
--- a/core/java/android/view/autofill/AutofillRequestCallback.java
+++ b/core/java/android/view/autofill/AutofillRequestCallback.java
@@ -18,7 +18,6 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.annotation.TestApi;
 import android.os.CancellationSignal;
 import android.service.autofill.FillCallback;
 import android.view.inputmethod.InlineSuggestionsRequest;
@@ -56,10 +55,7 @@
  *
  * <P>IMPORTANT: This should not be used for displaying anything other than input suggestions, or
  * the keyboard may choose to block your app from the inline strip.
- *
- * @hide
  */
-@TestApi
 public interface AutofillRequestCallback {
     /**
      * Called by the Android system to decide if a screen can be autofilled by the callback.
diff --git a/core/java/android/view/inputmethod/InlineSuggestionsRequest.java b/core/java/android/view/inputmethod/InlineSuggestionsRequest.java
index 77a2b5b..70279cc 100644
--- a/core/java/android/view/inputmethod/InlineSuggestionsRequest.java
+++ b/core/java/android/view/inputmethod/InlineSuggestionsRequest.java
@@ -18,7 +18,6 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.annotation.TestApi;
 import android.app.ActivityThread;
 import android.app.compat.CompatChanges;
 import android.compat.annotation.ChangeId;
@@ -701,10 +700,7 @@
          * provides the input view.
          *
          * Note: The default value is {@code true}.
-         *
-         * @hide
          */
-        @TestApi
         @DataClass.Generated.Member
         public @NonNull Builder setServiceSupported(boolean value) {
             checkNotUsed();
@@ -718,10 +714,7 @@
          * input view.
          *
          * Note: The default value is {@code true}.
-         *
-         * @hide
          */
-        @TestApi
         @DataClass.Generated.Member
         public @NonNull Builder setClientSupported(boolean value) {
             checkNotUsed();
diff --git a/core/java/com/android/internal/app/IAppOpsService.aidl b/core/java/com/android/internal/app/IAppOpsService.aidl
index 88447da..d63611f 100644
--- a/core/java/com/android/internal/app/IAppOpsService.aidl
+++ b/core/java/com/android/internal/app/IAppOpsService.aidl
@@ -81,12 +81,19 @@
     void getHistoricalOpsFromDiskRaw(int uid, String packageName, String attributionTag,
             in List<String> ops, int historyFlags, int filter, long beginTimeMillis,
             long endTimeMillis, int flags, in RemoteCallback callback);
+    @EnforcePermission("MANAGE_APPOPS")
     void offsetHistory(long duration);
+    @EnforcePermission("MANAGE_APPOPS")
     void setHistoryParameters(int mode, long baseSnapshotInterval, int compressionStep);
+    @EnforcePermission("MANAGE_APPOPS")
     void addHistoricalOps(in AppOpsManager.HistoricalOps ops);
+    @EnforcePermission("MANAGE_APPOPS")
     void resetHistoryParameters();
+    @EnforcePermission("MANAGE_APPOPS")
     void resetPackageOpsNoHistory(String packageName);
+    @EnforcePermission("MANAGE_APPOPS")
     void clearHistory();
+    @EnforcePermission("MANAGE_APPOPS")
     void rebootHistory(long offlineDurationMillis);
     List<AppOpsManager.PackageOps> getUidOps(int uid, in int[] ops);
     void setUidMode(int code, int uid, int mode);
diff --git a/core/java/com/android/internal/os/anr/AnrLatencyTracker.java b/core/java/com/android/internal/os/anr/AnrLatencyTracker.java
index 096d1cd..6fa6fa5 100644
--- a/core/java/com/android/internal/os/anr/AnrLatencyTracker.java
+++ b/core/java/com/android/internal/os/anr/AnrLatencyTracker.java
@@ -28,12 +28,15 @@
 import static com.android.internal.util.FrameworkStatsLog.ANRLATENCY_REPORTED__ANR_TYPE__START_FOREGROUND_SERVICE;
 import static com.android.internal.util.FrameworkStatsLog.ANRLATENCY_REPORTED__ANR_TYPE__UNKNOWN_ANR_TYPE;
 
+import android.annotation.IntDef;
 import android.os.SystemClock;
 import android.os.Trace;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.FrameworkStatsLog;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.concurrent.atomic.AtomicInteger;
 
 /**
@@ -44,6 +47,22 @@
  */
 public class AnrLatencyTracker implements AutoCloseable {
 
+    /** Status of the early dumped pid. */
+    @IntDef(value = {
+            EarlyDumpStatus.UNKNOWN,
+            EarlyDumpStatus.SUCCEEDED,
+            EarlyDumpStatus.FAILED_TO_CREATE_FILE,
+            EarlyDumpStatus.TIMED_OUT
+    })
+
+    @Retention(RetentionPolicy.SOURCE)
+    private @interface EarlyDumpStatus {
+        int UNKNOWN = 1;
+        int SUCCEEDED = 2;
+        int FAILED_TO_CREATE_FILE = 3;
+        int TIMED_OUT = 4;
+    }
+
     private static final AtomicInteger sNextAnrRecordPlacedOnQueueCookieGenerator =
             new AtomicInteger();
 
@@ -77,7 +96,16 @@
 
     private int mAnrQueueSize;
     private int mAnrType;
-    private int mDumpedProcessesCount = 0;
+    private final AtomicInteger mDumpedProcessesCount = new AtomicInteger(0);
+
+    private volatile @EarlyDumpStatus int mEarlyDumpStatus =
+            EarlyDumpStatus.UNKNOWN;
+    private volatile long mTempFileDumpingStartUptime;
+    private volatile long mTempFileDumpingDuration = 0;
+    private long mCopyingFirstPidStartUptime;
+    private long mCopyingFirstPidDuration = 0;
+    private long mEarlyDumpRequestSubmissionUptime = 0;
+    private long mEarlyDumpExecutorPidCount = 0;
 
     private long mFirstPidsDumpingStartUptime;
     private long mFirstPidsDumpingDuration = 0;
@@ -88,7 +116,7 @@
 
     private boolean mIsPushed = false;
     private boolean mIsSkipped = false;
-
+    private boolean mCopyingFirstPidSucceeded = false;
 
     private final int mAnrRecordPlacedOnQueueCookie =
             sNextAnrRecordPlacedOnQueueCookieGenerator.incrementAndGet();
@@ -111,6 +139,15 @@
         Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
     }
 
+    /**
+     * Records the number of processes we are currently early-dumping, this number includes the
+     * current ANR's main process.
+     */
+    public void earlyDumpRequestSubmittedWithSize(int currentProcessedPidCount) {
+        mEarlyDumpRequestSubmissionUptime = getUptimeMillis();
+        mEarlyDumpExecutorPidCount = currentProcessedPidCount;
+    }
+
     /** Records the placing of the AnrHelper.AnrRecord instance on the processing queue. */
     public void anrRecordPlacingOnQueueWithSize(int queueSize) {
         mAnrRecordPlacedOnQueueUptime = getUptimeMillis();
@@ -210,48 +247,89 @@
         Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
     }
 
-    /** Records the start of pid dumping to file (subject and criticalEventSection). */
+    /** Records the start of pid dumping to file. */
     public void dumpingPidStarted(int pid) {
         Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "dumpingPid#" + pid);
     }
 
-    /** Records the end of pid dumping to file (subject and criticalEventSection). */
+    /** Records the end of pid dumping to file. */
     public void dumpingPidEnded() {
-        mDumpedProcessesCount++;
+        mDumpedProcessesCount.incrementAndGet();
         Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
     }
 
-    /** Records the start of pid dumping to file (subject and criticalEventSection). */
+    /** Records the start of first pids dumping to file. */
     public void dumpingFirstPidsStarted() {
         mFirstPidsDumpingStartUptime = getUptimeMillis();
         Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "dumpingFirstPids");
     }
 
-    /** Records the end of pid dumping to file (subject and criticalEventSection). */
+    /** Records the end of first pids dumping to file. */
     public void dumpingFirstPidsEnded() {
         mFirstPidsDumpingDuration = getUptimeMillis() - mFirstPidsDumpingStartUptime;
         Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
     }
 
-    /** Records the start of pid dumping to file (subject and criticalEventSection). */
+
+    /** Records the start of the copying of the pre-dumped first pid. */
+    public void copyingFirstPidStarted() {
+        mCopyingFirstPidStartUptime = getUptimeMillis();
+        Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "copyingFirstPid");
+    }
+
+    /** Records the end of the copying of the pre-dumped first pid. */
+    public void copyingFirstPidEnded(boolean copySucceeded) {
+        mCopyingFirstPidDuration = getUptimeMillis() - mCopyingFirstPidStartUptime;
+        mCopyingFirstPidSucceeded = copySucceeded;
+        Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
+    }
+
+    /** Records the start of pre-dumping. */
+    public void dumpStackTracesTempFileStarted() {
+        mTempFileDumpingStartUptime = getUptimeMillis();
+        Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "dumpStackTracesTempFile");
+    }
+
+    /** Records the end of pre-dumping. */
+    public void dumpStackTracesTempFileEnded() {
+        mTempFileDumpingDuration = getUptimeMillis() - mTempFileDumpingStartUptime;
+        if (mEarlyDumpStatus == EarlyDumpStatus.UNKNOWN) {
+            mEarlyDumpStatus = EarlyDumpStatus.SUCCEEDED;
+        }
+        Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
+    }
+
+    /** Records file creation failure events in dumpStackTracesTempFile. */
+    public void dumpStackTracesTempFileCreationFailed() {
+        mEarlyDumpStatus = EarlyDumpStatus.FAILED_TO_CREATE_FILE;
+        Trace.instant(TRACE_TAG_ACTIVITY_MANAGER, "dumpStackTracesTempFileCreationFailed");
+    }
+
+    /** Records timeout events in dumpStackTracesTempFile. */
+    public void dumpStackTracesTempFileTimedOut() {
+        mEarlyDumpStatus = EarlyDumpStatus.TIMED_OUT;
+        Trace.instant(TRACE_TAG_ACTIVITY_MANAGER, "dumpStackTracesTempFileTimedOut");
+    }
+
+    /** Records the start of native pids dumping to file. */
     public void dumpingNativePidsStarted() {
         mNativePidsDumpingStartUptime = getUptimeMillis();
         Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "dumpingNativePids");
     }
 
-    /** Records the end of pid dumping to file (subject and criticalEventSection). */
+    /** Records the end of native pids dumping to file . */
     public void dumpingNativePidsEnded() {
         mNativePidsDumpingDuration =  getUptimeMillis() - mNativePidsDumpingStartUptime;
         Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
     }
 
-    /** Records the start of pid dumping to file (subject and criticalEventSection). */
+    /** Records the start of extra pids dumping to file. */
     public void dumpingExtraPidsStarted() {
         mExtraPidsDumpingStartUptime = getUptimeMillis();
         Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "dumpingExtraPids");
     }
 
-    /** Records the end of pid dumping to file (subject and criticalEventSection). */
+    /** Records the end of extra pids dumping to file. */
     public void dumpingExtraPidsEnded() {
         mExtraPidsDumpingDuration =  getUptimeMillis() - mExtraPidsDumpingStartUptime;
         Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
@@ -337,7 +415,7 @@
      * Returns latency data as a comma separated value string for inclusion in ANR report.
      */
     public String dumpAsCommaSeparatedArrayWithHeader() {
-        return "DurationsV2: " + mAnrTriggerUptime
+        return "DurationsV3: " + mAnrTriggerUptime
                 /* triggering_to_app_not_responding_duration = */
                 + "," + (mAppNotRespondingStartUptime -  mAnrTriggerUptime)
                 /* app_not_responding_duration = */
@@ -370,7 +448,22 @@
                 /* anr_queue_size_when_pushed = */
                 + "," + mAnrQueueSize
                 /* dump_stack_traces_io_time = */
-                + "," + (mFirstPidsDumpingStartUptime - mDumpStackTracesStartUptime)
+                // We use copyingFirstPidUptime if we're dumping the durations list before the
+                // first pids ie after copying the early dump stacks.
+                + "," + ((mFirstPidsDumpingStartUptime > 0 ? mFirstPidsDumpingStartUptime
+                        : mCopyingFirstPidStartUptime) - mDumpStackTracesStartUptime)
+                /* temp_file_dump_duration = */
+                + "," + mTempFileDumpingDuration
+                /* temp_dump_request_on_queue_duration = */
+                + "," + (mTempFileDumpingStartUptime - mEarlyDumpRequestSubmissionUptime)
+                /* temp_dump_pid_count_when_pushed = */
+                + "," + mEarlyDumpExecutorPidCount
+                /* first_pid_copying_time = */
+                + "," + mCopyingFirstPidDuration
+                /* early_dump_status = */
+                + "," + mEarlyDumpStatus
+                /* copying_first_pid_succeeded = */
+                + "," + (mCopyingFirstPidSucceeded ? 1 : 0)
                 + "\n\n";
 
     }
@@ -449,7 +542,7 @@
 
             /* anr_queue_size_when_pushed = */ mAnrQueueSize,
             /* anr_type = */ mAnrType,
-            /* dumped_processes_count = */ mDumpedProcessesCount);
+            /* dumped_processes_count = */ mDumpedProcessesCount.get());
     }
 
     private void anrSkipped(String method) {
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index 38632d1..f805bdc 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -1076,13 +1076,6 @@
     }
 
     /**
-     * Set whether the visible password is enabled for cryptkeeper screen.
-     */
-    public void setVisiblePasswordEnabled(boolean enabled, int userId) {
-        // No longer does anything.
-    }
-
-    /**
      * Set and store the lockout deadline, meaning the user can't attempt their unlock
      * pattern until the deadline has passed.
      * @return the chosen deadline.
diff --git a/core/java/com/android/internal/widget/LockPatternView.java b/core/java/com/android/internal/widget/LockPatternView.java
index fc5da13..c3e2fcd 100644
--- a/core/java/com/android/internal/widget/LockPatternView.java
+++ b/core/java/com/android/internal/widget/LockPatternView.java
@@ -83,6 +83,9 @@
     private static final float MIN_DOT_HIT_FACTOR = 0.2f;
     private final CellState[][] mCellStates;
 
+    private static final int CELL_ACTIVATE = 0;
+    private static final int CELL_DEACTIVATE = 1;
+
     private final int mDotSize;
     private final int mDotSizeActivated;
     private final float mDotHitFactor;
@@ -162,6 +165,7 @@
     private int mSuccessColor;
     private int mDotColor;
     private int mDotActivatedColor;
+    private boolean mKeepDotActivated;
 
     private final Interpolator mFastOutSlowInInterpolator;
     private final Interpolator mLinearOutSlowInInterpolator;
@@ -335,6 +339,7 @@
         mSuccessColor = a.getColor(R.styleable.LockPatternView_successColor, 0);
         mDotColor = a.getColor(R.styleable.LockPatternView_dotColor, mRegularColor);
         mDotActivatedColor = a.getColor(R.styleable.LockPatternView_dotActivatedColor, mDotColor);
+        mKeepDotActivated = a.getBoolean(R.styleable.LockPatternView_keepDotActivated, false);
 
         int pathColor = a.getColor(R.styleable.LockPatternView_pathColor, mRegularColor);
         mPathPaint.setColor(pathColor);
@@ -634,12 +639,25 @@
      * Reset all pattern state.
      */
     private void resetPattern() {
+        if (mKeepDotActivated && !mPattern.isEmpty()) {
+            resetLastActivatedCellProgress();
+        }
         mPattern.clear();
         clearPatternDrawLookup();
         mPatternDisplayMode = DisplayMode.Correct;
         invalidate();
     }
 
+    private void resetLastActivatedCellProgress() {
+        final ArrayList<Cell> pattern = mPattern;
+        final Cell lastCell = pattern.get(pattern.size() - 1);
+        final CellState cellState = mCellStates[lastCell.row][lastCell.column];
+        if (cellState.activationAnimator != null) {
+            cellState.activationAnimator.cancel();
+        }
+        cellState.activationAnimationProgress = 0f;
+    }
+
     /**
      * If there are any cells being drawn.
      */
@@ -748,8 +766,9 @@
             // check for gaps in existing pattern
             Cell fillInGapCell = null;
             final ArrayList<Cell> pattern = mPattern;
+            Cell lastCell = null;
             if (!pattern.isEmpty()) {
-                final Cell lastCell = pattern.get(pattern.size() - 1);
+                lastCell = pattern.get(pattern.size() - 1);
                 int dRow = cell.row - lastCell.row;
                 int dColumn = cell.column - lastCell.column;
 
@@ -770,7 +789,15 @@
             if (fillInGapCell != null &&
                     !mPatternDrawLookup[fillInGapCell.row][fillInGapCell.column]) {
                 addCellToPattern(fillInGapCell);
+                if (mKeepDotActivated) {
+                    startCellDeactivatedAnimation(fillInGapCell);
+                }
             }
+
+            if (mKeepDotActivated && lastCell != null) {
+                startCellDeactivatedAnimation(lastCell);
+            }
+
             addCellToPattern(cell);
             performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY,
                     HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
@@ -789,6 +816,14 @@
     }
 
     private void startCellActivatedAnimation(Cell cell) {
+        startCellActivationAnimation(cell, CELL_ACTIVATE);
+    }
+
+    private void startCellDeactivatedAnimation(Cell cell) {
+        startCellActivationAnimation(cell, CELL_DEACTIVATE);
+    }
+
+    private void startCellActivationAnimation(Cell cell, int activate) {
         final CellState cellState = mCellStates[cell.row][cell.column];
 
         if (cellState.activationAnimator != null) {
@@ -803,7 +838,7 @@
             animatorSetBuilder.with(createDotRadiusAnimation(cellState));
         }
         if (mDotColor != mDotActivatedColor) {
-            animatorSetBuilder.with(createDotActivationColorAnimation(cellState));
+            animatorSetBuilder.with(createDotActivationColorAnimation(cellState, activate));
         }
 
         animatorSet.addListener(new AnimatorListenerAdapter() {
@@ -817,7 +852,7 @@
         animatorSet.start();
     }
 
-    private Animator createDotActivationColorAnimation(CellState cellState) {
+    private Animator createDotActivationColorAnimation(CellState cellState, int activate) {
         ValueAnimator.AnimatorUpdateListener updateListener =
                 valueAnimator -> {
                     cellState.activationAnimationProgress =
@@ -835,10 +870,17 @@
         activateAnimator.setDuration(DOT_ACTIVATION_DURATION_MILLIS);
         deactivateAnimator.setDuration(DOT_ACTIVATION_DURATION_MILLIS);
         AnimatorSet set = new AnimatorSet();
-        set.play(deactivateAnimator)
-                .after(mLineFadeOutAnimationDelayMs + mLineFadeOutAnimationDurationMs
-                        - DOT_ACTIVATION_DURATION_MILLIS * 2)
-                .after(activateAnimator);
+
+        if (mKeepDotActivated) {
+            set.play(activate == CELL_ACTIVATE ? activateAnimator : deactivateAnimator);
+        } else {
+            // 'activate' ignored in this case, do full deactivate -> activate cycle
+            set.play(deactivateAnimator)
+                    .after(mLineFadeOutAnimationDelayMs + mLineFadeOutAnimationDurationMs
+                            - DOT_ACTIVATION_DURATION_MILLIS * 2)
+                    .after(activateAnimator);
+        }
+
         return set;
     }
 
@@ -1055,6 +1097,9 @@
         if (!mPattern.isEmpty()) {
             setPatternInProgress(false);
             cancelLineAnimations();
+            if (mKeepDotActivated) {
+                deactivateLastCell();
+            }
             notifyPatternDetected();
             // Also clear pattern if fading is enabled
             if (mFadePattern) {
@@ -1071,6 +1116,11 @@
         }
     }
 
+    private void deactivateLastCell() {
+        Cell lastCell = mPattern.get(mPattern.size() - 1);
+        startCellDeactivatedAnimation(lastCell);
+    }
+
     private void cancelLineAnimations() {
         for (int i = 0; i < 3; i++) {
             for (int j = 0; j < 3; j++) {
@@ -1079,9 +1129,9 @@
                     state.activationAnimator.cancel();
                     state.activationAnimator = null;
                     state.radius = mDotSize / 2f;
-                    state.activationAnimationProgress = 0f;
                     state.lineEndX = Float.MIN_VALUE;
                     state.lineEndY = Float.MIN_VALUE;
+                    state.activationAnimationProgress = 0f;
                 }
             }
         }
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 78d3923..3d72aef 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -5438,6 +5438,15 @@
     <permission android:name="android.permission.INSTALL_DPC_PACKAGES"
                 android:protectionLevel="signature|role" />
 
+    <!-- @SystemApi Allows an application to read resolved paths to the APKs (Base and any splits)
+         of a session based install.
+         <p>Not for use by third-party applications.
+         @hide
+    -->
+    <permission android:name="android.permission.READ_INSTALLED_SESSION_PATHS"
+                android:protectionLevel="signature|installer" />
+    <uses-permission android:name="android.permission.READ_INSTALLED_SESSION_PATHS" />
+
     <!-- Allows an application to use System Data Loaders.
          <p>Not for use by third-party applications.
          @hide
diff --git a/core/res/assets/geoid_height_map/map-params.pb b/core/res/assets/geoid_height_map/map-params.pb
index 8ca032c..6414557 100644
--- a/core/res/assets/geoid_height_map/map-params.pb
+++ b/core/res/assets/geoid_height_map/map-params.pb
Binary files differ
diff --git a/core/res/assets/geoid_height_map/tile-1.pb b/core/res/assets/geoid_height_map/tile-1.pb
index 93a2fa0..c0f1242 100644
--- a/core/res/assets/geoid_height_map/tile-1.pb
+++ b/core/res/assets/geoid_height_map/tile-1.pb
Binary files differ
diff --git a/core/res/assets/geoid_height_map/tile-3.pb b/core/res/assets/geoid_height_map/tile-3.pb
index 4e22ca1..cc30471 100644
--- a/core/res/assets/geoid_height_map/tile-3.pb
+++ b/core/res/assets/geoid_height_map/tile-3.pb
Binary files differ
diff --git a/core/res/assets/geoid_height_map/tile-5.pb b/core/res/assets/geoid_height_map/tile-5.pb
index c5f5127..7e1f008 100644
--- a/core/res/assets/geoid_height_map/tile-5.pb
+++ b/core/res/assets/geoid_height_map/tile-5.pb
Binary files differ
diff --git a/core/res/assets/geoid_height_map/tile-7.pb b/core/res/assets/geoid_height_map/tile-7.pb
index 0928a6a..3bcdaac 100644
--- a/core/res/assets/geoid_height_map/tile-7.pb
+++ b/core/res/assets/geoid_height_map/tile-7.pb
Binary files differ
diff --git a/core/res/assets/geoid_height_map/tile-9.pb b/core/res/assets/geoid_height_map/tile-9.pb
index 6a2210a..558970d 100644
--- a/core/res/assets/geoid_height_map/tile-9.pb
+++ b/core/res/assets/geoid_height_map/tile-9.pb
Binary files differ
diff --git a/core/res/assets/geoid_height_map/tile-b.pb b/core/res/assets/geoid_height_map/tile-b.pb
index 5fce996..fbe02da 100644
--- a/core/res/assets/geoid_height_map/tile-b.pb
+++ b/core/res/assets/geoid_height_map/tile-b.pb
Binary files differ
diff --git a/core/res/geoid_height_map_assets/README.md b/core/res/geoid_height_map_assets/README.md
index 800b3e5..37a57b8 100644
--- a/core/res/geoid_height_map_assets/README.md
+++ b/core/res/geoid_height_map_assets/README.md
@@ -1,8 +1,11 @@
-These text protos contain composite JPEG/PNG images representing the EGM2008 Earth Gravitational
-Model[^1] published by the National Geospatial-Intelligence Agency.[^2]
+These text protos contain composite JPEG/PNG images^[1] representing the EGM2008 Earth Gravitational
+Model[^2] published by the National Geospatial-Intelligence Agency.[^3]
 
-[^1]: Pavlis, Nikolaos K., et al. "The development and evaluation of the Earth Gravitational Model
+[^1] Julian, Brian, and Angermann, Michael. "Resource efficient and accurate altitude conversion to
+Mean Sea Level." To appear in 2023 IEEE/ION Position, Location and Navigation Symposium (PLANS).
+
+[^2]: Pavlis, Nikolaos K., et al. "The development and evaluation of the Earth Gravitational Model
 2008 (EGM2008)." Journal of geophysical research: solid earth 117.B4 (2012).
 
-[^2]: National Geospatial-Intelligence Agency. “Office of Geomatics.” 2022.
+[^3]: National Geospatial-Intelligence Agency. “Office of Geomatics.” 2022.
 URL: https://earth-info.nga.mil.
\ No newline at end of file
diff --git a/core/res/geoid_height_map_assets/map-params.textpb b/core/res/geoid_height_map_assets/map-params.textpb
index 5ca6e4e..170e73b 100644
--- a/core/res/geoid_height_map_assets/map-params.textpb
+++ b/core/res/geoid_height_map_assets/map-params.textpb
@@ -3,4 +3,4 @@
 disk_tile_s2_level: 0
 model_a_meters: 193.0
 model_b_meters: -107.0
-model_rmse_meters: 0.29
+model_rmse_meters: 0.27
diff --git a/core/res/geoid_height_map_assets/tile-1.textpb b/core/res/geoid_height_map_assets/tile-1.textpb
index 7edba5b..b0c8044 100644
--- a/core/res/geoid_height_map_assets/tile-1.textpb
+++ b/core/res/geoid_height_map_assets/tile-1.textpb
@@ -1,3 +1,3 @@
 tile_key: "1"
-byte_jpeg: "\377\330\377\340\000\020JFIF\000\001\002\000\000\001\000\001\000\000\377\333\000C\000\004\003\003\003\003\002\004\003\003\003\004\004\004\004\005\t\006\005\005\005\005\013\010\010\007\t\r\014\016\016\r\014\r\r\017\020\025\022\017\020\024\020\r\r\022\031\022\024\026\026\027\030\027\016\022\032\034\032\027\033\025\027\027\027\377\300\000\013\010\002\000\002\000\001\001\021\000\377\304\000\037\000\000\001\005\001\001\001\001\001\001\000\000\000\000\000\000\000\000\001\002\003\004\005\006\007\010\t\n\013\377\304\000\265\020\000\002\001\003\003\002\004\003\005\005\004\004\000\000\001}\001\002\003\000\004\021\005\022!1A\006\023Qa\007\"q\0242\201\221\241\010#B\261\301\025R\321\360$3br\202\t\n\026\027\030\031\032%&\'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz\203\204\205\206\207\210\211\212\222\223\224\225\226\227\230\231\232\242\243\244\245\246\247\250\251\252\262\263\264\265\266\267\270\271\272\302\303\304\305\306\307\310\311\312\322\323\324\325\326\327\330\331\332\341\342\343\344\345\346\347\350\351\352\361\362\363\364\365\366\367\370\371\372\377\332\000\010\001\001\000\000?\000\262zRf\212\007Zu(\251\005H\2652\324\311V\022\247Z\235*e\251\222\247Z\231jU\251V\244Zu\024f\220\232M\324\231\244-I\232B\307\322\232Z\223i#\"\233\234\034\0328\244\243&\237\237Zr\346\244\000\323\205H\0058\n\\R\3654\361\322\224\032p4\340i\300\324\212\325\"\340\323\2155\272Tg\255 <\322\226\246\226\2463S\013\363F\372]\374SK\322\007\346\245F\342\244\025\342\346\233E\024\341J:\323\326\245Z\231jt\251\323\255XZ\231je\0252\212\231ML\246\246Z\220\032\221i\331\2434\224\204\322S{\322\036\224\224\205\211\\SW\2574bEl\2575\031fc\222)A\347\232w\031\340\361G\000\365\247\003O\rO\014i\331\315H\254E<\034\323\207\265.9\247t\242\2274\240\322\346\236\255S\241\342\236MF\315\357L&\233\232\t\240\221\212\211\232\242-\315\033\275\351\273\351\013P\036\247\215\376Z\234\034/5\343\004\322\023H\r-\024\361\326\236\265*\232\231jt\251\322\247J\235je\251\224\324\313R\251\251T\324\202\244\007\212vh\315\031\244\2434\204\323I\246\223M\310\246\232h\225\220piRp\017\314)\306H\335\260\026\214\247\360\3233\3158\032p5\"\232\221MH)\343\332\234\033\035i\343\004qF}h\006\226\212Pi\301\260je~)\305\3522\336\364\322\334sM\335\2323\315-D\346\240f\346\232Z\232^\215\364n\253\020\277\025+\310\000\257\035\311\240ry\240\364\240\032Zx\251\007Z\221EL\2252\232\235*u\251\320\324\313S)\251\224\324\253R\n\220\032\220\032vh\315\'z3A<Rg\212i4\204\214t\250\211\244-M&\231\212Q\3058R\216\224\341\232\\\323\301\251T\324\240\323\301\247u\342\200YN)\302\215\330\247\007\006\235I\232@\334\324\252\334R\226\246\227\246\026\244\rO\rKQ\277J\254\347\025\021zaz7R\356\342\245G\302\322\264\231\257*\"\222\202h\034\323\251\343\255H\242\245Z\231jU\025a\027\212\231F*e52\021S-J\265*\234T\252i\352j@iwQ\272\214\373\320Z\2234n\246\356 \346\232\316MFi\244\342\233\232L\322\203N\024\341\322\234)\302\234*AO\006\236\r<\037\232\237\273q\311\244\247u\024\230\247\200\343\2474\243\334b\220\216r:P\033\024\027\365\246\356\246\226\240\032\221M<\232c\364\252s6\rUg\346\232^\223\314\243\314\367\247\254\334rh2\361^i\272\214\322\023B\232z\234\232\224\n\231*P*E\025*\234T\252\030\377\000\026>\225(\007\373\325*\023\353V\020\361S+T\252jU5 5\"\232~h\335\357F\352\003\016\364\233\271\353F\341I\272\202i\244\323\016i\234\236\224\234\203I\232u8S\201\247\216\224\360)\340S\300\245\002\2368\247\016\264\352Q\326\2342jE\\\232\230\014\014S_\221\305@Cf\233\363\003N\003\"\232\300\212a\244\3158>;\323\204\224<\200\255Q\235\252\243?4\302\364\322\364\236g\2754\313\317Z_7\216\265\300?\006\232\t\024\271\006\224T\212jU<\325\230\300\253\n\243\034\212pL\373R\355\307J\221jU5 <\324\252\336\3652\265L\257R\253\324\201\252@\324\355\307\024\273\250\335HZ\223u\033\2517P[\320\322n\242\233\310<\032NM\000R\323\200\247\001O\024\360jE4\341\214\323\307Zp\245\243\245<T\252\005L\253\212~)\245N)\244c\232\205\310\31593\216iv\347\255E\"c\245W9\006\231\232]\330\244.MT\235\273\346\2523\324e\351\273\351\245\352\'|R\244\231\025\305\023\223IHr\r\001\252UpE<75f)\010\034\325\224\22350\222\2246i\342\245^\224\360jE5*\232\225MJ\016*E5\"\265?4\340h&\220\232i4\231\2434f\234\r)\007<\032OcF9\245 \367\245\013\3058\np\024\264\341\322\234)\342\236)\342\234\005\030\247(\346\254\306\230\0315*\017\232\244\333\351M \346\243d&\205\203\234\232\220D\000\351Mh\317\\Tl\231\025NT \364\252\304\235\324\322\334S\013\361U\'z\246\317Q\227\246\357\244/Q3f\221\t\316+\223\221J\2754\032S\3154\216x\247(5\"\236jun*dc\232\235[5(8\251A\251\003qN\006\236\rJ\255R\253T\252\325\"\265H\032\234\032\236\r;9\246\223II\2322is\232QN\000\203\232R7\037\224\032r\200\243\346\024\273O\336\0074\243\2459S4\270\346\227\024\240S\200\247\201O\024\3409\247\201\305<-=\023&\247\035p*E\300\251\343\\.OSK\205\'\2457\n\r!#4\271\002\224\200\313\300\250$\\\n\251&;\325\t\370\351UKTl\304Ui\216A\252n\370\250K\322o\246\227\246\027\346\245\217\221\232\346\344L\216\225U\220\251\342\223\232@y\247\003OSS)\251\221\252elT\252\365*\3101\357N\017N\017R\006\251\025\252ej\221Z\244V\251\025\252@\324\360\324\360i3\357IE\024S\201\247\212x\343\356\232P\t\357OS\267\202)q\316@\251c\311B=)\240\035\334\323\261\305\000S\200\247\205\3434\340)\313R\001O\003\0252\214.iTsR\2049\315<\265&\363M-\357H\033\234\320\322g\232\226\031=j\033\231{-P\221\2169\252\223\034\245Rf\305@\357P;eMQrI\250\230\323wR\026\250\367\022\370\253h\300.3XL\274\361Q2\003P\264>\225\t\\\032QO\002\236\265*\232\225Z\244\rO\017R+\323\303T\212\325\"\265L\255R+T\201\252@\325 j\2205<\032vi3Fh\024\264\341O\024\341OZ\220s\326\234\020\366\247(\303zT\214\271]\324\301\310\245\002\234\005<\nv)G\025\"\324\350\271\247\037Jz\216i\345\305D\317\317\024\240\320\302\243\3174n\247\243\205\006\243v\004U\031\334\n\253+\374\237\205g\273\363U\344j\201\244\302\325fl\232\211\2150\266)\214\374S\021\263%X\335Y\244f\243*)\207\203\203P\315\037q\322\240\034\032\222\234\r<5<5H\032\234\032\236\257R+T\252\325*\265J\255R\253T\212\325\"\232\221MH\246\244\006\235\2323K@\353N\247v\247\216\264\361\322\234:\324\202\236\017j\221@\245l\343\255 \245\247\016\224\240\323\201\247\016\265\"\364\253\021\364\247\001JA\315#\003\212\21384\273\360i\032aL,)\245\361M2\212C(\332y\346\263.f\303\021\232\255$\277\'Z\246\317\223QH\337-Uw\310\353P\027\250\331\3522\365\0337\024\261\260\034\323\332Z\246\030\021Q\273sL\311\2458)U\230\r\324\242\224S\3058qN\006\224\036i\341\251\352\325*\275L\255R\253T\252\325\"\265J\255R\251\251\024\324\252i\331\245\245\024\264\352p\247\016\264\361OZx4\3655 5 \346\220\251\006\224\n\\R\343\024R\216\2652U\205\030\025*\200z\322K\305Dd\355Q\226\025\02374\306jn\376:\324O6\017Z\215\245\'\241\250ZfPsT&\230\273\342\241\226L\014f\253\0319\250\344\227\212\246\362u\346\253\264\2304\322\371\031\250\332Za\222\2177\024\246L\214\325E\223\035\351\036NsR+\202\264\021\201\327\255V|\206\240\003\214\322\203O\006\236)\302\226\224\032p4\365j\225^\246W\025*\265J\255S+T\252\325*\232\225O\275?4\240\323\201\245\007\326\234\r8\032x4\361N\024\340j@i\340\324\210qR\251\007\255?\313R3Q\036\030\342\214\322f\224\036jx\3175eO5:\021Q\314sUX\363L-\305D\355Q\027\250\236Oz\254\354}i\242LTo #\255Sb7f\252\315\'5\\\275A,\274UG\227\336\242i\006:\324M)\035\352?2\233\346d\320\315\315;\177\000T\000\363Crz\320\254T\342\245\r\221\212\0317\034\212v6\'_\302\221Dl\331\'\025 H\313\3434\245\027\034\032\0008\245\246\321N\006\236\rJ\255S+T\252\3252\265L\255S+T\312j@iA\247f\2274\240\323\203S\303S\301\247\202)\340\323\305<\032x5*T\352p\265\024\204d\324Y\2434\345\353V#\367\251\325\252d<\323d\252\256y\250Y\261P\274\225\013\275@\317Q3f\240w\252\354\347\326\242y\224\n\255#\206\351Udb*\243\266MT\225\231MW\363\2114\326zo\231\332\200\3376sJ_-O\r\315@\254jL\323\360\010\3159x5*\021I8\314y\035\215B\265 \251\026\244RGJJ01M\242\234\rH\246\245SS)\251\224\324\312je52\237z\224\032x\351KK\232Pi\300\323\201\247\212x\247\003\212x5\"\232\221ML\255R\206\342\243\2238\315F\304`b\2234\3655b3\362\324\240\346\245V\305\016\331\025Y\201\316j\254\274UV|\032\215\237\212\201\232\243-\305D\3075^CT\344\004\363U\367`\234\232\255$\234\021U\332@\rE#\007Z\252\300)\250\030\363L/\212E\2239\247\253\367\247\t~j\007\002\234\016jD\315J\007\024\240\363@\2339\\f\232\230\363>a\200i\347\001\270<S\224\324\200\321E6\223<\322\203R)\251T\324\312jd\251\226\246Z\231ML\206\244\000b\226\212QJ:\323\3058\032x4\340i\300\323\303T\212\325 \'\265H\036\235\2735\033d\232Jz\365\251\324\340S\325\352@\374u\2442b\242\222Q\212\247+\346\251\273sQ<\234T\014\365\013Hj&\227\025\021\2235\033\234\255T\224\000\0175A\330s\315U\221\252/3\006\242\226QQ\026\004Ui_\024\304\223\t\365\246\375\243\007\255)\271\\guh\032\027\255L\214=jBhS\316i\222\355Q\271\0174\304\220\223\317509\247\216)\340\323\201\2434\322i)EH\2652\212\231EL\202\247QR\250\251V\246J\2234\341E(4\264\242\236)\302\235K\232pjpjz\277\275H\036\224=8H1\31580\'<S\324\323\311\3158\032C&;\323\014\325\013\276{\325y_\212\250\317\311\346\241g\250\231\205W\221\310\350*\263\313\307Z\214I\223CK\205\252\027\023\222N\rS\337\317&\240\220\344\361Udb*\006sM\363q\305C;esQ+|\225\033\2675\0236Mt\'\030\246n\301\245\014sS!\312\340\324\212p\246\253\311\222i\023\212\260\255\305H\r8\032p4\036\224\224\231\247\n\225\005N\275*U\251\220T\352*U\251\007\025*\232x4\360ih\242\234)\300\323\301\247\003KFh\315858=;}\033\351C\034\360j\314o\362\324\313\3174\346#\025]\3175\021j\215\236\253\312\374UFj\215\232\241c\212ia\264\346\250L0\331\035*\0030Q\357U$\273b\330QU\336B\300\222j\r\304\232B\340.*\263\221P9\025\003\036j9[\344\300\357Q\226\332\270\250\031\351\253\226l\n\337/\221L,jx\376\340\251P\214\323\367u\024\306\031\031\246\016)\352jU5(\245\242\212)\313R-L\246\246SS\241\251\226\245Z\225M<\032x\353N\006\234\r-(\305-(\353N\006\2274\271\2434dQ\232pj]\324\006\251\024\363VT\345*TlR\261\342\253\273\032\211\232\241v\252\3225Wf\250Y\351\214\374Uws\353U\335\361\326\250\314\303\250\025P\221\232\211\334\364\240\020\027&\253\263\356$\324\014\325\021aQ6*\274\215\206\252\357!4\221\256\366\301\251B\210\316\354\216+S\'4\365\344\340\324\350s\305?\030\247t\245\352\271\246\232QR\255H:S\263FiiE8T\213R\250\251\224T\312*e\251\226\245Z}8S\251\303\2458t\247\0026\343\037\215\024R\366\245\243>\364g\336\214\373\322\344\321\232\001\315(\251\026\254\306\374`\324\312A S\330dqU\335MB\300\212\201\311\252\322UGnj\0265\0137\025\0136*\274\217U\334d\032\245(*I\355P\253\203L\232LGU\321\2629\252\362Hw\034TE\351\273\252\tOz\204\340\214\323\343tT9\034\324/&{\327B\0004\323\303T\221\223\272\247\006\221\211\333O\207&>iJ\234SFsR\251\251\001\002\215\324S\201\247\003O\025\"\324\253S\245N\242\246QR\250\251@4\352p\351N\006\234\016i\302\235E\024f\223\"\214\321\2323FiA\247\003N\247/\0252\232\260\277w4\365n)\030dT\022\014\n\251%V\220\360j\213\236M@\315P\263\32426EUs\203Q\263\325i~l\212\244AI)\263\214\307\232\256\271T\252\362\017\232\2424s\212\206f\001\rW\017\362Tm\'\275F^\272d\223\006\244\300nE9A\006\245SO#\345\247D0*P8\366\250\317\r\322\212viA\247\216\224\341\322\224t\251\026\245Z\231\005N\202\247U\251\224\032\225EJ:R\201KJ:\323\205<S\203)\0351FG\255&A<\323I\244\315\031\367\243>\364g\336\2274\240\323\201\247\212\220S\324\325\210\337\214T\203\031\247\026\025Vw\002\250H\375j\254\217U\034\325gnj6\344T\016\330\025^S\221\305Vf\346\230\306\252\312\t4\222\200\260c\271\252\255\220\2435\004\225\rG#\200\247\332\250M1n*2\377\000-FZ\232Z\272Ez\2367\307z\262\2445J\026\236\027#\025\"\256*`\277-1\343\371O\265C\216h\247\003O\024\341O\002\244Z\225\005XAV\021ju\025*\212\225EH\242\237\262\215\270\243\024\240S\200\245\034\036\224\224\206\222\220\201\214\346\222\214\212L\322\346\2245<585H\032\236\24752\034t\247\211>j\032L)\252\023\312I\252\216\365ZG\252\316\325RY>n\265\027\235\216\365\014\222g\245FN\027&\252\310\3377\024\3259\240\200MD\350\031\306O\002\253\334\340/\025M\216V\240c\212\2551%H\252.1Q\026\246\026\246\226\256\221O525Z\211\252\354|\212\220qR\246\rL\005+/\025NA\363`Spi\303\232\220\np\353OZ\225EL\225<b\254\245N\202\247U\251\025jUZ\223\034Rm\366\244\333K\266\214R\342\223\024\205i1\355HTc\"\230\300c#\2553\"\214\321\223@4\340\324\340\324\360\365\"\275L\217\305!\177\233\255$\222\215\225\237,\234\360j\273\275V\221\352\273\311Ud95^C\201U\374\314\034\032Vo\223\031\252\314\017Zb12b\211$>f\325\374\3526c\236\264\307 \214\032\247\"\340\222*\263\236j\t8\346\250\315\326\2531\346\230M0\232\351\325\252U5j#W\243<\n\224\036je\004U\204\351J\307\212\250\313\363\023M\332i@\247\201O\003\232xZ\225V\245E\253\010\265a\001\253\010*u\251\026\247QO\306h\333F\332LR\342\223\024\270\243m!Zc-FS9\305FGjm74\271\243w\322\215\324\340\364\360MJ\257\201\315D\322e\372\320\357\362u\252R?=j\007~*\244\262{\325W\226\240iy\353Lw\371j\224\214wR\t\t\342\245\004\0049\250\027\345\311\365\244<\032c\021\214\325Y\030\226\246\220JUiGz\247)\340\325)\016j\263\036j2i\205\253\246CS\251\2531\032\273\033t\253+\311\253\013\322\244SJ\307\010j\034R`R\205\247\205\247\005\251\024T\252\265*\255N\202\254 \253\010*e\025*\250\305J\253R\000i\330\"\212L\nLRb\226\227\024b\202\265\013!\007\336\241e \221Q\221\3150\212CM\315\0314\252y\253)\214S%|US)\337Oi>^\265U\337\232\2554\230\025FI3U\245~8\252\215!\317Zo\230}i\216\331\246.wT\305\3601L<\324r1\034T,\334b\242#\346\247\201\362\325i\2078\254\351\007\316T\3259\0075U\3705\003\032c\032\351\34395i\007\031\2531U\2658\305[\214\346\246\007\212ps\234\016hi\0161\212@\t\245\002\244QO\013N\013R*\324\212*U\0252\212\235\005XAV\024T\252*E\025(\024\374qI\217jiQM+A\007\322\223\221\332\224\032wZ\010\250\310\367\250]y\315B\302\243 \342\230i\206\212\013\005\024\345\233\013P\311)c\305E\273\236i\036O\226\252\311.*\234\222\363U^Z\254\362Uvl\232izM\331\247\240\346\236\352w\001I\322\241\227\223P7Z\\\0023K\3749\252\3569\315P\270\0309\252.2j\254\334f\252\265D\306\272\270\2075eH\305O\031\346\256\2475f>\225(`x\315\n\3309\025&\355\303\232r\021\267\004S\306\010\351NQR\001\3058\n\225EH\005J\242\246QS \253\010*d\025:\212\225EH\243\212v)(\"\223\036\364\230\244\305\030\024\270\244\"\232W\332\242e\250Y0j2\274Tej2)\216v\364\250\276f4\216p0)\231\310\300\246\266@\305Wv+\326\251\315\'5NG\367\252\316\347\326\241g\305@\317\223\232n\354\232z\363V\241\\\265X\362\376f\315Wu\305V\222\240 \232pS\214R\200X`Tr.\334\203Y\367\0309\252\014\270\315Q\233\255@zTO]dq\232\260\221\346\246E\000\360j\322\034\016\265\'\233\306\005<1\305=Z\247S\232\221jQR\n\221EH\253R\252\324\201MH\240\372T\252\017\245L\202\246Pj\302\n\231EJ\242\245Q\3058\322R\021IHE%\024\240\322\322c\212c(=\252&OJ\215\222\242d\250\231*\023\031-Mq\261p*\"7P#\3052A\305Q\236\263\346\357T\244lUs\'5^I2j=\324\003\315XJ\267o\367\305]+\3015Ra\326\251\275G\336\235\203\267#\255\021r3\336\241\270\357Y\263UV\350Ef\3160\306\253\032\215\353\264\034\016)\305\2601J\214sS\253f\246B3\315XF\\T\2523S*\324\312\206\245X\315L\261\032\225acR\254,*A\031\025*\217j\220/\265H\240T\312\005L\2121S*T\252\010\352*E\346\245\002\226\223\024\224\204SM%\024\240\322\322f\220\323H\246\225\250\33103Q\024\250\332,\034\325yP\356\246\254}\315\016\000Z\253)\300\254\371\233\346\254\373\206\306k>F\316j\253\232\204\365\244\3159z\325\210\375*\354#\004\032\272H+\326\250\314y5U\2075\0369\251TR\005\333\237z\255q\315gL9\252\222U9\323p\315Qq\203\212\211\253\262\'\271\246\007\311\353R\206\311\342\247CS\241\251\322\254!\253\010jt5a\005N\200\325\204\025:\212\220-H\020c\245;o\265(@}\252EC\354EH\247i\301\006\254&\017z\234\001\212\000\346\2348\245\315.E%%!\024\322)(\244\315\031\2434\224\207\255&3Q\262\342\243c\306*\264\202\231\310\024\307\351T\2478\252\022u\315g\\r\325JA\216\005Uq\315FV\243\"\244J\262\235j\344<\232\232L\256\010\351U\344\344\324.\225\001\004\032\2263\232\220\250e5Fq\265\2105BaTe\025]\271\2527\t\203\232\252\334WZd\3341\332\204\305N\203\232\260\265:/5a\026\247E9\253(\207\322\254F\206\254\242\032\262\210jtCS(\305J)\343\351N\030\247\355\006\224\002:\032pb\01752:\036\243\006\246\016\244p\324\340\376\242\227z\323\201\007\275;\212m\024\231\244\310\246\320Fi\264SsK\232J\003`\322HK\235\330\250\010\346\241)\227\244 \n\202\\sY\363\214\325)\001\301\254\371\207&\251\272\325w\034\324l8\250\312\323\220U\230\305Z\210\342\2452\014r8\250\030\203\322\233\326\241e\347\002\236\027j\032\003|\231\252s\034\223\232\317\233\031\252\222\n\254\313\203U\346M\303\245P\225\0105\322)\251\320U\204\253\010\005XLU\230\352\312U\230\352\312\n\262\202\254\240\251@\346\244\002\236\005<R\201O\031\002\227\232p\346\224\002)\343=\252E&\246P\017Zw\2261\307\024\273\010\357I\226\244\311\240\020iqL\"\232i3KM<Rf\220\232)\301\366\241\030\353P\232i\344\324N\016*\254\202\251\3123\322\252H2\265FX\372\325\031\220\201UXz\324X\313b\224\246hX\352\302.\026\244Q\315I\214\212\257\"\230\337\330\321L\311\r\232qrA\367\246n\371H\252s\232\244\352I\315WqP2\324l\234U)\342\311\255\204\253\tS\241\253\010j\302\032\265\035Z\214U\230\305Z\214U\250\3075ajU\247\212x\251\007Jp\024\360)\341x\245\013\315<(\247\204\247\205\251\024{S\300\245\3078\2451\323J{Sv{SH\"\233\311\355HE4\212LzSI\246\037jU\004\366\251\226/j\036<S<\222\312O\247j\215\323h\250\230qUdL\325g\217\212\253,Dv\252r\307\201\322\250\313\036j\234\221TB\022\016qO\362\370\245\t\355K\217jQR\003\362\324S\034\255F(`1\232\215\251\204\360j\254\234\212\256\303\003\025]\327\255@\303\006\243a\305U\225kEML\206\254\'5a*\314uj:\265\035[\216\255G\364\2531\375*u\351R\255H*@*@)\341y\251\025i\341i\300S\200\247\250\247\201R(\247\205\346\246\216\035\307\245O\366p\0055\340\030\342\2431c\265D\321\344\342\232 \357H\321c\250\250\232<r*=\225\033\2550/5b4\025)!F)\204\346\205\004\036\234To\031,r8\250Z<qP\264jj\007\214\n\251*\212\245:|\207\212\314\221O5Y\227&\220\307\306i\270\307\024\322)\247\212h\353O\355Ln\224\3209\245#\345\250\030qQ\036\224\302\231\025\003\247\025RAUd\246u\030\250d\025eNj\302qV\020\325\204\2531\325\250\352\334un:\267\020\253+\322\246QR\250\251\024T\213R\255J\242\245QRm\310\243\034\323\200\251\024S\302\324\212\265<p\222j\332 Q\300\247\342\230\302\230\313\305FT\023\322\215\234R\025\2464c\322\2430\003\322\253I\003g\212\207\311pzT\252\254\243\221Mm\304\323\221\016*Lq@\\\216\177\n\257\"\374\325Y\301\006\253\270\252\322-S\231r\270\254\331\223\232\254W\006\223m0\240\315G\"\340T\007\255*\255/C\212G^*>\235iKdb\243q\301\250\302\360(\333\301\342\240\220s\212\2472V|\243\346\250\372TrT\310y\315XCV\022\254\307VR\255\307V\343\253q\325\310\352\302\324\313R\251\251W\221R(\346\245\003\212\231\005J\007\031\310\251\027\2458\npZxZ\225#,p\005\\\212\330\377\000\025X\010\007\013R,t\245\016zS\030sQ\260\250\217Z)\r0\344\322\n\010\006\230c\036\224\323\036i\206!I\267\024\323\326\230[\024\326 \365\353P8\007\245W\221\0063T\345\305S\224dU)P\223\322\2534\\\323Lx\024\306J\202E\315E\345\363N\330\0051\2074\323\234Tei\241y\2472dSD\177/\343HS\202*\274\251\212\2457B*\204\211\363T,\270\250\034f\244J\260\225e\rY\216\255F*\334B\256G\305Z\215\200\253(\342\247G\0252\276jecR\253\032\231X\324\252ML\225:\032\220\014\366\247\216\264\365\034\324\310\271\355W\355\242\001rEN\370U\342\210\372T\352)\314\006*\263\236j\"j&4\235\0050\2657w\2757w4\340x\2434\231\3074\306zo\033y\250\3109\342\243j\214\363Q7\326\253\271\355T\345\3435U\310\315W|T\004\014\323\030\003Q\262\361Q\030\375i\205EF\302\242aM<\323H\244\013\315=W=\2516b\232G\315\232\212Xw\216+>X\212\223\221Te\\\036\225U\224\324L\224\211S\241\2531\325\250\301=\005[\211I\253\221\200\rYCV\025\252tj\231\rN\206\247F\251\320\324\311S\255J\265:\021\221\236\225 ~\010\035\351\350y\353V\341@y\253\221\306\243\034U\225\340qNe\310\024\252\273E;v)\013\361P9\250\311\3151\263L=)\215L5\031\340\323\325\270\245&\232M  6M8\220\335(\030\025\004\243=*\273\n\211\201\250\034Ui\024UGJ\255\"T\014\244S(=:Tdf\242u\301\250\212\324L2x\240&\0055\2050/52.\006\010\241\2075\033.W\216\324\3022\236\365Ja\234\326|\221\363\322\253\264Y5\003\307\216\325Y*\302.j\334J*\344C\247\025i8\351V\022\247J\235\rN\206\247CS\247\326\247J\260\225:T\312*u\024\376\264\365\0252\212\277m\234U\261\326\245CS!\005\262M=\260G\025\031\024\303Q7Z@\0055\2526\024\302)\204S\010\246\034\203C7\025\031s\232p<S\267Q\232c\032\201\270\250\230\324\017\315Wq\232\205\326\253\262T\017\035Dc\024\302\206\230V\243e\315B\302\230#\311\351JS\025\023.\005\010\243\034\324\204c\232n3I\264}*\031\020\250\310\252\262&\340H\252\222E\355U\332/j\206H\375\253*1W#\025n!V\322\246SS+\212\231\034\324\350\306\254!5a\rXL\325\204\025e\026\254\242\324\352\265(\251\025jUZ\225E^\267_\222\254\005=\252P\010\245\004\253S\267\232vr)\215Q7Zi4\224\303L\2448\2465F\302\230zTD\032@\330\247\206\247g\212\215\215F\325\003\324-\315F\335*\027\031\250XqP\225\346\232R\230c\366\250\336:\201\3439\250\314|R\354\000t\2462\324,\234\320\027\212i\031niv\236\335)\254\205Wu0\202P\202*\243.\t\250\330\003\324T\016\202\252\310\204\326$jqV\243\006\255G\221V\024\237Z\231jd\253\010j\302\032\260\225f1V\243\025j1VcZ\262\213S\252\324\241jEZ\231V\246H\363WaR\251\315N\010\002\2369\245e\3434\314\322\356\246\226\246\023\3154\322\216\224\311\024\216\225\001&\232X\212\214\2614d\221\212kp*3\3150\212\005<\032\030TL1P=Bz\323\032\2425\033.j\"\274\322\204\243eE\"\014\361P2Te)\2451Q\021Q2\344\323\010\246\021ON\264\254\013\n\215\207\311\214UG^M@\313PH\rT|\203Y\021 \357VPqS-L\2652T\351S\245YAV\243Z\265\032\325\270\326\255F\206\255\306\225j4\253p\300_\245O\366G\331\273\034S|\262;T\212\265:\014U\304\301\\R\201\363T\3109\244\231\200\\Up\334\365\245\335HZ\232M\0034\2439\245<\324l\200\324O\035DP\372P\020\367\2468\301\246m\346\220\216)\002\323\202\320V\241pj\006Z\211\205FEF\302\231\214\323Y{\322\250\342\220\2574\306\\\325wJa\\\nc/\025\013-DV\243+\3150\245*\214\032s)\333\221\322\243a\230\370\252\254\265\013/\025ZU9\252\256\225\216\213\305N\265*\n\235\005N\202\247AVcZ\264\213\355V\243SV\343J\271\032U\270\322\255\306\225i\024U\270\243n\302\257\333\034\202\217\323\025\004\252\276g\3128\241S\212\220\n\236.\2656\337\232\244Q\315A1\313b\240 \321I\322\226\214\320\032\224\034\322\3434\335\271\244+\3050\257\265B\353L\333AZM\274\324\213\036E#\'\025\003\245D\310*\007J\205\224\324L*<\363N\306V\205\0242\324DS\n\212\211\226\242e\2462\361P\272\324Ei\245i\245q\315*\222s\216\206\220\246\024\325G\034\324.0*\007\\\325w\216\260\324qR(\251\226\247AV\020f\254F\265n4\315Z\215*\334IWcJ\267\034un4\253(\265j%\344f\264\003\242\304\002\016{\232Eb\t#\275.3F1K\232\222&;\252\3568\006\244Q\205\252\356\240\2651\220b\230V\230F)\247\245!\243\265\000\363R)\247\205\006\215\234\320c\006\241x\352\"\224\302\264\230\346\246\214dR8\030\252\354\274T,*&\025\023%D\361\361P\030\360h\306\006)\003\001K\301\2462\323\n\324l9\250\231y\250\310\342\242e\250\331*\"\264\233r1B\307\203\200h\223\n\244w\252l;\232\201\305G\267\232G\213p\256\\\037J\225A5:\n\260\202\254F*\324kV\343Z\267\032\325\330\222\256\304\225r5\253(\265:\001V\020T\300\324\253O\310\305!4\016jxP\347&\255\241\340S\363\306)\2453\3154\246*6Z\211\2050\212i\024c\212@9\251\224\014S\2063Ru\240\014\323Y\001\250\2319\250\332:\210\2574\364\024\254*\007\034\324\014)\205h\362\363H`$t\250%\203`\311\025M\306\r3\031\243\024\021I\267\212\211\227\232\211\2075\031\024\302\271\250\331N1Q\225\246\021\212:\014\212\257!$\346\240`j&ZENiYv\255r(\2652\212\235\005XAV\020U\250\305[\210U\310\226\257D\265v%\253\221\255N\253R\255L\246\245\rOV\247n\244\335R#sWc\345EZU\371i\333A\247\005\342\232\351P2\324l*\026\342\242&\233\272\200\3075*\267\025\"\232\220t\247\016\264\354dSv\323Z>3\212\204\307\232\004x\355LaQ2\324\014\264\300\234\324\321G\226\346\254\210\323n1U\257!\0333X\322\'5\036\334\032LsK\267\"\233\214Tl9\250]y\246\025\246\221Q\260\250\312\323Z<\212\213n\001\315B\313\315F\313\305BW&\223n\r6Rv\364\256M\026\246E\251\321j\302-YE\2531\255[\215j\344KW\342Z\275\022\325\264\025(\351J\r=MH\246\245\024\372P\246\244U9\253\360\003\266\256\240\310\247\010\371\351O*\000\346\242a\351P\262\361P0\250\231y\250\331*2\224\230\3058\034\324\211S)\247g\232\225H\247\000\t\251B)\\\032\211\341\002\243d\342\240d\347\245E \305Wa\3154(\315N\253\307\024\356\202\243\224\227\\\032\315\232,\032\247 \250\361\315H\213\236\264\216\270\250\030TdTdPS#5\023%3m#\014-V~\265\031Z\211\206i\241\t8\002\217,\214\223U\2468\004W.\213S\242\324\350\225a\026\254\"\325\250\322\255D\265v$\253\261-]\217\212\260\246\237\232QR(52\212\225EH\242\245T\251\322*\261\031\nqV\025\360sV\222@\313C\014\323\n\324l\225\003.\r@\303\232aZB\224\302\224\3020h\r\212p\223\024\242Z\2327\315YCR\206\024\204\202)\244`T\0220\351U\230d\324.\265\027CSFi\355Q61U&\031\315Q\225j\014sR\245\0168\250Yj\026\\S\010\024\336\224\322)\214\275\351\256>Z\250\313\3151\2050\246)\321\'$\232d\247\002\263\247<\232\347\321*t_j\235\026\254\"\325\224J\263\032\325\270\327\245[\211j\344ue*u\251\000\251\025jE\025*\212\225EL\213VcJ\262\023\002\230\334\032z\260\"\247\214\221\315Y\007\"\2341H\3121U\332<\324\017\036*=\234\322\354\342\230R\240\221y\250[\212o4d\324\210\344T\3511\251\226Q\267\255\006nz\322\031r)\204\346\243\250\334TEy\247\247\024\366\037-B\365ZJ\251\"\346\253\262\340\323\223\216\2643s\212\214\372\324n*-\264\205i\002\363Lp1Q>6\325v\024\2018\245\362{\232G\340qT\345=j\204\375\353\025\026\254\"\324\350\265a\022\254\242\325\204Z\265\030\253Q\212\262\200\325\204\025e\005L\253S*T\202:xLT\212*t\025f>*\302\3621H\321\223\332\221m\244#p\034\n\2364u\352*\302\216)G\006\203M#\212\211\227=\251\276]\006\023Q\274~\325]\343>\225\003E\203\322\231\266\232W\232r\245;\030\243w\024\201\262is\357J)\330\244+\232iJM\274\323\361\362T\016\005Wu\025\001J\255\"\363Q7\024\302i\273\275i\t\3153\034\323Xb\223\024\307^3U\330S\030qH\024\346\236zT2\016*\234\253Tf\025\224\211\305N\211\355V\021=\252\312%XD\253\010\225f8\352\312\'\265YD\253(\225f4\253\n\2252\245H\026\227\024\241Njd\006\247AV\341\031aW\320B\215\373\305\004\373S\036\340.V!\362\237j\222\031\004\213\265\200\311\350iY6\022\010\246\000\244\324\251\010jV\265n\302\233\366V\356)~\314})\0148\035*\027\207\332\253\274|t\252\317\017\265Wx\210\355Q\354 \321\320SX\323I\342\220\034R\206\346\244\0074\361\322\234\005\004z\323X\001M\'\214T\017P0\250\230TN\274UI\006*#\322\230F)\0014\354\342\232\3447A@^*)=*\022\2714\323\031\243f)\030T.*\264\213\236\225Nh\353%\024\021VQ*\302\'\265YD\2531\307VR:\262\221\325\204\216\254\307\035Y\216:\262\221T\341)\341i\341i\301i\312\2252\245J\253S&GJ\230\022\335jA\030\"\247H\260r*|e0y\367\250\0323\273\212\265o\021=MhG\0261\226\006\2440\257aQ\2748\031\252\357\025A$B\253\264#\322\240xEVx\375\252\026\213\'\245@\361\021\332\253\272\324d\032L\032P\2475\"\255L\026\234\006\r5\21534\323Q\270\250XT$sMe\342\252\312\231\252\345qL<\2321M\"\200\224\347\033V\253\260\346\231\263\276)\344q\214S\030s\322\243aP8\250\035y\252\322\245d\306\225j4\253)\035YH\375\252\314iV\243\216\254\307\035Z\216?j\262\221U\230\343\253)\035J\261\023\320S\214%z\322\204\245\333J\242\247U\251UjUJ\220-H\240\212\231\037\024\362\336\207\255.\340\274\232\226\031\001\351\326\255+g\275J\222:\236:U\225uu\301\034\324o\032z\325w\210T\r\020\3061U\344\204\325W\214\347\245Dc\366\250^.*\244\261\363\322\253\262sM\333OU\0252\240\305-\033sQ\262\342\242n)\273\251\244\346\232\313\305@\312EF}\3526\000\324\022G\305W*\001\240\257\313M\003\232\220\000\006i\216\245\201#\265E\260\346\235\345\340f\232\312)\214\265\023\n\256\342\253\271\252\362\034\326tiV\243J\267\032U\224\216\254\307\035Z\216:\265\034uj8\275\252\312GVR:\231S\332\245@C\014\016i\322ng\313\nLzR\0244\345\\T\312*x\327&\255$9\2531\333\307\217\230\323^\020\033\212\210\251ZP\334S\035\216*%\231\243\223\'\245]\212\344\021\326\254\255\310\035\352d\274@z\324\313q\034\202\220\220x\246\025\250\2313P\264c\322\241x\207\245@\361{U)\243\307j\245\"\340\324X\346\234\240\372T\352\016)H\246\236;S\0335\013f\243\"\220u\251\225C\n\212X\275\252\234\213\203P\263\001\326\230\314\245z\324\014E3p\244\030\315?\256\006)\357\030\021\361L\211\006\303\221\310\246>G\025\013S\017J\215\252\t\005S\224sU\\\340\3241\'j\264\211V\343J\265\034uj8\375\252\334q{U\250\342\366\253I\035XH\352\302%L\261\324\210\230l\342\246h\325\227$\363Q\254>\324\246*n\312z\245X\210b\255+`T\250\031\217\024\374\034sMd\310\344\322}\230\323\036\r\275\301\250Z\000{SB\025\355F\342)\3502y5n\027U8\002\254\357\315/\231\317ZB\331\357L$S\030\002:Uw\036\325ZT\317j\254m7\236x\245\026*)\r\250\034\201L1c\265\'\227\355M1\342\242)Q\274|f\253\270\301\250\330\342\232\322\343\220i\032\360m\303V}\315\310\347\006\263d\273ny\250\276\322\347\253R\371\304\236\265<gwz\233\3138\310\240\002\rI\234\361NQ\311\305E\"\363U\335qQ1\250\331\252\007j\253.*\224\207\346\251\"\\\212\271\032f\255\307\035[\216:\267\034un8\375\252\314q\373U\244\217\332\254$~\325:GS\254u(\2134\357+\265\00508\024\315\244\366\245\362\275\251Dx\247\250\305J\270\253\021\266*p7\014To\033\003J#r98\024\257h\3737)\315D\2609<\324\242\333+\202\265\033Y\340\344\nh\267\000\363R$J:\032\234Dv\323\0362*<\021\336\215\304u\031\244\363GB\264\206D\357M&>\271\024\321\345\267JB\027\2650\250\250\2360i\233*6J\217\312\315V\237\344\342\251\261\3115\024\234\n\2434\273sY\323\\\221\221\232\250\316\362\034\014\324m\023\355\316*\234\216\310\324Gq\223W\241\233\241\315_\216\\\212ql\232\001\346\245\003\346\006\211\000\252\316*\007S\212\254\365\003\265U\220\325I\0075j\025\351W\242Z\273\024y\253\221\307V\343\216\255\307\035Z\216:\262\221\325\224\217\332\254,u*E\236\265*\307\315I\345qI\344\346\224A\355G\225\201M1\023I\345\036\302\201\023T\311\031\025:pj\306T\247AUef\317\024\304\231\324\343<\032\263\037\314A\315\\P\010\351JcS\326\242{u5\027\221\203\3059c9\347\212\031{c5\033 \364\250Y=)\214\206\243+Q\224\246\025\244\301\035\351W9\346\235\212M\276\324\306\217#\201LD\344\356\025\235x?zj\213u\250\345\031J\311\271V\347\025\234\320<\215\3005~\322\303\241e\316j\343i\350W\356\363X\267\372n\030\225\037Z\307{w\215\372qR\306\344U\330%\347\031\253j\331\247\003\223W#\031AJ\361df\240h\361U\345^*\214\242\252?\025]\372\325i*\364KW\341Z\277\n\364\253\321\'\025r8\352\334q\325\250\343\2531\307\355VR<T\353\035L\261\324\253\030\025 \216\234\"\311\247\264$.@\315Fb8\311\240F1\315#(\307\024\212\000\034\322s\236)EH\231\316\r\022G\232\205bR\334\234U\310\243\215G\007&\247Q\216\224\343M\372\232C\214u\246g\236)\016sQ\2605\021\0079\246\344\037jF\214\036\225\013&\005FE7o5 \214m\246\272\025\246f\214\322\003\317Z\202\342\331dR@\344\326D\261\354b*\224\315\216\225_`q\234T\266\366\310\374m\255(mUG\002\2476\340\257J\243ub\256\247\345\346\271\315GO(\013(\357Y\277e;2T\323\0226Y+b\332\311\246\217 \363D\226\257\021\346\254Z0\337\264\325\231\020\257\035\252\263\255V\225x\2522\255Q\225j\233\365\252\262\032\325\211j\364K\322\257\302\265~\021\322\257D\275*\354I\310\253q\240\3435j8\352\312G\355S\254u*\245J\261\023\332\245X\375EH\25023J\301G\335\315D\313\236\325\031\\\nL\014sM\362\362h)\212f\010\244\336\303\221L294\334\234\344\232\261n~nj\372\016)\304\nB\252:\324,\240\236)\002\221A\300\024\302\303\025\033u\342\242`sL\311\024\306$\365\246R\021\315N\200b\231*\344\324[i6\212p\2174\214\273T\222+\036\351<\307;W\025B[lu\025\\@T\236:\325\253hJ\234\347\025\247\032qR\021\305B\311\236\242\251\\Y\254\240\202*\221\323\220)R\274Vt\272hY~QV\355\255\244\2152;S\245\371\224\207\034\3251\036\311\262=j\3431*3U\244\372UY\005S\225z\325\031\226\250J1Te5\273\n\325\330\226\257D\275*\364C\245^\210U\330\205\\\210f\256\306\265j5\315YD\366\251\2261\351S\244b\244\021\212\n\016\302\232W\212aZ\214\247\2651\223\006\231\203\232\010&\230\313L+\232n\312p\21354Q\341\205\\QN\013\232k\212\210\216h8\307&\240v\031\300\246\355&\227c\032<\263Q:\360j\002\274\323\010\244\305K\030$\343\322\225\3078\246\355\3158F)v\343\255#\200\313\212\245,Q\2575\235:\202\324\304\2005N\266\3309\251\000#\265;\024\204qQ2\203\332\230c\315Dm\324\266H\240\304\241p\005T\236\327r\022\274\232\317\362\376l\021\322\244+\305B\343\212\251\"\363U\244Z\243:qY\263\255g\312+\240\210U\330\227\245^\211j\364KWb\025v!W\"\355W#\305[\214\032\267\030\253(\265(_jx\034PW\232iZaZn\337Zk \"\2421\234\322yt\326\216\242#\006\234\211\272\245*\253K\031\\\324\312E;x\035M1\244SP\274\250:T\r2\372\323C\202sO\022\201\320R\371\347\260\246\231\030\323H&\232TSLY\035j&B\246\225\034\243S\316\013f\224b\227r\200j\273\317\223\212\004\240\214\032\2539\315Qu$\364\2536\361|\265d\3066\342\243)\201\322\243 \212N:S\017Z1M\"\243a\305FG<Ui\255\201;\324Uf\217\216EV\221*\263\245V\221*\234\310\010\254\313\210\372\326t\251\315oD\265z%\253\321\016\225v%\253\261\n\271\030\253Q\373U\270\205]\214t\253\221\212\262\202\247\002\235\212\010\246\225\244\331HR\230W\024\233\001\2441\342\242a\316*?(\023\223La\267\245W\221\334\367\246\254\314\016\rJ\327J\203\214\223U\336\365\317A\212`\273\220u\246\274\345\273P\204c&\246\0141I\272\224\034\324\253R\205\310\246\262\340\322\252g\024\262F\241rEQ\223ho\226\232d\013\324\342\230n\027\035j&\270\335\300\246\344\232p\006\202\245\273R\375\234\036\325\"\307\267\245?\024\322\007z\205\366\324\rQ19\343\245\033\250\316i\204S\010\246\032\211\343\004g\025NX\210\344UI#\252\322/\250\252\222\307Y\363\305\327\212\316\222\034\236\225\377\331"
-byte_png: "\211PNG\r\n\032\n\000\000\000\rIHDR\000\000\002\000\000\000\002\000\010\000\000\000\000\321\023\213&\000\000\0021IDATx^\355\335\341\212\2030\014\000`\321\367\177\344\311\301q\333A\031\247\363\2646\311\367\375\014\010\352:m\322t\233&\000\000\000\000\000\000\000\310cn\003\265\024\277\374iZ\333\000\000\000\000\300Q\345+-\000\000\000\000}(\303p\217\245\rl\321\232\004\377\341a\017\000\000EH\237\001\000\330\246d\014\000\000\000\014F\271\002\000\000\000\340l?m\305\272\213\241\242\346\233\257\002\013\000\000\334e\270\302\204\004\t\000 \rS;\000\000\000\000\212\233\325\310\000\000\000\000\000\000\200\212\254\225\002\000\000\000\224\240\014\004\000\000\345\331J\013\000\000\300/I\"\000\000\2440\334_[\002\000\000\177z\226\347\217\225\351\277\217:v(\000\000@hR!\000\000\000\000.\245%\027\000\000\000`\014\032\205\000\030]\3565\005ob\000\000\000\000\000\000\000\000\000\000\200\354t\216\003\000\000\000\000\000\000\000\000\000C\323\354\010\000\000\000\000\000\000\360\226\345T\306\023`T.m\000\000\200~\3266\000\000\000\000\000\000\354\241\304\016\000\000\000\347\013\260\005\002\000\200\253\230\014\002\000c\270qV\242\033\005\000\000\340\036\3621\000\000\000\000\000\000\000\000\000\000\000\372\270q33;\330a\000\000\000\244\'1\005\000\000\000\000\000\000\000\200\275\362t\333\344\271\022\000v\262W\2568\003\000\200-\2176\000\000\000\000\000\000\000\000\220\234\336:\000\000\000\000\000\000\310,\302\212`\204s\004.\344!\000\000\000\000\000\000\000\000\000\000\000@\030\232\340\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\200\314\3466\000\000\244\342]_\336\352\2675\253\363\024\000\250\315{\240\270\347\0000\020\330C\352\000\000\000\000\274((\001\000\000\\K\336\005\000\300G\2266\000\000\261i^\007\000\000\000\016RV8\217\366\025\000\000\000z\222\207\2264\373\334\001\000\000\000\000*R\035\006\200\300z\265\354\207\2330\364\2721\000\000\220N\270\331?\347*?\000\242\337\200\350\347\317Q\n!\000\000\000!H\337\030\211\361\010\000\000\000\000\000\000\300;_s\363!1$IHR\000\000\000\000IEND\256B`\202"
+byte_jpeg: "\377\330\377\340\000\020JFIF\000\001\002\000\000\001\000\001\000\000\377\333\000C\000\003\002\002\003\002\002\003\003\003\003\004\004\003\004\005\010\005\005\005\005\005\n\007\010\006\010\014\013\r\014\014\013\014\013\r\017\023\020\r\016\022\016\013\014\021\027\021\022\024\024\025\026\025\r\020\030\031\027\025\031\023\025\025\025\377\300\000\013\010\002\000\002\000\001\001\021\000\377\304\000\037\000\000\001\005\001\001\001\001\001\001\000\000\000\000\000\000\000\000\001\002\003\004\005\006\007\010\t\n\013\377\304\000\265\020\000\002\001\003\003\002\004\003\005\005\004\004\000\000\001}\001\002\003\000\004\021\005\022!1A\006\023Qa\007\"q\0242\201\221\241\010#B\261\301\025R\321\360$3br\202\t\n\026\027\030\031\032%&\'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz\203\204\205\206\207\210\211\212\222\223\224\225\226\227\230\231\232\242\243\244\245\246\247\250\251\252\262\263\264\265\266\267\270\271\272\302\303\304\305\306\307\310\311\312\322\323\324\325\326\327\330\331\332\341\342\343\344\345\346\347\350\351\352\361\362\363\364\365\366\367\370\371\372\377\332\000\010\001\001\000\000?\000\272N)\t\315%\003\212u9jU\251T\325\204\253\021\212\265\025Z\217\245Y\216\254!\2531\325\210\352\312T\311S\255J\225&x\244\245\3154\265&\357zB\324\205\261M\337\232i|SK\nM\245\201\"\243\335\203\315\007\024P\t\024\360\331\034\323\223>\225(\346\244S\315J\006i\340S\261@9\251\007\002\234\r8\032x4\365lT\250\3654x4\362)\2148\250Z\22074\342\342\230\317Lg\342\2432Ry\224\276g\2755\245\244\022sSF\365(9\025\363\253\000i\224QN\006\224u\251P\324\310*\304uf:\263\025Z\212\254\240\253\021\212\260\234U\230\315XCS\245L\246\245Z\2234\233\251\t\315!4\332nsHzSi\031\362\270\246)\311\346\217\2366;y\025\023\312\316\334\212\025\275zT\234g\203A\340\365\245\006\245V\251\026LS\303g\265H\216EJ\033>\324\360)q\3158qKK\272\234\r(j\221\032\254\306jBqQ\263\324D\342\231\273\232\013Q\221\212\205\332\241/\315\'\231He\246\0313@\222\254\303 \307\275YV\343\232\371\330\234SI\240\034\322\321O^\265*T\321\232\261\035Y\216\254\305V\243\253)V#5e\rN\225:\032\235\rL\265*\236)\344\321\272\202\324\332BqA9\246\223Q\226\3057p\24655n\032.\224\261]\000\307p\034\323\336H\335\200\002\202\020}\323\317\245F[\232p4\3655*\232\225ML\264\361OW\305J\274\216)3\353J\r-\031\305(4\345lU\230\344\342\236d\250\231\251\205\351\273\362i\013R\346\241\224\342\2533sL\337M2Ry\224o\253V\256\rXy\200\025\363\331bh\034\232R8\244\006\235R-H\2652\n\261\035X\214\325\230\315Y\216\254\306j\312\032\260\206\254!\251\320\324\253S+T\252\324\374\321\272\220\236h\315\004\214{\323s\3054\232i \203\353P\263SK\323\030\346\230E\000b\236\t4\340i\300\323\201\305H\254jtj\231Z\244V\247u\245Vd4\340I\352iC\340\323\304\200\322\346\215\324\233\271\251Q\270\247\227\250\332Jc>i\003\323\303R\347\212\212L\342\252J\330&\2402S\032JO34\241\370\251\341\227h\315:I\363^\030F)(-B\363O\247\257Z\231\006jd\353S\245XAV\343L\212\260\203\025<l*\314f\254%N\22526*e5*\265J\246\234\036\215\364\273\251\013{\322\026\244\335\355M\337\265\263\201M\222R\303\260\250I\246\026\3057p\244&\200i\352i\353\322\234\264\3403R(\251\027\212\225Z\245V\247\206\033\205H_\314>\224\235\r;\250\244\333\212z\356\0359\024\365 \236F)\214\274\361\315*\276(ix\246\357\246\027\2405K\031\315JN*7\034f\263\356[\006\251<\230\250\314\264\202lR\371\325$w<`\232V\236\274d\265&\352Fj\025\271\251T\3565*\212\261\02758Z\225\005XC\212\2317\036\340\n\235C\001\367\252x\330\364\253Q\267\025a\032\247F\251\324\324\252jUj\2207\275\033\275\351K\320\254\017SM\337\315.\372B\331\357HZ\230MF\304\323\016OJa$\036h\007\024\341N\006\236\246\244Z\224\nz\212\220\014S\224S\307\025 \353N\316)GZz\344\324\212\2315e\023h\244q\301\307Z\252\333\272Td\225<\323\302\356\024\326R*6\244\r\212p\227\035\351\3536id\227\345\254\333\247\254\371$\346\2432S\014\264\236o\2755\2560i~\321\307Z\362\25184\300\344S\213\003@\251\222\247CV\241\000\342\255\242\014sR\010\363\320S\202b\244N*\3021\251T\340\324\350\376\365:>*\304r\325\204\220T\252\365*\275?y\305(z7{\322\027\246\227\243}\033\351\013\373\322o\242\230r\016s\3154\345\217\275\000S\200\247\201J\005J\265*\232\225M<S\307Zx\024\264\271\"\236\246\247E\025:&9\251v\323\031O4\302\276\325\014\230\315\021\222GJ~\315\335j\t\242\307J\252\331\006\243.}iC\342\221\245&\250\335\310q\326\250<\225\013KL2\323L\225\014\222\342\210\347\335^p\355\223IM$\203J\257S\244\200\212\221d\301\253pK\216\265v)sV\004\240S\267\346\236\265:t\247\253b\246F\315L\206\247CS)\305L\257R\243\324\201\251\352\324\023M&\220\2657u\005\250\335J\016i\304\036\324\231\365\240\216iv\236\364\241i\340S\202\323\200\3058t\251\001\251\026\244^\325\"\323\200\315.\332r\255Z\206.\346\254\242\374\330\251v\323XsQ:\023LKR\307&\247[p\007Jk\304Gj\211\342\310\254\373\210\366\223T\334\374\324\322\370\025\031\222\250\335I\212\317y*\026\226\233\346SZJ\202I3M\211\3105\302\314\233\032\230\r)\346\230W\035)\350\rH\207\232\267\033qV#sVQ\263S\251\305L\255S#\361N\006\244V\305N\217S\243\324\310\3652\275J\257O\rR\006\247n\3154\232i4\205\250\335J\016i\300\323\206A\3159\206\343\362\344\232r&\334\356\024\245\t\344\034\212r\340\216i\310\233\251\333py\247m\366\245\013O\013O\002\244\003\232z\216jEZxL\324\221\307\223V\207\030\002\246@\005X\205x\311\247\025Ri\273T\032\t\037J\003\001N 2\236*\264\261\225\035*\204\300w\254\313\240\027$U\006\223\232\211\344\"\252\\6\341Y\322\311\212\256\322S|\312C%Dd\346\245\204\356\346\271\t\242\r\332\251<eO\024\200\232n\356i\301\261R\253f\247F\253\021\265XG\305N\222U\204\224b\234$\247\254\225*\311S$\225:=J\217S#\324\312\365\"\265H\257R\003A<u\246\223\232(\240\034S\201\357R\251\315=r\234\251\247\000[\222y\247\246\027\202)v\362H\351SC\226R1\315 \007w4\375\274P\005<\npN3O\013R(\251\024T\2521S\30603OQ\315J\250s\236\325.\374\014Pe\246\027\367\246\357\347\232W\2275-\274\27185\025\365\300\003\002\262e\220\221\232\243rr\206\263]\261\232\257$\265VI2\rf\312\304\223P9\250\367\322\027\342\2412e\261W\341`\024\n\346\0359\250$\2105W\222\334\366\252\354\205M(\346\244U\251P\342\247C\305L\217R\253\342\245Y*E\223\232\225^\245V\251\221\352tz\231\036\245W\251\225\252Uj\225^\244V\247\346\223p\244\335@\247S\207Jz\361R)\251\024\324\200\006\353OX\317n\225\"\002\255\351R\274{\206\357J`9\024\001\212z\212\221E<\n\000\305L\225b4\334jV\030\342\234\213\322\2462\000*\027\226\205485\036\352M\325$rm\3175\024\256\030\032\316\271p\240\325\t\345\005+.Y95RY*\253\313\200j\233\276MB\355Q3\001Q\264\225\032>d\025l>\000\254f\033\252&AQ\236\016\rV\271\213\270\351U\224\020jPx\247\251\251\025\252Uz\220=<IR\254\225*\275N\217S\243\324\310\3652\275J\257S+T\312\325*\265J\246\237\2323K@\353O\247\016\225\"\323\327\245H\275\252U\251T\361\212\225\006i\314H\\g\212b\212v)\300`S\201\247\203N\035jh\305Y\204p}j@\271\2459\244e\3435\t8j_4\n\036\340TE\3019\246\231\000\246\264\343\2654\3146\236y\254\213\353\2541\031\252\022\334~\357\255Pyrz\324\022\277\313Te\223 \363U\214\265\013\311Q\0313Q\274\234RB\300\034\367\251Z~+=\\\021Q\312\334\324;\251s\225\301\252\222(\rB\363\3059i\343\245H8\247\003NV\346\244V\251\021\352d\222\254F\365:=L\217S#\324\350\32525L\255S!\346\244\317\024S\205-8t\247\212x\355R-H\247\025 5\"\232\225N*U\346\220\241\007\245(\\S\266\322\201\212)\312j\304ui\027\002\247E\315$\377\000-Bf\300\301\250\231\205@\357\203Q\273\323|\337z\206K\235\275\352\027\271\'\245Wk\242\271\315f]]y\217U\246\233\013T\232nz\324R\315\201Y\362\315\311\346\252\274\330\246\03123Q<\375\252&\2334y\373\005)\233\"\250\3071\024\222\315\315>9\025\227\'\2558\215\243=\215S\224\341\261H\240\221\232pjz\265H\246\236\264\264\340i\312\325\"\275O\034\225a$\036\265:=N\217S\243\324\350\32525N\215\232\2245(4\340sN\007\326\234\r=MH\246\236\246\244SOSR)\251\024\324\321\266*u!\272\323\374\220\335\370\250Xmb\001\243u&M(nj\314G\221W\020\363Vc#\212e\313dqT$<\323\013\361PH\365\t\220\324\022M\216\365NYI\357LY\361Q\3130#\255gI\367\263T\256\245\301\252\206_z\255=\306\001\2522\\{\324\017.j\007\270+\336\2423S\014\3314<\231\247\t~P*\252\265+\363MF(q\332\254+\344b\222H\367\340\212\221S\312On\364\325X\335\263\234T\253\002\027\300jS\010\031\301\240/\245.8\246\322\203\212pj\221Z\247F\251\321\352\3029\253\010\365b7\251\321\352\304m\232\230\032Pi\340\322\206\247\003OV\247\253\324\212\302\244S\357R)\251\024\324\212jU54uf3\201P\314y&\240\rF\352ru\253P\365\025i[\232\261\023sI75FS\203U\335\361U\344\224Uw\226\253<\235j\t$\315V\222\\UW\224\372\324\022N\243\251\252s\310\037\241\2522\311\266\251K!cT.\034\241\366\252\206\350\223\214\323^l\367\250\374\332\003\374\302\225\245\311\305=^\253$\206\246\rO\n\010\3159x5<d\032.Fb\317\245VCR\2519\251\220\324\310H<R\036\264\201A\007&\233IR)\251P\343\275L\215V\021\252\3025XF\253\010\325b6#\275N\255\353R/JZ\\\323\201\247\003OSR/\"\236\271\251\024\343\275H\255R\243T\312\325<n*u~*)rG\265D\330\n1\326\230\rH\207\006\255\302j\302\266qS#\342\235#\344U\031\001$\232\251?\002\250I&\rD\362qU\244z\211\237\216\265]\316j\254\306\263\346\311\315T\336w\020MT\232n\242\251\274\270\250eu\221qT$P\246\240w\346\2422b\221&\3114\364\223\'&\244\023r9\244QNV\315M\03152\216)A\301\247\013\200r\270\315E\036\014\234\360*V\001[\203\221NSS+R\236i)\247\212ni\312y\251\024\324\350jt5f3V\022\254Fjt5a\rL\000\247\n)FE8S\301\247\203R)4\360i\352\325\"\275J\257R\253\036\3252\313N\337\232\211\371=)*D\353VP\340S\322J\235d\310\244iqP\3138\307\025\237q-g\313\'&\240y\260=\352\253\313U\336b*\007\270\"\242y\362j\007 \203TfLd\326d\3142y\2523>*\017;\006\241\270\231qU\313\202*\254\362m\250b\233\nNi\r\336\323\326\235\366\325\306s\212\323\'\212E\353Vc\"\245-\201B\234\232l\301c\005\325\271\364\250\222r\307\236ju9\025\"\361R\003\212p4\244\323I\3056\201S%XAV#\025b1Vc\025:\n\235*x\352pqJ\016iiA\247S\205<\032x\247\npjplS\325\352U\227\025(\227=i|\332\221f\035\372\322\202\t\366\251\020\202jRr:\323\203Pf\333Q\265\3005ZI}\352\254\322qY\357)\334y\250\036Nj\006qUg\227\035*\233\317\305D&\311\244y\260\246\263o.\372\340\326i\223$\222j\264\355\270\361T\246r*\253\312sL\373F*\033\2517.j\262?\313QJ\3715\013\276k\253lb\231\273\024\0079\342\254\304\333\206\rK\031\302\232\2531$\323c\342\255F\374T\241\251\340\323\301\245\'\212m&iW\255O\030\253(8\251\320U\230\305XAS\255L\2652\034T\241\251\352i\324R\346\224\032z\232\224\032p>\364\264f\22458==d\247\211(\363)VB:\032\267\014\274\034\325\210\316\341\232\221\210\305T\225\215@\315\212\215\344\305T\236^\rQy95\013\275Wv#\2750\270#\232\314\272\0041+\322\252\375\240 9<\325+\215H\356*\005T\226b\340\223U<\302N)\032@\240\216\365RV\006\252I\212\254\347\232\212y?vEB\033b\n\256\362f\243\004\261\342\272\243&ED\316j\315\277)\315O\033\014\324\241\360H\250\231r3Q\201\212\221\rN\206\246\036\264\3523E%=*d\253\010jx\315Y\214\325\224\251\226\246CR\251\251\026\234\016)\340\323\251G4\270\245\035i\340\342\234\r.\352]\324n\243u8=.\372P\365\"6M\\\214\345*x\237\024\347s\216\265VI\016j\026z\257+\361T\346\222\251\310\370\250\036Z\211\245\025VYOj\253$\236\265\233t\303$\212\317b2Oz\206I{Sc\3062j\264\262nbj\253\311P3f\241sU&l\021\236\225VY\263L\211L\257\212\235b\362\230\267\030\025\267\270\346\236\207\'\232\265\023v\251q\212p\342\2279Za\024\345\343\0252v\251\20585.E-(\247\255J\242\247AS\240\253\021\212\260\225a*d\025.)\353\300\247\323\2274\361\323\232z\221\267\030\346\212)\331\2434g\336\227w\275\033\275\350\335K\272\200\324\354\324\210j\344\022`sV\024\214\214T\256\271\025RU\252\3561Ue5RS\326\250\312\3705Y\332\240y8\252\356\370\353U%\223\255T\220n\316k6\340\024$\325u\220\022sM\236m\261\234U(\344\335\232\255<\330b\005WiM7\314\252\367\r\236j\263`\212|\014\250\030\236\275\252\031&\'\275uACt\246\260\332jH\233\346\253@\346\206c\212[bYM8\241\305 \310\251P\342\246V\035M\033\275\351sN\006\236\r=jd\025:U\230\305X\214U\204\025<b\247Q\212}8t\247\251\247\203\232x\247\321IFh\310\243u&\3527R\356\245\006\236\r:\236\231\251\320\325\270\371PjTs\212G\031\025VU\300\2523w\252s\036\rfJy5Y\337\025]\344\252\362\276zU)_\232\205\245\305T\237\347\310\254\306\006)=\251\2679h\270\252\221\222\212j\254\331,j\006\244\311\002\241\235\200CU\026O\222\241iqQ\264\265\330\305.\rJW\177Jr)SS\241\315HFV\235n\273G\326\254\001\217\245B\300\006\240\032x>\364\340sO\035)\303\245=zT\252*d\253\021\212\263\032\325\230\326\254\"\232\235\005N\264\240S\251GZz\323\307J\2202\221\3374g\035\3512\t\346\230H\024\233\250\335\357I\237z\\\373\322\356\245\006\236\246\244SR-J\207\025j\t\007CS.3O$UK\247\000VT\322\365\252SK\326\250J\331\315S\225\360j\0079\025^F\300\252s\266G\025Q\236\243sT\256F\356i\222\250X9\353\212\244\334(\315W\224\014\032\254j9\037\n}\253.\346\353p\"\241\363p\265\013I\232az\354\022J\263\014\265q\030=L\251R\205\315K\034x\253\n\237-G$\031\007\332\253\343\232)\340\324\213OZ\221F*D\353V#\025f1V\342L\325\224Z\235\026\247AS*\346\244\362\3516b\214c\2658\np\024\341\301\344P}\251\244\361M\240\250 \234\323i2(\310\240585=Z\244W\251U\352El\324\361\234T\242o\232\234\322\340\032\313\273\270$\232\241,\265Ji*\244\222U\t\345\303T\006\343\025\004\323dqP\026\371rj\224\357\363qLV\315#\000x\250f\210\273\001\236\007Z\255z\241S\212\315s\225\252\316qUn\030\3545\227(\307Z\205\237\002\242/Lg\256\301N\rX\215\361W \222\264\241;\226\246P\001\251\343\346\254*\322\262qT\'\\\034\016\265\030\007\2759y\372T\312)\343\212\221jd\025b0*\324C5r!VcZ\260\211S*b\247D\251vqI\266\223fM/\227J\022\227m&)\n\232n\337jk\'qLe\033s\236j<\320Z\223u(jpzxz\221d\305L\222\212\23698\315#K\363u\242I\276J\313\271\233\236\265NI*\234\322\325Y%\2523\266MT\227\201\234\325S>\323\203\322\225\344\3711T\244\311$\212\215$&M\264\263\315\261\366\216\265\013\271\343\232\216F\005pk>d\303\022:U9\0178\252\263q\326\263\256OZ\246\347\025\021j\215\232\2735j\235\r\\\267<\326\234\r\300\253\000\324\350\010\253qr)\354x\305g\310\271ri\233M*\255J\242\236\253\315H\253S*\324\361\245Z\211*\334@\325\310\252\302T\351V#\034T\233ivRl\305\033h\305\033h\333F\332\nTl\225\013G\234\342\242\"\231I\234Q\272\223u.\372p\222\244V5<R\340sQ\311>_\255#Jvu\254\351\244\301<\325i%\342\250O5R\226|w\252\257q\223\326\242\222_\227\255g\314\344\032h\234\236*d )\315V_\221\230\323H\347\'\2551\333\212\245;\222x\250\310,\247\326\252N\274V|\355\220k:w\316j\224\207\346\250Y\2522\330\256\3166\2531\265\\\200\340\326\214-\322\256\247&\254\241\342\247C\212s\034)5T\214\2326\212P\224\360\264\365J\231V\246D\251\321*\314kV\243\253q\016\225eV\247D\025*%L\252i\341H\243\024\205A\246\355\305\033iz\322\355\243m!L\324\016\204\036:\325wB\016\rB\303\006\230E5\251\273\2517S\225\252\334X\305$\322m\034U\027\237\347\251\032o\226\251K&I\252w\023`Vl\363f\251O\'\025A\347 \323|\362sQJ\373\205F\277z\247/\205\3050\362*)X\250\252\357\'\030\252\356\016\352\225W\013T\356G&\262g_\230\251\357Y\323\214\022*\224\243\006\253;TL\325\331\304rj\354c\212\267o\326\264c8\305^\205\262\005YS\3058I\212V\237\345\3069\246.M8\n\221\0275(Jz\245J\211S\"\342\246AV#\025f5\253q\n\265\030\251\321jeZ\231V\245\013\3054\257\265!AL(i\010\366\244\344\036\224\340i\303\232\n\324N*\274\313\3115]\327\035j\0228\2460\250\310\305%.\340\242\236\227\033GZ\202k\222\347\212\257\277\232I&\371z\325)n1T\'\271\344\363T\245\234U9g\315S\222L\232a\223\024\335\371\247\240\311\251dC\362\212L\342\240\27095Q\372\322\355\310\247\014\342\252J>bk2\365pr+.a\270\346\251\\\014\032\246\365\003\232\355\241\\\234\325\344 \014U\250[\232\320\210\356\305]\207\212\2348<\003B\276\016EK\2748\347\255>\"\000\301\025 \003\0359\247 \251\200\247*\324\312\265*\255O\032\325\204Z\263\030\253Q\212\263\030\253\010*d\025:/\024\355\264b\220\212M\264\322\264\233h\332)v\320A\2462\373T\016\231\250\036<T\014\225\023-FV\242\221\266\n\204\226sH\347j\340T@\344qLr@\367\252\322\310T\363T.\246\311\254\351\245\343\255S\222CU\336L\016j\264\222\344\346\243\337\223R\'5n\33170\253\206\034\271\317\245V\2256\223T\3465U\2014\344V\003\024\345\004\256\005C,{3\232\313\274\301\315e\272rk6\344\362j\243s\232\202A]\324\021\032\265\034E\215ZH\366\343\232\273\t\332957\33200*E\220\340\037Z\221\036\254F\331\251\222\247SR\250\251PT\250\2252%L\251R\242\373T\350\rX\215sVc\025f1VPT\350*tSN\"\223\024\204SH\244\"\222\212Pii\n\360j6@{T/\036:T\017\025B\361\324\017\035Wh\3135#\247\224\2759\252\3547\nE\213\034\323&^+>\353\245d\\\023\223Y\323\271\031\252\215/5Zyrj\276\372\003d\325\250\252\375\257\336\025\244S\253\037\245Q\270\035k>^sP\221\315;\034dQ\007\315\223\336\241\274<\032\307\270\311\006\250\260\3005\221x0\306\251\023QHx\257DQ\264S\367\355\036\364\251!\315ZI2*\304m\223\315Z\215\227\025:\000OJ\2368\352\302Fjd\210\325\204\204\232\235-\330\366\251\222\335\207j\235b#\265M\032\324\252\2652(\251\321\005Y\215*\302GS\252\221\332\245Nj\300^)i\010\315!\030\246\221LaIE\000\342\235I\232C\3151\2074\306J\205\342\357P\264y=*\'\203\0075V\3423\221Q$9\346\234\352\000\252S\234\n\313\271nk*\355\266\346\262g\223vj\214\255\212\254\304\223M\3159:\325\270\273V\215\262`\203Z|\025\353Y\327\'\004\325\t\0075\0163S\"\322*lb}j\255\3379\254\213\232\2417\025B\3557\214\326\\\243i5\003\362+\320\311\246y\233\232\245V\007\030\2531\032\263\031\2531\366\253q\034U\270\315Z\214\325\250\305Y\214U\270\205YE\366\251\202\003\332\245XA\035)\3020;S\204@\2368\251\02221\320\324\350B\036x\253q`\343\006\254\205\342\200\274\360)\340\221K\272\2274\023M\244\"\230E%\024\233\250\335I\232Jku\244#<TN\273j)\010\306*\244\343\212\213\225\025\034\234\212\317\272l\003YS\234\234\326M\351\313qY\263\r\243\025JE\346\241)Q0\305I\020\253q\016Eh\333rEZ\230\224\000\216\225Rnj\254\221\325v\004\032\232\026\r\305LP2\232\315\273]\254A\254\253\232\316\234pj\233\363\305g^E\264\346\2507\031\256\361\346\3340(\214f\254F\265m>\225j5\346\255F\265f45n(\317\025n(\315]\2123\351V\342\210\325\250\343>\225a\027\025:\216\225*\375)\312\005H\020\032P\n\3644\365s\236EX\216H\317\261\253*\343\03404\345\223\035i\336b\372\323\201\007\275;\002\232h\244\335M$Si\010\3156\212nh\335FsH\033\006\222w\363z\016\225U\227\232\257$e\237\332\221\220\n\255?\265f]\214\346\263&\004f\262\256G\'\326\263\345OZ\251*\324\0148\250\331)cZ\271\n\347\025z\003\203S\264\243\034\364\252\362\020zT}j\t\020f\236\211\261I\3074+aj\205\313n\'5\227rk>a\232\245\"b\252\334G\275k.x\366\223]z\034\325\230\205[\210\n\267\030\025j *\344X\253\221v\253\220\363W\"Z\271\022\325\330\227\212\231W\232\231R\244Q\212\221x\247\001O\031\024\340M8r)@\305H=\252dcS\252\206\352)\342\021\333\212_,\216\206\215\314)7\373P\010&\202\264\306Zg\"\2234\264\323\326\233\272\202\324\224\344p\200\344g5\003u5\031\0315\024\243\212\2437\031\252\027\0039\252\022\256A\342\263.!\316k6\342<\003T\035}j\022\271lP\321\023\332\204\204\203V\342L\n\231\001\006\245\306EU\231\014-\317\3354\003Q1;\263R\031r\017\035j \374\021Tn\233\004\326d\252\\\325YV\253:f\240x\353>\356\014\346\267\342\030\253q\325\230\216*\324mW\"9\253\220\366\253\261\n\271\022\325\350E]\204U\310\370\0252\324\213R\257j\221zS\300\247\205\315H\251\305<\'5 \214b\234\261T\2411R\242\212\224-)\035\2501f\232c>\224\337*\232\312V\231\235\335\251\254\264\322)1\216\224\3265\033\037J\024\022zT\351\016{P\360\342\231\366r\352H\355QI\026\301\232\201\307\031\252s\307\2735JXx\252S\333\221\232\317\236\034\003Y\227\020\3475\2374\030\252\342\334\356\251D<R\210\361\332\234\027\035\251W\255L\244m\250\256Hd\252\3528\024\254\243\025\023\0361Qn\306j\234\377\00005Q\327\002\252J\225U\306\rD\313\305S\2353Z\250j\304mV\2429\253q\n\271\r^\206\256\302j\3645v*\273\025YC\221S\245J\242\245QR\252\361R*sS\"\324\241qJ\026\244\002\244E\251\002\324\212\265 J\236+\1770\212\265\366 \0055\355F8\250M\276;T2C\2361L\026\274\322=\276:\212\206H1\322\242\362\352)\023\025\020^j\3241\003VxE\250\230\356\244Q\203\355QM\036\366<`Uw\207o\025\003\300\016j\254\220\001Tn#\034\326u\324Ca\254Y\223\223T\344L\323L<f\231\267\024\322\270\246\236)\200\344\324\231\342\230\374\212\215W\232R\274Uw\034T\'\241\250LY\036\365^X\261Tf\\f\250\315\305D\016x\250&Z\270\2075f>*\334F\255\304j\344&\256\303W\341\253\320\325\350G5y:\n\261\030\342\246J\231F*T\342\247J\231\005L\213S\004\310\243m<-H\253R\204\315J\211Vb\200\261\025z\030\202\017z\230/\255F\353Q\262qP\264`\232<\241\216\224\206<\212\211\340\007\265D\326\240\347\025NkV\007\245W08=*h\325\224r)\035\213\032thH\251B\361\357@L\347\"\253O\037&\251\312\244UY\006j\214\311\221T.\027*k\036\346.MQh\360h\331\217\245F\321\363QJ\233EVc\315\010\234\323\372\034b\230\353\305G\323\255)pF*\'\035j\000\235\375\351vc<Ui\200\316*\205\314c\232\312\270\\5A\322\243\232\247\210\363V\220\325\270\215[\210\325\330\215^\203\265_\207\265^\206\264!\342\255\307\332\254!\251\320\324\351\315J\243\232\235G\025<B\254*\361\236\325*t\247\005\315=R\244T\251\243\210\261\000U\350,\330\365\025u \013\300\251\026#\232q\212\230\351Q:\361P\221\203I\232F\250\316I\244\0242\206\250\214#\322\232\320f\243kp)\2416\323OZa|S\034\206\353\326\253J\242\251\313\037\025B\340c5\2378\3105\233q\036sT\236\016i\246\034\n\215\243\305W\235;U\177\'\236\224\361\026*7\\S\033$TL\224\300\2314\346\217#\336\230\261eM\006>\243\275T\236-\2475\237q\320\212\312\236>j\273\246*\264\274\324\261\032\265\021\351W\"=*\344Uv\021W\340\035+B\036*\354,\005]\212AVRQVR\\\324\350\365<njtsV\021\252x\316j\314f\247\000\036\203\212r\212\225\0075a\0235\245cl\016I\037J\270\340F\271\024\220\363\315ZA\232s(\306j\244\307\232\205\2335\013\232`\351Q\263b\233\277\236\264\315\374\232z\267\024n\244\335\336\242i)\243\004T.\274\361Q=D\334\324\017\232\253+\366\252\027\025BB9\252\262\340\325V\000\232\215\3005\013\245@b\311\311\250\331\000\250\235qQ0\315F\334\212c/\024\320\234\324\210\233\273Pb\332=\2526\\\034\324S\333\371\200\342\262n *NEf\\&\t\252R-B\361\346\231\025Y\214\325\330NqWa\311\351W\340RqW\340\\c&\256G\326\255\306\3358\2531\265Y\214\325\230\332\255F\371\253\021\232\263\035YJ\235*\314dq\236\225:\310\0008\024\370\311\317Z\271o\036\343\232\321\206\005\034\221WS\n8\247:\356QND\332)\376f(ir*\264\255\326\240\'5\033f\230O\025\023w\246\023\212\211\211\006\236\217N-L-M\004n\346\244b\255\320ST\001PN\240\347\025M\306*\007\006\253J*\234\353\234\325\031c\305S\232#\332\252:\221Q\363J@\"\242a\232\202E\301\250\031sP\272\363\201H#\3074\326J\210.MX\211v\216G4\256\242\242d\3108\355Q\343)\356+:\351wg5\221<<\232\251$\0315^HqT\2435n%\315^\202>\225\243\002\216:\325\330\206:\n\267\035Z\216\254\306\325f3Vb5j3Vc\253QU\250\352\302\n\262\202\245\251\020\032\235\026\264\254\262@\317j\321\007\006\246\214\346\254\306Aa\355R\270\030\342\240aL<T\017\311\246\205\024\327\025\013\212a\031\250\330Tl3Q\234\255\014\374TFS\232z\266i\333\261F\352\216C\221U\237\212\202CU\245\3475VE\315U\221*\254\221\346\252\311\016j\006\203\006\230c\250\3311P\272f\240e\342\242\362\262i\306<\n\206D\300\246\307\037\255LW\002\231\267u\033\006q\336\253\315\031Q\221Tf\217x&\250\315\005Tx;\325ya\366\2548G5z\025\253\360\n\277\027n\365e\032\254\244\200T\361\311VcsV\242j\267\021\315Z\213\234U\310\205\\\211j\334IV\243Z\235EJ\213\232\235\022\246E\305iY\'\313\236\325p)\251\200#\024\365%[4\377\0004\322\356\310\246=@\375i\244\323j6\250\351\030TL\005F\342\243n\225\003\002)\003b\236\257\232~\354\212\215\332\240z\257!\"\253\271\315@\342\240\220f\253\262\365\252\356\274\324f,\323\0145\014\220\361U\344\210\366\250L4\242\034\014\324o\035W\222<\232\025)\2547\034t\245\n{\nk\304B\356\250\316YH\305Pt\303\032\205\300n\242\253I\020\002\251M\0315\315@\247\255]\204\036*\3649\030\253q\261\372T\350y\2531\373\325\250\315Z\210\325\270\252\344C5v\025\253\260\255]\205j\344IVQ*eJ\231\022\254\"U\210\342\315hZ\241E\031\253j@\251\001\3159\223\345\250\263N\335\212k>j2y\246\232\026\243\225qU\331\2151\244\305D\317\232M\304\212k\034\n\210\363Q\260\244\034T\200\366\241\206j\027\030\252\262\234\325s\326\243qP\260\250\235r*\273\'4\242,\322yx\250\246\210v\252\257\025Dc\2464x\250Yq\232\201\327&\230F*23N\217\255:E,\244\016\225\023(\331\323\232\243*rj\263\240\252\263\014\n\243) \327=\004y\306j\344K\201VR\254FsV#\253Q\325\230\352\334@\325\330V\257B\265z\025\351W\242\214\325\350c\253\320\307Wm\355\214\207\000sV\227O}\273\261\3054DV\246\215*\324+\202+B,m\306)TsS\306\274\322\316\301V\252o\346\227}5\236\232M &\224\023\232q\301\025\023F\rA$5\001\210\320#\246J\270\250\266\363H\313\305 JpJ\n\324\022\212\254\353\232\201\226\242aP\270\250\310\3151\323\2759\027\212k.\rF\351\232\253$}j#\036\005F\313\305@\361\324\014\225\023%F\321\320\243\006\236\352v\344Tl7Fj\214\211\315@\351T\347CTe\2175\316\304\274U\244\251\320U\230\305Z\214U\230\226\256D\225r$\351W\241N\225z\030\363\212\320\202.\225~\030\352\374\021U\350\243\253\266\361\266x\025\253bwe\037\246*\013\250\224>\027\2455#\251UqV`\0370\253[0\325\"/5\005\331\311\305T`E\007\2323\212\001\315.\354R\007\247\006\315)\031\246\224\3154\3061Q2c\265A*f\243\t\212B\224\2339\251R-\302\207\217\002\253I\035Wx\352\274\221\342\253:\221P\270\250\2623N\333\225\241W\024:\324%qQ\224\034\324\016\225\003\255D\351\221PI\035B\311Q\262SJc\232Uc\223\216\206\223\313 \032\243*\362j\274\213\201Ud\\\325Ya\256a\027\212\231\005XA\212\261\030\253q.j\334IW\240\2175v\030\372U\370\"\351Z0EW\341\212\257\303\025\\\2111W`NEk\306\321\305\020\332>jH\344*\305\207ZR7}h\306)A\305K\013\374\302\264@\310\006\246E\3435Zd\005\252&\210b\2421\342\230W\024\323\322\230x\243<R\203R\241\251\002\003G\227\315\r\0105ZX}\252\023\026)\214\224\322\2705b\025\364\244\225\000\252\256\225Y\327\223P\272\346\253\274|\364\250d\207\"\252\264<\321\215\242\200\300\032S\206\250\231i\205*\027^j\t\023\232\211\227\212\205\326\242x\352\006CM\332H\305\"C\264\340S\244\033\024\344\326{\216I5VNj\035\2314I\006\361\\J\221\305L\200\232\263\032\325\250\226\256D\265r\024\255\010\022\257B\231\255\010#\351Z0G\322\264a\216\256F\225j1V\242\025iML\225(\300\024\204\322u\253\026\361\234\346\264#<sR\356\342\243h\367sLh\361Q:T.\270\250\210\246\221F8\246\205\346\254F\243\025 \342\244\373\300R\201\223L\222 j\007\213\025\013\305P\262b\244\210b\225\327\"\253\312\265U\326\242)\232O\'4\215jXt\252\323\332l\\\221Td\\\032\213nh\013\212\010\315&\336*\t\027\232\205\3075\013-F\311\236\325\023\257\025\013&i\205q@\343\232\255p\305\2115U\324\232\256\351LX\371\247\272mZ\340#J\263\032\325\230\226\255\304\265n%\253\260\255^\205kB\005\255+t\351ZP%hB\225j4\251\320b\254#b\247V\251\025\352O2\223}>6\347\232\321\203\224\030\253\261\307\362\203O\362\301\247\210\370\246I\037\025]\327\025\013\255@\343\025\013\032g\231\212@\374\324\350\374T\212\331\251\307JQ\326\237\267\"\230S\232k\303\306j\273\303\232\0048\355Lu\305@\351U\235*!\0375<1naWV\004\nF*\245\375\250\021\203\212\347\247\213\014j\r\230\243\034\320S4\335\270\250\244^j\274\211Q\024\246\025\305D\353\315D\311Lh\267\n\207i\\\346\253\310\274\324.\234UvL\322l\301\024\331\311\333\322\2708\326\254F\225j5\253Q%\\\211*\344IW\240^\225\241n\275+R\335:V\225\272t\253\361/\025`\014\npj\221Z\246V\251\224\346\244\024\241I\251\021\ri\331\203\214\032\323\211r)\342,\032\224\307\201PH*\273)\346\2538\250\035MD\361T&>i6\342\234\032\246\214\325\204jx=*d\"\234\024\023S\254*\313\212\202K`\246\242h\270\342\253I\0275\004\253\201U\\d\323\002\202j\314q\343\245I\222\005E;\371\211\264\3265\324\0305BU\305C\212\226%\315$\221\343\232\254\342\241qQ\025\2441dT2GQl\241\227j\3259:\324%*\031\026\242\362\311\355\223J  \344\216j\265\301\3005\303F\225j4\253Q\307V\243J\267\022U\310c\253\360G\322\264 \217\245i[\2461Z0\214U\270\316*PsJ\rJ\200\232\235\026\254 \251Tf\247H\372U\230\340\253pb3V\322M\2475v9C\257\275+\214\324L\225\023\307U\244\217\025Y\327\232\210\256i\014\\TM\0350\256\332P\370\247\t\200\247\t\375\352xe\335V\3435`8\244f\004S\n\361\232\2551P=\352\224\203q5^H\352\014m5b\027\251_\025\013\216*\205\322\203Y\223\2463Uq\315O\025,\203\"\252\272T\016\230\250\310\031\246\362)\214\271\250\335)\222\017\224\325\027NMD\302\2431\367\247A\021/\2228\024\223\234f\262/\017&\271\030\343\253q\307Vc\216\255D\225n(\352\354Q\325\350c\255\010\023\245_\204c\025r#V\223\232\231V\244T\251\221jd\253\010*x\3235n\030\371\025u\"\300\246I\362\232\221$\014\005Y\204\221W\003ei\303\024\216\231\025VHI\252\262C\212\210\305\315)\217\212\215\242\252\322\245Wc\212g&\200H\251\242\224\255[\212\344\325\204\234c\255#\\\320n2:\324,\333\252#\336\241\220T,\224\370\306\rJ\303\"\253\311T\346\2523.j\233\246\r:.\264\347n\325\013s\315E\"\361U\312\322\025\246\204\311\246\310\240T\017\367j\243\2554G\232>\316[\223\322\225\300Q\305P\270<\232\312\272\3475\315\307\035Z\215*\314q\325\270\243\253qGW\"\216\256\304\265v\025\253\221)\253\221\n\271\022\325\204J\235#\251\226*\221b\305L\213V\"\025r\034\n\270\235)\257\021jjZ9\345A\342\254\301\033\257QW\021x\245\034\032V4\3020:T\022&\356\324\317\'\332\203nj)\"\305T\226\022{UW\203\232g\227\212aA\232zGO\306\332]\370\024\320\345\215;q\245\004\232p\031\244d\315Fc\366\244\331R\252\374\265ZU\301\252\262\2409\252\215\0375Rd\301\250\033\216\225\03350>x\244c\232\214\2574\306\030\244\003&\243\225N3U\034f\243a\3055T\361R\221\300\250&\\\212\317\235z\326e\312pk\0068\352\314q\325\270\243\366\253qEW\"\213\245[\212*\267\024Ur(\352\344Q\325\270\242\253\260\307V\222:\263\034u2\240\247m\024\0059\251\343Z\265\020\253\326\343,\005jG\024HG\2329>\224Ks\0349X\200\301\247\333J\222\215\254\243\'\245+\305\260\220E0*\347\255J\226\373\251^\305\207A\3050Y7qN\026\'\322\221\255qU\345\266\036\225VX8\351T\345\267\366\252\222@Gj\207\313\"\235\214\nc57w\024\320qJ\037\232\23004\360x\247\250\240\257\2555\224\na<UiMV\220Uy\005A\"dU\031\327m@y\025\033.)\024\342\234\016\323M\220\206\034R*qQM\351U\212d\323\014D\366\243\313\305\016\265^AT\346\\\326u\304<\032\301\211A\025n(\252\334Q{U\310\242\253\260\303W\"\206\255\305\r[\212\032\267\0145v(3W\"\202\254\254\\T\252\230\251B\323\202S\326>jt\216\247H\361V\"\005Nj\300b\375ML\260\344\003\232\236(0A\025snW\r\311\365\252\262BA\342\256Y\302\315\301\342\265a\2678\033\260jf\264A\332\242\222\327\035\005T\222\337\332\253Kl\007j\250\366\303\322\253Km\355U$\200zUg\267\317j\257,\033j\244\211Q\020i\2704\241NjdZ\235R\236\006\r5\316*=\324\323P\3123U\335j\273/4\307N*\234\361dU6\217\024\306\346\233\266\232A\241c4\366]\213U\\d\324{9\315?\003\030\3051\327\333\212\211\326\253H\271\252\262\246*\235\302\022+\002\030\261Wa\2175v(j\344Q{U\310b\253\221EWb\212\256E\r\\\212\n\273\014\025n8ju\204\267AO6\345z\212r\305N\331\212UZ\261\032U\204J\235#\251V<T\250\010\2531I\212\224\311\350z\320\030\016MX\267\230\036\007Z\270\222g\275O\034\356\247\332\256+\254\253\310\346\241\226\005\365\252\222\333\346\253<\003\035*\254\326\346\250\313\t\007\245B\320\373Uy`\3105Bx0zUW\213\006\231\262\236\221\346\247H\252B1I\263uD\351\212\205\206)\233\351\254sQ\262dUgB\246\242\366\250dPj\264\320\361\232\252\321\340\320S\"\230\027\232\225Pc5\034\252_8\355U\374\274\232x\203\214\322:\n\211\223\216*\007^MU\225qUe<UINA\254x\242\366\253\220\305W\341\212\256E\025\\\212\032\273\0245v\030}\252\3640{U\330\240\351V\342\207\025e\"\366\251\243]\2548\251g-#\014\214b\231\266\220\246i\311\035XE\253P\307\270\325\330\355\263V\340\262V\373\304\nl\266\241[\003\245D\321\354\245V\000S$\220\221\212\201.L2\002zV\225\275\350|sW#\274_Z\261\036\240\212y5an\343\233\2750\220r*6\\\3242G\232\255$\000\366\252\362[\016\325VX=\253>\346\014v\254\351\223\006\253\221\315=3Vc\007\024\342\264\322q\332\243\220\223PI\232\200\212A\326\247H\303\n\206{|\003\305P\2316\346\253\263\001Q\263\202*\254\230\025\036\341M\030\316jBA\000\n\225\341\002>:\324V\361\002\016{S%;x\035*\273\036*3\322\242qU\245\\V}\300\301\252R6\rT\202>\325z(\252\3641U\350a\253\260\301W\241\203\245^\206\017j\273\0245n8\252\324qU\224\213\212\225\"\303\002EXh\004\213\223\301\250V\337\232q\267\3057\312\305H\261\325\250S\025z6\300\251\323s\036*R\017z\215\342,=\251\277c$t\246KhS\255W{\\\216\224\301\026\316\224\276a\035\315><\261\344\325\373gT u5tJ\r/\233\315!|\212\215\230TN\001\035*\254\213T\356#\r\332\250\265\201\225\250\032H\006\206\323\366\364\024\323o\266\230a4\326\207\025\013GQI\017\025VE\301\250X\355\246\264\344\000A\245mDm\303b\262\257\257W\007\007\232\307\233QnEW\373{\223\326\217\2653w\253\020\266\376\365`BH\240\002\247\232\233vF)\3100\325\014\311\315U\221qP1\250]\261U\345z\245q\212\315\230\363N\267\217 qZ0\307\232\275\0145z\030zU\370a\366\253\320\301\322\257E\017\265\\\212\032\267\024\036\325j8=\252\324p\324\353o\237\245;\310\305\006 \242\231\260\236\324y\024\341\016;T\210\270\251\323\025n\027\013VW\347\035*)\"`iV9\010\366\242K\031vn\0075\002\333H\307\232\235l\262>aQI\246\340\344t\246\013<\037J\236;`\247\203V\026\006\3052H\212\212\213\004t&\2170\216\2434y\353\350i\246D=qQ\262\307\327\"\232\002\036\206\220\240\250\331\001\252\362@\t\250\374\237j\215\343\366\250\014\0315Z\350yB\263\234\344\364\250%\340V}\314\373\001\346\262no\260O5\235-\303\312p*\007\215\310\316*\214\322\264MDW\2315\243mq\310\346\265 \270\310\305<\276M\000\212\224)\312\236\324\351Tb\251\312:\325Y\024\212\251!\305U\221\252\234\315Y\363\003\232\267n\230\305i\300\235+J\010\263\212\277\014=8\253\360\303\355W\341\206\256\303\007J\273\0245n(j\324p\325\210\340\315N\260\363\212\224A\221M6\371\355J-=\251~\317\212g\221\232i\200\366\245X\rX\212\"*\314@\251\253\237)^@\252s\273\016\235*8\256\335\0163\305Z\213\347 \346\257\242\002\007\024\343\002\267j\202[%=*\017\262\025<T\211\023}(\221@\3523P\264@\366\250\036,t\250\232#Q4u\023GL)\212o\314;\232Uc\236i\305i\nf\243xr\016\005E\034`\267\314+3T\\H@\355Yn9\250f\031J\304\276V\346\261e\201\345n\001\255\r?J$\202\302\264\233FB\277t\346\271\375[D*\305\224\037\245s\322\332</\323\212\261\014\205@\255\033[\216@\315_G\335OS\223W\341]\310)\322BXf\252\274X\252\263\'\025\233p\270\315P\227\"\252Hj\244\325\241n\235+N\335:V\245\272\003Zv\361V\2040\372U\370a\366\253\321C\355W!\206\256E\016*\314p\347\265XHN*t\200\n\225a\315<[\346\245kr\253\234T&\003\214\221\212\022\001\212\036 \007\002\230\212\007\\Ps\236:S\205I\0319\301\242xs\315W[p[\223\212\277ol\251\374Y5m\006)\347\2450\344\367\244 z\324e\260x\246\222I\351Q\270>\225]\201\3154\220i\257\016j\273\304@\250\212\323\n\324\253\000\3056H\312Ty\243u <\325k\273\025\2343c\346\254\013\210<\246 \326u\313\355\006\251\224\022\347\201O\265\260I\033\356\367\255\213]9P\014\n\270lT\257J\316\277\322VE<s\\\216\265\243\030\325\230\n\304[\023\267$\021L\216\026I=\253z\307N{\224\312\236i\362\330\311n~aVt\366\371\302\236\365zX\212\347\320\3259R\251\316\231\025\231q\037Z\316\2351\232\317\227\202j\224\307\255l\333\247J\323\267J\323\267N\225\251l\275+N\005\034b\264`\217\245hC\035\\\212/J\273\024\036\325e!\251\322*\231!\'\265N\220z\212\231a\031\036\224\347UQ\301\250\035\001\250\212`Sv\2029\246\030\262h1c\2650\214R\031\n\363Q\265\303\023\357L\334\304\344\232\265h\3377\'\351Z\221\003\212yPi\n(\353PH\200\237\224\324a\010\247\034\001Lf\030\250\037\035\252\027S\236)\231\"\243\221\313pzTG\203M\"\254\304\240\201M\2352x\252\345)\273\001\247\010h1\355RH\254\035J1+\235\242\262&\262<\344UAj\310\304\3665r\312\334\253f\266\355\342\340f\246+\201\357PI\030n\010\254\313\3355g\004b\263\016\206\212\245v\214VM\316\204#\223**\355\205\234\220\214\201\322\247\234\t\024\207^k;\3101L\010\351\232\320g,\2035R`*\224\3035\237:u\254\313\224\306x\254\273\201\214\326l\355\326\272;t\351ZV\353ZV\353\322\264\355\326\264\355\327\245i@+B\004\3163Z\020\247J\277\014y\253q\305\355V\022\020{U\230\341\036\2258\200\n\0320\017\024\306\217\216\225\031\216\242h\271\351Q\274x5\031S\232\010&\230\311\305B\321\346\233\345S\2049\253\020A\206\025\242\213\322\236\0234\331\027\002\253\225\346\224\364\353U\345p\017\035j=\244\321\261\215\006\023\216\225\024\221\365\252\254\2074\306\\Sq\232\232\020I\305:Q\203\212f\314\323\226\021K\345\343\250\244\221C\256+:\342\325\024\223Y7\210\t\342\241KA!\2531\330\355#\0258]\264\354R\025\342\242x\301\250Z\034\324\rb\256rE\037fT\\\001T\256\254w\253\021\326\262L\'v\010\344T\245p\270\250%\034r*\214\311\216\235*\234\311\305f\335G\301\254k\265\353Y3\257Z\352`^\225\245n\235+J\335s\212\323\267N\225\243n\275+F\005\351Z0\n\320\207\265_\204U\350V\256F\225:%J\253\305\014\271\246\024\250\312sM\331\223Lx\201\250\032,\032o\225Mhx\250X`\323\243\217y\251\214A\005:-\271\253\nFi\373\300\246I*\036\365\004\223\"\3645U\356\027\326\243\022\253\032\221gU\355N\373W\240\246\233\2064\306\311\352*2\202\230\320\026\357P\264e\r\021Hc|\324\314C\234\320\000\247\002\0075^[\241\234\nh\270\004`\325;\267\315eJ\204\232\265g\007\025x\3006\324M\020QQ\025\301\246\361\322\230z\322`S\031j6\025\003\014\036*\235\325\220\'z\212\250\320\340c\025Rh\372\3259c\252SG\326\250\\\306\0105\215y\017Z\307\270\213\232\351\255\327\030\255;t\316+N\335zV\214\tZ0\001\305h\300\265v\036\265~\001\310\255(EhB\275*\344C\245YU\247\205\305\005i\205i<\274\3224U\033.)\276P4\326\207\025\023\214qP\233}\3074\306_/\245V\232g=\3524\272e8\"\247k\345\211s\234\232\255.\252O@sQ.\244\375\3052[\3170t\246\304\301\271&\254+\014R\0319\247+\346\246N\225:\256E1\343\301\245X\363\212t\260.\334\232\315\234(o\226\231\347m\352qMk\260;\212\201\3577p\rG\2774\253\232VB\303\221I\3660\303\246*h\340\362\307\025&\334\323Y\0075^E^\325]\370\250\035\216x\351H\036\2279\250\330Tdu\250\332\240\226\020\3035B\342\0029\025BX\272\325)S\326\250\317\027Z\312\272\2039\342\262\'\267\311<W\377\331"
+byte_png: "\211PNG\r\n\032\n\000\000\000\rIHDR\000\000\002\000\000\000\002\000\010\000\000\000\000\321\023\213&\000\000\001JIDATx^\355\335!\016\300 \020EA\262\367\277rI\253*\276C4\024\230\221\317b\226d\t\255\001\000\000\000\000\000\000\000\000\000\000\000\254\2552\000\000\000\000\000\000\000\000\000\000\000\234\315\2325\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\\\031\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\030S\031\000\000\000\000\000\000\000\000\200_\260\333\003\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\323\371F\004\000\000\000\000\000\000\000\000\000\000\000\000\340\345\311\025\000\0000\203\273\010\3004=\003\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\313\250\014\000\000\354\313\360w0\207\017\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\360\251\312\260\271\236\001\000\000\000\0367\231\251\003\020\030\305\203\234\000\000\000\000IEND\256B`\202"
diff --git a/core/res/geoid_height_map_assets/tile-3.textpb b/core/res/geoid_height_map_assets/tile-3.textpb
index c147825..9abaaaa 100644
--- a/core/res/geoid_height_map_assets/tile-3.textpb
+++ b/core/res/geoid_height_map_assets/tile-3.textpb
@@ -1,3 +1,3 @@
 tile_key: "3"
-byte_jpeg: "\377\330\377\340\000\020JFIF\000\001\002\000\000\001\000\001\000\000\377\333\000C\000\004\003\003\003\003\002\004\003\003\003\004\004\004\004\005\t\006\005\005\005\005\013\010\010\007\t\r\014\016\016\r\014\r\r\017\020\025\022\017\020\024\020\r\r\022\031\022\024\026\026\027\030\027\016\022\032\034\032\027\033\025\027\027\027\377\300\000\013\010\002\000\002\000\001\001\021\000\377\304\000\037\000\000\001\005\001\001\001\001\001\001\000\000\000\000\000\000\000\000\001\002\003\004\005\006\007\010\t\n\013\377\304\000\265\020\000\002\001\003\003\002\004\003\005\005\004\004\000\000\001}\001\002\003\000\004\021\005\022!1A\006\023Qa\007\"q\0242\201\221\241\010#B\261\301\025R\321\360$3br\202\t\n\026\027\030\031\032%&\'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz\203\204\205\206\207\210\211\212\222\223\224\225\226\227\230\231\232\242\243\244\245\246\247\250\251\252\262\263\264\265\266\267\270\271\272\302\303\304\305\306\307\310\311\312\322\323\324\325\326\327\330\331\332\341\342\343\344\345\346\347\350\351\352\361\362\363\364\365\366\367\370\371\372\377\332\000\010\001\001\000\000?\000\367>\235(\335\317Zz\311\212\231d\2517\347\2751\316qP\261\250\330\324L\324\302\324\302\324\233\251\271\2434f\214\322\023M&\232Z\230^\220\2650\2650\2654\265F\315Q\261\250\213Tl\325\0235D\315Q3TL\325\0235D\315P\263T\014\325\013\275Wv\250\035\352\007z\201\236\240w\250]\352\006z\205\232\241f\250Y\2522\324\302\324\322\324\231\244-I\2323J\r.i\300\322\203O\006\236\r<\032\2324-W`\207=\005j[\300\027\006\275\334\2750\275(z\221d\251VOzs8\332>\264\307<\324Lj&5\tjijB\324\233\251s\357I\2327Q\232a4\302\324\302\324\315\364\205\251\205\251\205\251\205\251\214\325\013\032\211\236\243f\250\231\252&j\211\232\242f\250Y\352\026j\201\236\240w\250\035\352\273\275@\357U\331\352\026z\205\336\240w\250Y\370\250Y\2526j\214\2650\265!jB\324\233\275\350\335\357F}\351sK\272\234\r8\032x4\360jh\320\261\366\253\360\307\320b\264`\214\001\315^\213\257\025\354\276g\024\323%\001\352E\222\244\022{\323\304\231\025!`?*\215\273\324,y\250\030\363M&\2234\231\245\335Fi3HZ\232Z\243f\250\313S\013Ro\246\226\2463Tl\325\033=F\317Q3\324E\3526j\205\236\242g\250Y\352\026z\201\336\241w\252\356\365\003\275Ww\250\035\352\007z\205\236\241g\250\035\352\026j\215\233\232\214\2650\2650\265&\352Bi7P\032\215\324\273\251CS\201\247\203R\256jx\243,\325z(\272\014V\2041m\031\"\255\'Z\275\002\2168\257U\022{\321\346R\357\247\t)\342Ozz\311\357S,\231\247n\004~\025\023\324\014j<\321\2322)i3HZ\230Z\230Z\243f\250\313S\013R\026\244\335\221Lf\250\231\352&z\211\236\242g\250\231\352&\222\242i*&z\205\236\241w\250\035\352\007z\201\236\240w\250\035\352\273=@\357P\263\324,\365\013=D\315L-L&\230Z\230M&\354SK\323w\322n4\340I\251\002\223R\254f\244X\215L\220\237J\260\220\037J\271\014\030\034\212\273\014`\021V\366p1SE\0375\241\nb\275\024I\2327\347\275\'\231\216\246\234%\247\211=\351\313%L\222\373\324\353 8\311\244f\343\336\241cQ1\346\215\324\271\2434\204\323\013S\013S\013Tl\325\031jajn\352\003sLsP3\324,\365\023=D\317Q3\324L\365\013IQ4\225\013=B\317P<\225\013\275@\357P;\325wz\201\336\240w\250Y\352\026z\211\236\243-M/Q4\224\303\'\2753~{\320\r8)jx\205\261\322\224D{\212\225!>\225a!\035\352\302D\276\225a!^\302\247HG\245J\261\201\332\245A\315Y\211rE_\216<\212\265\0245r8\253\256YjA\'\275!z\003\323\204\224\361%J\262qS\244\276\365/\230\n\363Q\226\342\243c\3153u(zv\372ijajaj\214\265FZ\230Z\230Z\232Z\223~\r5\236\253\310\3309\252\354\365\023=D\317Q3\324,\365\013=B\317Q3\324,\365\003=B\357P;\324\016\365\003=@\317P\263\324,\365\013=D\316\005F\322\014u\250\213\222z\323K\344\360)\2474\000I\305Y\216\036\346\255\244\\p*_+\326\223f;S\302\n\225\02352&:\325\224Q\212\231G\024w\251\220U\310S\232\321\205*\354iV\343J\332V\367\247\253\340\323\367\323K\340\321\346S\326L\324\312\365*\311R\tx\247\007\033i\254x\250\313a\261@z7\322\027\246\227\246\026\250\313S\013Tl\324\302\324\322\324\302\364\326~*\027z\254\355\203P\263\324L\365\013=D\317P\263\324,\365\013\275B\317P\263\324\016\365\003\275@\357P\263\324,\365\0135B\357\201P4\237\205@\\\036\246\232Z\214T\213\036FM)@\005*(\335V\324\000\225n!\362\212\227\034R\004\317jp\217\332\236\213\265\272qS\205\335\322\246U\307\025*\255\001~j\261\032U\330W\025\241\0168\253\321(5m\026\256\206 sN\363)\302\\w\246\264\264\321\'5\"\311\357S,\225 \226\234%\251R^\324\375\371\034\364\250\334\374\324\315\364o\244/HZ\230Z\230^\230Z\243-L-L-L/Q\263\324,\365\003\276j\026z\205\236\242g\250Y\352\007z\205\236\242g\250Y\352\006z\205\336\240w\250\031\352\026z\211\232\241w\300\252\356\304\362j\027l\364\250\371\3158\nr\34358a\267\2550\276M*\036j\310<\001W`9\214T\340d\324\201i\341i\3733RD\270n\225g\313\357N\013\355OT9\351S\306\225n8\311\350*\334Q\277\241\253\360#\367\025~4=\352q\351Q\267\025\031\223\236\264\236e\002Jp\223\336\245YjA\'\2758KOY\275\352u\224\025\306h-\317ZilSw\321\272\220\2754\2750\275F^\230Z\243-M/Q\263\324,\365\013IP\263\324.\374T-%D\317Q\263\325wz\201\236\241g\250Y\352\026z\205\336\240f\250Y\352\"\325\0335Wrwgw\341Q9\'\251\250\215.\0062i)E<\036(\035jT\034\325\265L\246j\354\t\373\261VUjP\234S\202\232\235\"\251V,v\251BT\253\02052\302OAV\340\264f=+F+eA\310\251\324 \350*\304]zU\330\2235\022\237Jc\037\326\2531\3014\335\364n\245\335NW\251VJ~\372p\223\336\244Yy\251\004\231#\007\2458\276x\246\261\305&\372B\364\322\364\302\365\033=0\275F^\230^\243g\250\036J\205\244\250ZJ\205\344\250^J\205\244\301\353M2f\241\221\252\273\275@\317P\263\324,\365\01351\201#\223\212\205\266z\232\211\266\212\215\231GAQ\2221P7&\232E\030#\212LR\216\224\341\326\244QS\305\031f\000U\365\213\345\n*\344q\355\000U\204J\224-J\221\367\305N\211S,y\251\004^\325b\030\t=*\364V\3309\"\257\307\032*qC\002\306\237\034^\265n(\371\351W\341\210\2228\254\264l\216\264;\201\305V\224\363\326\241\337@pi\341\251CS\303S\303\322\357\367\245\022c\275H\262\343\232\224I\232w\231\3074\335\334\365\246\226\301\246\227\246\027\250\331\3522\365\031z\215\244\250\232J\201\344\250\032Oz\205\244\367\250ZOz\211\344\250\232Oz\217\314\346\230\362\002*\273\267\275B\355\357P3\014\375\352\214\225\317,M1\235{T.\344\367\250Y\251\205\252&4\322s\3054\323H\315\030\346\202))\312*tRN+B\332\036kE!\300\034U\205\216\244\013\212\225\0235a#\251\202T\311\037\025:\307\223V\342P\200U\225\313T\300ai\312\244\232\267\014E\210\300\255(,\316\001j\322\206\331Gj\343b\224\355\247\261\312\3475ZV\371A\252\345\350\017\316\rH\036\236\032\234\032\234\032\227}.\352]\370\247\254\230\251\004\264\246@E4\271\034\365\024\306zaz\214\275F\317Q\264\225\013IP\274\236\365\003I\357P<\236\365\013K\357P\264\225\023I\357Q4\236\364\303\'\275F\363\n\256\363sP\274\265\013I\351L\363)\205\3526z\210\2674\247\356\324$\363I\232\\PzSh\240-H\243<U\310\"\316+N\024\300\034U\344\031\002\247Q\3058)&\254\305\030\025ac\'\265L!\307&\245H\371\253Q\3066\364\251\243\207-\232\264\221{U\204\267-\326\255\307j\275\352\3541*t\025z\030\311\253\321\307^k\024\2318\315Z\007\345\252\356~V\025M\233\006\220==^\246\017N\337N\017\305\033\371\245\017N\rJ\033\024\273\350\337\357K\346\3664\322\370\350sL/Q\264\225\023IQ4\225\003\311\357P<\236\365\003\311\357P\264\276\365\013\311P\264\225\023IQ\264\236\365\031|\232\205\337\035\352\003\'\275B\362d\324e\351\206J\214\311M2Sw\322\231x\3053>\264\264\340h\353K\2126\320\027&\254E\0375\243o\027\025u\027\025j%\343\232\260\027\003\245K\034lM^\206\016*\322\307\212\220GR\244\'=*\322G\201V\"\213\236\225u!\366\2531\303\355Vc\200\347\245]\212\000\0075r4Q\300\025n$\357^I\t\357W\021\262*9N\t\036\265\235+a\351\201\351\341\352E\222\246R[\245)b\247\006\223}(zpzv\3727\321\276\220\311M2S\014\225\023I\357Q<\265\013KP<\236\365\003\313\357P4\274\324-%D\322{\324M%B\322{\324fJM\376\365\014\257\232\256\317P\263\363Q\227\246\027\246\027\246\027\244\337K\272\236\270=\351s\3159i\342\235\364\037\215\001K\032\231c\300\251\242\034\326\225\270\351WUrj\324Q\364\253\211\026{U\210\342\031\253*\010\342\254\306\271\025j8A\031\251\204c\260\251\222.j\3240\367\305]\216?j\267\024G\322\255$x\025*\251&\255\305\025\\D\257\027\212@\006*\322II#du\254\373\203\363f\240\335N\017N\017\203Wm.\021\037/\310\245\273\2366|\247\025]d=\352E\223\212v\356x\243}/\231\357H^\232d\246\231)\215\'\025\013KP\264\265\003\313\357P\274\276\365]\345\367\250^_z\205\245\250\232_z\211\244\367\250\232Z\210\311J$\250\344\222\253;\324E\371\353L/L/M-M\335I\272\200\324\360\325 4\3655*\344\364\247\201\306\007J\236%\343\221R\225\342\204\030<U\353v\350+R\001\272\264\"Z\266\213\305H\243\006\254\304\205\2175v(\272qWR<-J\261\363\322\254\307\017\265[\216!\351W\"\210zU\330\341\343\245L\"\251R.zU\270\343\253I\037\265|\376&\035\215X\206\343<f\247\3633U\2479S\355T\313P\036\236\036\227\314\3474\206BOZ\270\2775\226q\206\035\352\024\227\234T\276e\'\231\357K\277\336\220\311M2S\014\225\023\311P<\276\365\003\313\357P\264\336\365\003\315P<\276\365\013KP\264\276\365\021\227\336\243i}\352&\222\230d\243\314\250\344~\371\250Y\352\"\374\323\013\323w\321\272\2234\322\324\006\247\253T\252y\251\323\006\254\242\022=\005.\3346*\314`b\237\216)\350\225j$\305h\333\261\004V\244\'\200j\330\347\221S\"n5\241\004G\003\212\321\206.3VV:\2328\262zU\264\207\034U\270\240\351\305ZH\260zU\310\22358\216\246\216*\260\251VbN+\346T\2347CV\"\227\r\326\256\307.\345\353M\221\271\252rp\334S\003sN\rN\337I\273\0075e.I\217f@\024\301\265O\336\353K\346`\3434\031W\336\227\315\030\340\232O3\336\232\322TM/\275B\362\325w\233\336\241i\275\352\007\227\336\240y}\352\006\227\336\241i}\352&\227\336\242i}\352#/\2754\312\r4\311@\222\233$\231\\Ur\376\364\322\324\322\324\322\324n\247f\230M 5*\232\231\rY\214\325\245\177\227\024\3602sS \253\010\231\251\322:\265\032v\025n8\361W\355\317!Mi$y\351W!\214zV\214\0108\253\321\250\307\025f8\363W#\213\320U\250\341\307j\275\014=2*\301\204m\006\237\032\342\254\252U\210\322\247H\362j\324q`W\311q\276\323\305\\\216PqV\341\220\347\255N\347\345\025^n*\002\334\321\276\234\036\202\334Sw\363\326\246NS\223M\337\212<\317zo\233\216\364\276w\035i\215/\275D\322\373\324\0177\275Vy\271\353P\274\336\365\003\315\357P4\334u\250Z_z\211\245\250Z_z\211\346\367\250\214\264\3237\275\'\234\t\353OY3\336\232\357\357P\357\347\255&\372\\\346\232M\033\251CQ\326\2009\251V\246A\212\261\035ZJ\235EXE\2531\255[D\310\253\021Fs\322\257F\237-X\216\"\032\257\305\221Z6\304\022\005i\302\231\034U\350b<U\370\241\351\305]\216,\016\225n(\263W\022<T\2732)R.j\312G\355Vc\212\255G\017\265ZH\253\343\262\n\234\036*D|\036\265\243nz15e\232\253L\374\365\252\314\364\233\375\351\301\370\245/L/\316jhf\\\021\232I\030\347\"\2422\373\323\014\247\326\223\315\246\231x\250^oz\256\363{\325w\233\336\253\274\336\365\003M\357Q\264\336\365\013K\357Q4\274\324M/\275B\362\373\324F_zC.{\324fB\017Z\226)\275\352I\030\355\316j\277\231\317Z7\361J\262\032\220\035\302\233\273\006\234\rH\274\323\302\363R\252\363R\250\346\254F*\324kVQj\314iV\243J\271\022U\310\343\253\321\304\002\n\262\221\r\271\315O\032\342\256\333)\r\2221[V\303\201Z\260G\221W\243\216\255$ur\024\305ZT\251|\276*D\213\236\225i\"\253qC\355V\322\036:T\242:\370\302YD\217\236\224\337\272\303\232\320\205\212\250\346\247\363~^j\244\262\345\272\324%\3517\322\211)|\312k?\275C\346\220\335j\337\231\373\260}\252\263I\315Fe\367\2442\373\323\032_z\201\346\367\252\362K\357U\244\233\336\253<\376\365\013M\357Q\031\275\351\246oz\211\245\357\232\211\245\367\250^Z\210\313\357L2\322\371\271\025$rsS\2313\035V\337\363S\203\366\247)\315H\255\203R0\005r(\217\232\235G52\255L\213\305J\250I\253\021\245[\215j\314iW\"\216\256G\025Z\216:\273\024um\024\221\200*\324p\372\325\270\341\366\253\261E\355Zv\311\323\212\327\267\030\000\032\320\215}\252\334k\355V\021qVPT\350\205\217\265Y\021\362*\324Q{U\310\343\342\254\242|\265\"\246M|6_\232U|\236\265e.\230\000=*Ss\271z\324/&M7}4\2774\241\375\350/M2TN\342\246I\363\017&\240i}\352#-4\313\357Li\270\353U\336nz\325y&\367\252\262M\357U^nz\324M7\275F\323{\323\014\334\365\250\314\336\364\303/\275F\322du\250\213\323w\373\322\253f\246L\216jS!\331\326\240W\375\345?q\311\251\021\352Ubjh\316x5*\256\326\253!;\324\252\274U\204\\\214U\210\343\253)\021\364\253\021\307\355W\"\210\232\277\024\'\216*\354p\035\271\305XH}\252\3541{U\370\341\000p*\314p\363\234U\310\341\366\253qE\323\212\323\266\207\332\264#\213\030\255\010\223 U\310\243\253\n\236\225<qs\315[H\352tL\265^\216?\224U\210\323\332\254*\361\322\234\253\315|\036Z\200\364\340\370\251\004\230\245-\306h\335\3057w4\273\251\245\375\351\215%D\322dQ\034\235Fz\323\036B\016*&\226\2432\373\324o/\035j\273\315\357U\336_z\253$\336\365Y\346\367\250\032oz\211\247\367\250\314\376\364\236w\2754\313\357M2\322\027\342\2422sR$\300T\302\340b\236\262nZ\217?=K\273\214\346\244\214\324\361\232\2323\363\325\324R\300U\270\324c\232\221W\245XE\253\320E\221WV\036:T\311\007\265^\206\034v\253\321C\322\264b\207+\216\365:A\317J\271\014\034r*\342DGQV\242\206\256$#\025j(\306j\374*\005\\\214\363\300\253\320c\275]B\265f<\023\212\271\032dU\224\216\247\2159\253\210\265e\005N\027\212r\250\315|\003\346\000y\247\027,7(\340Q\346njv\342\034\n\231\\\037\224\322\026\301\246\226\244-M-Q\263\324L\364\344\340d\323&q\2675M\345\367\250\214\336\365\023\315U\344\227\336\253\274\276\365^Ix\353U\036nz\324\r7\275B\323{\324Fnz\321\347{\321\347Ry\276\364\242N)\254\374\320\262S\267\221Vazs7\315R\253ejTlT\361\236j\344 \026\311\255\010\260\000\305ZT\357\353S\242t\253\t\036H\255+x\361\212\275\034y=*\344Pg\034U\264\207\007\245]\212.\231\253\321 \253\261F\276\225q\020`S\311P\334\232\231$\003\245Z\215\330\216\225f2\336\225r\000\356\370\355Z1G\216\242\245\336\021\261R\306d\310#8\253\261M\203\363V\2043\257\255]\216e\365\253)\"\346\255F\343\212\262\214*\312\034\212\221G5\371\354\314;\232\236\031\000\210\340f\240\016D\234\324\341\263\3159d!\271\342\234\316;\032g\230I\351\305\005\251\245\270\250]\251\201\271\346\225\245\003\203U\346\230\021\200j\234\222\325v\227\336\243i\262:\325g\233\336\253\264\334\365\250d\227\"\251\313/\275Vi\275\352&\233\336\2432\373\322y\276\364\242oz\014\236\364\242^z\324\233\367\n\0019\251\003dU\210_\236jF99\0254-\352*\302\340\325\210\306*\344B\257\303\327\232\274\235\000\253Q\257J\277\024C\203WbLb\257\302\225\247m\036@\253\206\014(oZr\341j\304n\007j\261\024\254OCWc,j\302\333\022\241\2175<v\355\321T\325\330\255% qW\240\261va\272\272\033\r64\3035X\271\201@\371\005f<\017\346g\006\264\254\221v\341\307\343W\r\226\377\000\231j&\267\222>Fx\246,\322\2111\223W\241\235\370\316kB)\233\002\257C6\352\321\210\202\265n5\257\316\326\"\230%d\340P$gq\232\262\255\205\245\335\232\034\341(-\200\007\240\246\357\342\232\317\301\250Y\351\273\352)e\317z\253$\234UY$\252\315/5\023KU\336Z\256\322\363\326\240y=\352\244\322\325V\227\336\242i}\3523/\2757\3164\341/\275<I\305(z\225$\367\251\226L\324\200\324\321\365\251\263S\303V\223\255[\214dqW!\034\212\320\214`\003W\242L\212\275\024}+B\005\253\361\305\236j\3641\361Z0\341ENf\310\3329\247G\031c\223W\240\203w\001kN\r:GL\204\255\013})\3627V\264\032_\000m\253\360ij\017\"\264a\260\205T1\003\025al\341\316G\003\326\255D\261\'\005\270\251\235\240\306\000\311\246\210\"s\222\202\247\216\010\227\370*p\2038Q\201K$\000\257\336\006\253\375\220\003\300\346\234\221\354?2\323\213\205<\036*xf\031\004\032\330\264\2240\034\326\254g+_\235\004\323\r\000c\232\220>E<=\014\371\000{\323K\374\344\032ilS7\361\223\353Q\226$\346\243\222L\n\252\362Ug\223\336\253I%Vy*\026\227\336\240\222N:\3257\227\236\265\033I\225\316j\234\322\036y\252\215-D\322\373\324fJo\233OY\252Q-<IR$\265:IS\243\325\230\233\232\261\232\236\023\315[\217\357U\330\205_\204\002*\364|\340V\215\272\020\005iE\036@\342\257E\021\030\342\264!N*\342\020\242\245\334H\300\253V\220\274\216\025A&\272\013\035\032G \272\221\355[\366\332dQ\340m\346\265#\201\021F@\2531\204\014>^*\324L\003\344-XP\307\247\031\251\222\023\216j\302\333\344c\232p\265m\336\325r;4\013\223\315L\"\033~Q\212z\307\315L\261\361\234S\274\241\216\224\236^:\nF\214\025\344V-\3434Rc\265Od\306\\V\314!\341 \366\255\313V\337\0305\371\323\232L\322\026\245\rN\rJ[\212s\2601\206=j\"\331<\323@%\010\250\331\2609\252\262I\315U\221\352\263\275U\222J\254\362{\324\017%B\362qT\345\223\236\265\020\227*Fj\274\357\212\240\362{\324&Zi\223\336\220\311J\262\017Z\235d\004u\251D\200T\210\3435a\032\254\306\325n.H\253\212\274T\321\214\032\271\020\346\264!^\005]\210b\264!L\340\326\244\013\225\025\251n\274\n\322\2161\264U\204\343\212\263\032g\223W`\265i\233\n8\256\233L\323\342\210\253\021\315tq0U\300\0252d\232\264\212[\255Y\216?j\267\034~\325r(\352\312GV\222<T\311\021c\322\246\333\311\030\251V\023\216\225$p\214d\216jM\203\265(\216\224\304*&\217\212\307\324`.\300\001Ri\360\030\361\221\326\267\202n\200\014U\333\025!p{W\347F\352i4\023FiCS\267Q\270\021\203\322\244\001@\246H\373W5FY2j\244\217U\244z\255#\325Y\036\252\273\325wz\205\344\343\212\2473\325q6\033\255E4\245\207Z\317y9#\336\2412R\031)\206Nh\022sS$\204\324\301\310\251\243sWa~*\3325\\\205\271\253\321\267\034\325\210\3715z\025\351\232\321\210p1Wa^\000\255;x\376QZ\226\351\225\255;t\340U\365l\n\263o\036\362\t\255\004\200\261\001\005tZu\226\310\201\"\266\340\214(\000U\350\226\256F\276\325n5\253q\2575n$\253\261G\232\262\221\324\252ppj\374\0106\347\332\236\"S(\305X\021\324\\\357 T\212\275\252M\243\361\244)\223\315!E\007\025ZKp\356X\216;RE\n\211\000\002\266\241\266\036X\'\275Y\212\r\2475\371\262\307\232n}\3513\317Z]\336\364\240\320Z\223u8LUqPK6\352\252\357U\235\252\254\217Udz\253#\325gz\256\355U\335\370\252r\275S\222Nj&\227\212\251+\376\360\324%\351\206JB\342\215\343\035jx\244\025h0+R!\364\253p\265^\214\346\256\300sZ1\256@\2531\214\032\277\010\316+N\334z\212\320\2059\255;t\030\255[d\034V\224 \001S\240\337 \003\245k\333C\220\024\016MtV6\210\2403\n\327\211@<U\330\305\\\210U\310\305[\214U\330\226\256\304\265r$\311\253\210\234R\264D\034\201W\255ab\225j\030s#g\265<\256\rW#2\222*U\034\342\254\024DL\360O\255D\205H\352\r!\214\023\222i\262\014\200\024S\355\255\031\23468\255U]\240\017J\224\036\342\2774Z\243\'\232i4\241\271\245\rHZ\233\272\232\315P;T\016\325^F\252\222=T\221\352\263\277Z\254\355U\335\352\274\217\301\2523=T\221\352\002\365Zf\301\006\240g\246\0319\246\231\005*\2775b3\315]V\005)\350\304\032\271\003V\204G\245_\207\265h\304zU\310\207\"\264 \034\212\323\200t\2558\000 V\235\272`\212\323\200`\212\267\273\260\253\366\250\024n5\320i\220\227`\304W@\230\030\002\256\302\005]\213\265\\\214dU\330\205]\211j\354KWbZ\267\020\303\n\274\203\212\221\2600=kN\323kE\214v\2516l\311=\352\t\0133`t\246*8=*\302FN8\346\226D##5L\306\342^3\212\267\025\263\267Z\264\226\200\036j\334qm\034\nVC\330S\221Oz\374\321qU\317Zi<\321\236E(jBi3LcP9\250\034\325i\032\252Hj\244\215U]\252\273\265Wv\252\262\265Q\225\252\234\217\212\204\265A;|\265\001n*\"i\205\251U\215Y\212J\266\222U\210\333\'\232\273\t\346\264!l\021Z0\266qZ1\016\005]\213#\025\243\007QZ\260\016+R\335zV\245\270\344U\341\362\342\257\332\307\270nj\321\266O2P;\n\351\354\325b\210\016\365\241\021\3175~\023\305^\213\255]\212\257CZ\020\216\234U\350\226\256\304\265n%\371\261V\300\305\005N\354\326\205\237\030\346\256\345\031\366\036\265\024\221\205|\366\252\263^$-\364\252\347Y\347\345\300\242;\366\232`3\234\232\333\212%\221\001\013V\222\034t\251\322<\366\251\322,\324\313n\270\346\241\2224\022azW\3463\032\256\375j\"y\245\034\2123A4\302i\214j\027\342\253\271\252\322\032\251!\252\222\032\253!\252\356j\263\267\025RV\252R\265S\221\252\020\325\004\315\362\232\256[\212ajajP\330\251\343nj\332t\315Z\210\325\370{V\204<\342\264\255\373V\234\006\257E\202x\255\010GJ\325\267\347\025\255n8\025\247\026\000\006\255G\363\270\002\266m\220\371`\n\324\262\213\016+n&\351W\241=+F\023Wb5~\036\325~\n\321\207\265_\210\216*\364C5m\024\344\032\260\2751Nlm\025f\335\260*\312\034\234\236\264\2636\324\311o\302\261n\225\246\223#\245eK\013\244\235\361\232\333\320\255\274\311\201a\232\353\243\210\"`\n\22249\311\351V\002|\276\224\221\312\021\360\334\323\245\237p\302\361Q\002Ks_\230\354*\273u\250X\320\247\265\024\204\323I\246\023Q9\310\252\322UY\rU\222\252\311Ud\353Ud5ZC\305R\231\252\214\255U$j\215H\r\315C)\3105X\236*2i\264\240\324\261\234\032\273\023\r\265b7\346\257\300\365\247\001\316+N\n\323\267RkB\025\"\264 \035+R\337\265k@x\025\240\216\002\n\277d\233\233q\255\313R\000\305kA\205Q\216\265~\023\232\320\205\272V\204-\322\257\302\334\212\277\021\255\010OJ\320\210\325\370z\212\321\203<U\370\306x\251\3251O\362K\032txK\200\275\253I#V\\\212Im7b\205\323\242#\030\346\263\357\364\320\274\201S\350\351\345K\203]:((\r/\002\227p\'\031\246\225\031\340R\021\201P\271`r\r~i<df\252H1U\\\363H\247\232q\246\236\224\302x\250\330\324l\325\004\235*\254\225Y\352\254\225RJ\253%U\222\250Lj\214\246\2529\346\243\316MF\346\2531\346\242&\227\265 5\"\232\261\023\032\275\0078\255\030\007J\322\203\203Z\266\374\342\265m\306\0005\245\030\'\025z\021\201Z\0206*\3742\363\201ZP+0\031\351Z\2201@\006kn\310\026\301\255X\310\004U\350Z\264 5\241\013U\350\232\264!n\225~\027\351Z0\275_\201\253J\007\255(NqV\324\202\005M\270\001\305Wf\036\177\035\252\3543\221\026\001\247y\356H\346\254\301#n\004\324\367\210\036\020qYq8\212\351~\265\320\3056\020\021\320\212O0\227\"\245_Z\177zC\322\242nk\363nD\004\032\2434UFD\371\252=\270j\030\374\324\323\3235\031\353Lj\205\215B\347\212\256\365ZJ\253 \252\262\n\253%R\224\325\t\215R\226\252=1;\324/\324\212\254\335j>\364\022)2*D5j\"*\354=\210\255(\017J\322\203\222+V\334t\255[s\310\255XG\312*\354}*\314m\310\002\264\255\366\246\t\353Z\266\363\344akR\322&\221\263\330V\335\263\204@\243\255_\211\263\315hBzV\204MWbz\275\013\362+B&\351W\342~\225~\027\351Z\020\311\322\264\355\3378\346\264\340\223\003\025r6\315HX\343\212b\246O5b45f8\363W\"\214\n\262St$W?r\031n\370\365\255k;\221\264#\325\304!\234\232\260\264\341A<TLk\363\201\3075\004\210\030Vl\310C\036*\271S\326\241bFi\212\375\215!84\326\250\230T\014*\007\025ZAU\244\025R^*\224\246\250\312j\214\246\251Hpj\253\236i\253\320\324\017\367\215Wa\311\250\361Q1\371\261J*T\253Qu\255\010G\"\264a\352+J\337\255k[\366\255K~\325\253\007#\232\270\244\001V-\3179=\252\322JL\200\016\365\275a\001*\t\255\350\231c\217j\365\2530\261\3175\245\013t\255(\033\214\325\350\332\255\306\365v\031\017\255h\301\'J\320\211\352\374/\322\264!j\320\267\223\025\251o&MhD\3318\025eA5*\241\007\245N\213V\243\025e8\025f\034\034\347\322\262.\240\r30\355N\2120\252\0335z\334\361\232\264\246\234\255\221\212\t\342\242c\315~r8\252\355U\246Q\203\305R~\265V^\265_\275?!\206i\247\245F\325\023\016*\007\025Y\326\252\313\300\2523\036\265BSTe5FSU$\346\252\2654t5\003\3655\023S\010\342\240\332K\325\210\355\231\206jS\001A\234T\221\255^\206\264`\007\212\323\267\035+R\337\265k[V\244#\24751r\242\244\216|GW\354~i\003\032\350\355\346!\000\035\253B\t\t<\232\323\205\272V\204-\322\264a\223\013W#\227\212\265\034\231=j\374\017Z0?5\241\023\325\370_\000V\204\0161W\340\227\346\305jB\370\301\006\264\355\311 \032\275\024\243 b\256\241V\030\251B\025>\3252T\273\260\264\350n\006Z\263\256\256\202\263\002z\324p\334\371\244\"\236+^\016\024U\215\330\245V\3474\245\273TD\363_\235N\265]\326\253\3102*\204\310A\'\025JNy\250M38z\220\323XqQ0\250\035j\274\202\251MY\363w\254\371\217Z\2435R\222\252I\324\325w\024\323\302\325v\353L\"\221\242%sQ\252s\212\321\267Q\201\232\225\325H8\034TH\234\325\250\227\221Z\020\016+J\016\202\264\355\307J\325\267\343\025\245\023`S\244l\212l,|\320\265\275h\000\003\035+j\335\276Z\321\201\271\255(_\245hB\376\365r9=\352\334Rt\253\260\275h\301\'\003\232\320\206N\225\241\014\235\352\3642qZ0=_Bx\"\264\255f\316\024\326\315\264\230\030\253\221\237\2375m&\332x\255(]eJyR\215\355OH\232s\261i\322Z\371\0216\016N+\234\325\213!\\w\251\364\230\311@\306\267\323\205\247n\241[\232y~*2\334\327\347\244\213U\331*\273\247\265U\232<\251\254\313\204\307J\252EF\302\204b~SR\021\305F\313Q:\361Ue\351Y\363w\254\371\273\326|\335j\224\2435JAUd\025]\2050\216*\006\034\320\250X\324\214\277/\322\243\362\376l\342\254F6\361Nw\300\300\241\016j\334C5z.\325\245o\320V\225\277Z\323\207\265\\V\300\251\003df\235\003\005\230\023\336\267m[*+V\332N\331\2558\032\264!nj\364r`u\253Q\311\357W\"~\225~\031:U\370d\255\010_8\346\264a~+B\006\034V\224\r\300\255(\033\245]C\206\004\032\323\265\230\226\025\250\257\214\037Z\261\033sV\341\220\306\331\006\265\243a4 \324\326\200\3071\357\232\226\340\026\213\031\357\\\366\263lJ\207\307N*M4m\205kU[\212B\324\006\346\236[\345\376U\003HK`\365\257\200\331*\026\212\241x\270\252\322E\362\326U\314?1\315g\272`\324ei\2730sSm\312\212a^*\t\006\005R\233\275g\315\336\250J3\232\243*\363T\245Z\247*\325I\026\253\262\363Le\342\241e\346\237\032\340sO)\224\316)\270\246\222A\246\002X\346\254F*\344C\025r.\265\243\007j\322\267\355Zp\236*\306\356)\352\337\'\024D\314g\003\322\267\255\033\n+J\007\303\n\326\267z\277\024\234\325\270\344\367\253q\311Waz\277\024\225z\027\351Z0I\322\264\241\223\"\257\301\'J\323\267\220qZPIZ0\276j\374\r\265\201\255h\217\231\020\301\346\254\302\177\204\365\025h\034\n\263iz\310\302>\2435\257\034\352\0109\353V%u)\307z\311\325\231D\000T\026g\021\212\274\033\2127\363K\272\224?4\223(\362\374\320y\035k\340\307\216\241d\305D\313\236\325\004\221\326m\324\031\311\254\231b \342\240)L+\315=}\r\014\274t\252\262\214U\t\273\325\tFj\224\213T\345Z\245*\3259\026\252H\274\324%*7^*-\231j\223\313\317\312\005+\302Tz\323V>*9\227\013\305E\032\036*\334kV\343\025f!\315hC\332\264\240\343\025\241\021\253=\251\321\236\325,\n\005\306Ml[\2368\253\3617J\325\201\370\025z\027\253\221\275Z\211\352\364/W\243~\225~\007\351Z0\022qZP1\030\253\321=h\301\'NkN\ty\025\251\014\230 \326\204M\220+J\326L\034V\212\000He<\325\245;\223\007\255X\262E$\226\352*\356\335\304\020zU\230$,\370n\202\262uysr\020S\355\316\020U\235\374R\027\247\007\367\245\335N\335\272&\\\360k\341\246\216\241h\271\346\243h\300\252\322\2475Fx\301\025\223s\017\315UZ<Tf<\364\243c\001\203Q1*\330=;UY\252\214\253T\345^*\224\253T\345Z\247\"\3259\026\252\310\225\026\312\205\322\221c\307&\245\211\024\344\201R4D\216\225\013\304TT\016\201\2074\304\216\254\306\225aF\005X\204d\325\370\227\332\264!\253\361v\253K\310\247\"\374\365!\371\034\021Z\266\257\225\025~#\234V\234\r\362\212\271\023sWQ\352\324OW\242|\n\271\024\2075\241\013\364\255Ki\000\305i$\200\200EY\216Nz\326\204\022V\234\022t\255He\340V\255\264\240\250\031\253\261J7pkV\tr\242\256\243\344U\250\016\016}j\352\277\315V\025\302\2515\317\\\312f\324\233\234\200j\364G\n*m\324\205\3517\323\203\361R#\361\212\370\231\271\250H\371\216i\214\024\016\265]\225I$\325Y\243\004\022+2k|\265U\222\324\366\025\010\200\257Zc%V\232?\227=\305Q\224`U9\006j\244\213\305S\221j\234\213U$J\251\"UY\023\232\205\223\212\214\246\343\322\206\214\364\024\364L\n{\034\n\202F\317\025\t\217\214\323Bc\265O\032\324\273\t\253p&\005]\214U\350\272U\330\272U\264\025&;\212p\371\370\255\033U\302\216kJ,\014U\330Z\257D\330\025j6\346\256Dx\253q\267\275\\\205\372V\204.8\2558\037$V\204r`\014\232\263\034\247ui@\376\365\245\004\2359\2558$\351Z0\277\275h\303\'J\320\206\351P\340\236+J\t\203\214\203\305\\\216R;\325\250\245\3169\251..B[6\0178\254h\016\351\213\236\346\264\221\360)\345\351\013\322o\245\017R+\327\306\005MF\313P\262\232\201\326\240u\342\252\274u\003!^\331\252\322FI\311\252\355\035V\23185\235*rF*\214\213\203\212\255\"\325IR\251\310\236\325VD\252r\247\265Vh\375\252&N)\253\037\265\002\"OJv\312\211\320\236\325\021\210\223\234T\211\010n\242\234m\0068\024\337+oj\221\027\326\254\304\265n5\253\221\n\271\020\"\256\'J\230\016)\240bL\326\235\267\335\253\321\232\271\t\253\3215Y\214\363V\221\210\251\222B*\3442\232\321\202Ny5\251m\'\313\311\342\256\244\331=j\3442g\025\245\003\340V\214\022t\346\264\340\223\245i\301%hE\'\035jUm\362\000I\255\233V)\030QW\321\252}\354\027\212\317\271\270\225\233a<\023S\333\360\242\256+\361K\276\215\364o\245\rR#\363_\036\272\342\242e\366\250Yj\027Z\201\324UvNM@\361\324\016\225]\322\250\3149\254\331\303\006\371y\252\022r\346\241u\310\252\322%T\222:\253,x\006\251\272d\364\250^.*\017+\'\2459\242\332\275)\0263\212\014T\317\'\'\245)\203\216\224\251\006\017J\260\220n\244{,\236\225\013[2v\247E\031\335\322\256\"U\224\\U\270\273U\270\307\025-\030$\325\333m\330\305_\213$\325\330\262\005\\\217\246jx\333\232\266\215\305M\031\031\253H\340U\370\033\245hE6\000\031\253\220\310Oz\275\004\2308\255H\034\034V\215\274\2000\315i\306\340`\203\326\264`\223\2475\247\013\202*\355\242\357\271\031\365\255\204\302\310}\251V\3665lf\255-\332\354\316j\241\1772m\325r6\300\251\203\322\357\367\245\017F\372xjz\265|\240\320q\234Ug\207\232\204\305\317J\257$g8\305Wh\317\245A\"\340\346\253\270\252\356*\254\242\250\314:\325C\030 \346\262d\\JG\2754\257\025\004\221\325g\216\251L\2318\002\2400\340t\250\036,\360(\026\341G#\232\216H\263\320R\010\260:Q\344\236\364yt\276W\035(X\362zT\361\300A\315Z\362\203\247Nj6\265\3349\025\t\264(r\005H\261q\322\246H\352eB\rY@qR\200Oj\2268\217SW!\001j\344#\025z1\362\212\260\275*d\253*~Pjt\311\344U\230\201\316M]\216Lt\2531I\317Z\320\201\317j\277\033g\236\365~\tH\305iC\'C\232\322\202N\225\247o\'J\323\206^\005i\331L\026\\\232\334\204\251\217~z\326}\354[e\016\247\203S[\344\250\005\211\253h\240T\312\370\247\207\247\007\247\007\247\006\247\006\251\025\253\345\271\037\003\002\252\263s\315B\354\000\342\253\273T\017\322\253:\223U\244S\330\212\257\"\2663U\\\022:U9c89\252\254>Z\312\235\017\236O\2557g\025\023\247\265Wt\317AU\332\016rEV\2311\332\243K~7\021Mx\316zS\032/\223\245\'\223\305\'\223G\223\355G\224iV\034\036\2250Zr\214\032\234(`8\240\304)\236X\317J\2368T\212\220B\271\251\2225\0252\"\372T\3012q\212\010*\341E\\\204t\006\257(\343\031\251T\366\251\227\202*\3127\002\255F\325e\033\26152\260\315O\033\340\326\215\264\240V\224R\002j\364,3W\341>\225~\027#\025\245o/J\324\206N:\325\373y\260\343\232\350 \224\375\233\000\3247S\017-S\024\353y1\201\232\272\034\036\224\340\364\360\364\360\331\247\006\374i\341\251\341\252En+\345\311\007<\325g Ui$\025U\345\0035\003\315PI6\005Ty\2115\023MQn\335L\2212\2475E\343\301\252W1\2563\216EV\300\305F\351\305V~\rD\343#\245Vh\213\267J\224A\204\306*&\200Tf!\214Ry9\035(\362@\024\010A\245\3629\244\3629\351Hc \342\200\234\364\251\321)\3738\346\232c\031\340S\320b\244\024\360\265*\014\032\262\230\353Qn\r6M[\211\276aWU\375jU5:\032\231\rX\215\215YC\201\272\245V$\325\270\317\025j#\310\255(\037\245hB\375+F\027\253\360\234\343\232\321\204\364\255\010d#\002\256\306\344r+R\322\365\266\354-\364\253\022\313\271@=E>)\010\357V\322CR\207\251\025\375\352@\324\360\364\340\364\365j\221\036\276c\225\272\325\031Z\250\312\375j\224\216sU\336CP<\204\236\265\00350\234\323\220sR2\356^*\264\261|\244\325\tb\316A\252\262@P\203\330\323\032\034\255S\222\002\rFb$t\240E\264S\266\361\322\242t=j\026\214\322\010\370\2441\n\014D\nn\n\323\270#\232\215\216N1B\21475:\205\305;\002\200\240\322\005\301\247\201R(\247\214T\312F:\325F\312\334u\3435\241\017@j\352\020W\336\246^\225:\324\311V#\342\246R{\324\351V#j\271\023U\350X\325\370_\232\320\205\353F\007\344V\234\017\322\257\304\365md\371j\305\274\204J+FI1\201R\304\371\025i\037\336\247W\251U\352@\364\340\325 jz\265H\255\315|\3131\315P\224\360j\204\247\255S\220\363U\234\324,j2)6\323\227\255XQ\362\342\225\242\005\t\254\311T\0068\252\223\222Wo\2450H6\035\313\323\275@J\276qM1\000\271\246\030\275i\276VzSZ\037ja\203=\251\255\016\321\322\242+\212c\016*\0278\355Q\226\246\026\002\232e\002\220\\c\245H\267$\324\211?52\035\334\232\225W\322\246\0203t\251\005\234\230\247\010vpXTR@I\310\251\340;W\rVQ\271\030\253\211\322\247AS\250\251\324T\243\212\221X\324\350j\324M\357W\241n\225~\026\255\010^\264!n\225\245\003\364\255\030[ U\325\031\025f!\202\017\275Y\022n?J\261\023\374\242\255#T\352\3252\265H\036\244\rO\rOV\251U\253\346\251\253>~\365B^\365NJ\254\365\021\024\200S\266qB\247\315W#\207\271\351Q]\312\021<\265\357Yn3\315U\2226=\252\026\215\300\306*5\211\267\344\255K\262\243u\246\250\031\346\234\311\305FW\024\326P\313\357T\345R\r@\304\201\322\253H\325]\237\025\013\313P\231\t4\201\232\246\215]\217\000\325\350\255\'l|\246\257Eg8\034\241\253q\331\312W;\rJ!\224tSO+2\257\3355RW+\235\331\250#\271\303\340\364\253@\357\371\224\325\210\367\005\346\257\302r\2435eEL\265:\221R\016\224\253\311\251\323\336\254\307\332\256\304\334\201W\341j\275\013t\255\030_\245h\302\331\305h\333\2675\245\023dU\370\202\233r{\212\256n65O\r\320 \014\325\370\245\014:\325\244qV\024\323\301\251\025\251\341\252Ej\221Z\276s\225+>\341q\232\316\225z\325)\005WaQ\221@\024\265<\021\006\033\217AN\222C\214-Sx]\333-J-\0169\024\033U\364\246\233U\307J\202[eQ\322\251\274x\'\212\256\313\223Q\221\203N\004\032k`\364\250\360A\250\245@j\224\213\214\212\245(\252\216\244\232#\264y[\000\023W\342\320\345l\022\r\\\207\303\262\226\037!\307\322\267l\2746\212\0032\201Z\277\3316\311\036\000\031\247\255\235\272\250\033zw\251\014\021\036\000\002\243k(\363\221\326\201e\0360{\326]\356\2302Lc \326,\332k#gn)\320Z\313\274\000\rk\245\231h\307j\222;vC\203V\2218\351S\252qHx\346\225e\003\214\324\213 \365\251\321\363V\3425r3\305Z\211\261W\340|\365\253\360\276+J\007\351Z0\267CZ\020\275h[\310\000 \367\025\\\300\355!\347\214\324\253l\3523\326\255B$S\305^\212^\307\255\\\215\352`sO\006\244SR)\251\001\257\237\344A\212\317\270\217\255e\314\230\315P\225y5]\227\232\210\216i\246\232z\325\373r\r\271\003\255H\220n\346\236`\003\265#E\307J\256\351\212\210\236i\031\003\2575Fxx<V~\300\030\324\022\214U\1773\234S\263\232)\217UdL\325f\266gl(\251\341\322\035\334n\025\320i\372\004`\006a\212\336M2\010\324qR\010\221\006\025E5\233\035*2\304\367\250\330\267\255G\226\035\351<\302;\322\211\275\351\336b\367\252\367\021\305\"\223\201PC\022\356\311\035*\340EQ\236\364\326\306i\353R\214m\252\262H\000\"\2514\247\177\006\247\212~@cW\342pG\025v\027\351W\2439\253(qW!nEhB\365\241\003\363Zp?J\320\211\261\212\273\023U\264\347\232\265\036EM\264u^\r5\217\361\016\243\255O\004\271\357W\2439\025 \247\212\225M<\032\360\211R\250\\/\025\227:pk>U\305Tq\315DE4\2550\306Oj\232\022\3126\326\245\250\314d\232s)\'\000S|\246\352j\274\361\340{\325_(\223\322\232P\216\364\313\210\301\204\340sY+\0212\221\212e\335\261\021\022+\034\214=N\243\212q\034Tdd\324\260\331<\307\201\305l\331h\245\261\362\217\251\255h\364\350!\003(2*|*\016\000\342\230\322\212\211\244\364\250\211$\323zSY\2522i\215Q\223\212n\352B\300\365\241d\301\351O\363s\322\200\331\251\224\324\252x5N\352\027\306\345\351T9\007\232\221^\256\301!\030\007\245iC\222\001\255\010\211\003\232\260\217\315[\205\253B\026\255\010[\221\315iB\331\305h\304\334\n\273\013U\330\232\256\304\325iGqM\222\"N\345\353Q\200\310wU\333y\201\002\256\307\363T\230\002\234\010\024\365a\351^\037 \2523\200A\254\273\201\326\263f\025M\227\232\217nMM\025\266\343\222*\317\331F\334b\237\025\206\366\351W\322\321\243\033q\201Lt\np((\002f\251\310\027<\363P\266\320\274\n\254\351\223K\345\3450zT\006\3324$\201T\357\024\010\017\322\271\326Be<w\251\2218\346\222B\000\246D\215$\240(&\272\235+Mm\240\270\300\255\215\236Z\340T\016\325\003\261\250\311\024\302i\205\275\351\205\207\255F\304z\324e\251\013S\t\250\3154\236)\245\251\310je5*\232\225[\002\244$2`\326m\324!\\\225\025\002\251\2530\203\232\324\266,\007N+F68\035jU\'5r\023\323\232\320\205\253B\026\255\030\rhD\375*\364mW\"j\275\023U\350\233\"\254/ZIP\024\315TV\362\344\343\245h\303)`1S\341\232\236\241\200\371\205<p:\327\212I\310\252\023\326d\375Mg\314*\243/5,0\026n\225~;r;U\270\255ry\025\243\005\272\"\347\003\353Q\335\025H\370\025\234Wsd\324s\023\267\002\251\270\250\034S1\305(\034Tr&GZ\313\276F\362\310\355X\214U\t\342\242iy\3004\350\240\222f\340\032\335\3234\300\0301^k\244M\261G\201\216*\031\245\311\353U]\215FNz\323\t\025\0335D\317Q3\324l\364\302\324\322\370\246\231)\205\250\315&y\247/Z\225[\025\"\265<7\024\364zd\2447j\201Pn\2531\204\317\025r)1\306*\344R\234sS\253\344\325\270\233\245hBsZ\020\234c\232\321\205\272U\370[\245^\211\252\354&\256\304j\344OW\021\252Br\270\252S&\033\353R[JT\355&\264c\223#\255L\037\326\201\327\212\361Y[\212\317\230\365\346\250J*\224\253\232\201b\334\365\255kj\002\347\025q`\311\351S\307\036\0074\362x\364\025F\340\357l\016\202\241\333\305W\224UfZg\227\232\215\242\333@Q\217z\206A\212\314\276\000\245`\\\252\223\362sL\202\325\235\306V\267-mv\000\241q\236\265\271\n\210\241\030\034\322\263\026\250^\2429\3151\311\003\006\253\263T,\365\0239\250\331\2522\324\302\324\322\324\322\324\322\324n\024\241\2058?\275=\\S\274\320)\353&{\323\303\320Xb\221NML\256\243\250\2531J\244\343\245]\216\255F*\324|U\330[\245h\300\325\243\001\342\264\"5z\023W\2435r3V\343j\271\031\310\251A\246H\271R\rUN%\255(NT`\324\340\232\221Mx\224\246\251K\324\325\031zUf\\\232\263kk\275\301\305l\307\000T\002\237\263\260\024\216\002\214TR\034.\007Z\250\343\232a\351T\346?6*\034d\322\220\005F\370\250\310\031\252\362\343\221\232\313\236\007\235\210\317\025\017\366r\2022*\3546Q \014\024dS\335\304m\3063\351RF\354\347\255N~T\252\362\314\250\271j\316\233QD$\356\025I\265`[\236\224\035R\003G\332\343~\215G\230\010\3105\021\224Tm(\250\214\343=i\276x\250\244\271\013\336\253\276\240\007J\204\337\2714\365\276\222\244\027R7\025j9\216\336i\305\331\272qR#\260\034\232\223y\343\232z\276x\2531c\251\251\000\347\212\235#\343=\352\334E\224\200M_\2178\006\255&1V\241\353ZPv\255(M^\210\325\350M^\210\364\253\210j\324f\256Dj\3004\346\033\206*\234\250RM\303\245Oo.\016*\362\266EJ\243\326\274JST&j\250\347&\210\342\334\340b\266-m\302\017z\266W\214R\037\225}\315B\304b\252\310z\232\201\272\3242>\0063Te89\250\214\200rM0\334\002x\300\250\332u\365\252\362^(<\032\315\274\275\000\034\036j(/\224\367\346\256,\276g\275J\031\261\214\3242)\335\232E\234\307\317aT\256\365\226BT\032\306\271\325&\220\237\230\325\026\232G9$\323\014\204u5\033M\203\326\201vW\2759u\'O\342\253\t\252D\303\347\353S\245\3242/\rI#(\344\020j\244\267\014\007\312*\224\263\273\036\265\007\314MO\014d\236EhG\020\002\245X\2239\305N\252\005H\024z\324\200\250\352i\014\311\234u\245Y\001>\325f99\034\325\224`M[\216\255\307\206\"\257\300\017J\266\261\215\271\025<#\014+F\036\325\241\rhE\322\256E\305^\204\325\310\352\324}\252\324f\255!\310\251W\221L\2252\204b\253\307\303}+B#\305N\rx|\306\250JI5\020RM_\262\266gpq[\"\r\253HP/-PH\302\253H\343\025Q\333\232\201\311\316j\026RNMS\270e\000\232\315\226nO5U\347\307z\251%\313d\340\3259n$\355Tf/ $\223N\265\014$\002\267\240\341\005X\310\025\024\207\035\3532\356\361#B\240\363XSHdri\202<\3221U\025Ri@5U\245\367\250Zoz\211\246\347\2553\315\367\245[\211\020\345X\212\235u)G\004\346\2365\014\365\024\357\265#v\025$sC\374U<sD[\203V\321\324\216\032\246WQ\374B\203s\032\177\0275\033]\223\367iD\307\034\234\320\254sV#cV\323;r*\324D\361W\242cWa\373\302\264\242\310\301\307\025y\000)\221RG\301\253\320\032\321\207\245_\212\256\304zU\310\215]\210\346\255\307V\223\025b3\315XQ\315+\256V\251\203\211H\253Q1\035j\322\034\327\207\312\t5\007\224X\340\n\261\r\2133\002El[[\254k\322\2540\000\022GJ\247#\344\223T\345\3115]\220\346\240q\203P\261\366\252\362\260\nI5\215u>X\200x\254\351\036\252H\304\324\'\2558\"\3106\232i\262\344\363\305*\333l\344u\025a$)\301\025\'\332x\351Q\311#:\341k*{7\221\211\344\324\037be<\203QK\031\215N\005e\\\273\202EPvcP\263\032\205\230\323@$\323\3262M?\310cA\2674\303\036\017\"\234\022\234\020\216\365\"\203\330\324\350\362\001\324\324\333\344\307Z\001c\324\323\325\210\342\246F\311\353Vc\000\325\204\025j6*q\332\255\306A\305_\204f\257D:V\244#**\334y\013\322\245N\265r\032\277\t5\241\t\365\253\321t\253q\325\310\215\\\217\232\265\031\253)S\241\251\205Wx\201\223\"\245X\316\337zz\022\016\rx\337\226Y\261\212\267\r\240\000\02295v+p9\305X\330\025x\252\363\002O\265W\362I\344\360*\t\004`\341NMT\223\216r*\234\204\223U\344p\240\222\177\032\307\274\272\334J\251\342\263$bj\263d\324,*&\024\200\355<u\246\275\321Q\353P\265\334\244|\240\325W\274\233wz\222\033\211\\\216\265}\037j\363\326\235\346\344\364\247\022\244r*\255\304\033\324\225\254\251\364\307p[\025\231=\203\241\306\332\246m\034\236\224\323c\'\367i\r\233F2E\"\253\217\340\375(g`:T~n:\232]\352\302\232X\nM\336\225\"\023\351Vc\"\245\355E(\251W\255Y\214\343\265YF\253Q\341\206*\304{\225\260kJ\335\270\255\030\217\250\255\033r6\325\350\275\rN\251V\"\030\340\325\330\273U\370N*\374G\212\271\021\253q\325\310\316*\324f\255\247J\224\034T\252\324\270\371\263V\024er)\216\207\250\353^Oo\016\\\022+I!\317j\234D\024S\037\000Uv\003\005\337\200+2\366\364}\3048\002\262\244\271#\241\252\217rKri\206|\216MP\272\270-\362\251\342\263$\344\324\014*\006\034\324L*?\255C#\2000*\233\362jH\023\'\221V\036\321\034gh\024\261\301\260\000\270\024\363\264\036X\na\220g\345\301\250X\314y\rI\347\262\2141\3152K\206\306\007J\245,\300\217\230Uc,y8\024(\311\315,\2011\363b\250\3154J\n\214U\007\205\246l\2514\337\260c\253\363CZ\021\321\2054[154v\236\3659\216(\323\007\255F\030\026\342\246\013\357O\n1OT\317J\231#=\352t\\v\253\021\2405b1\266\256\304Cu\025~\000\243\232\321\205\2061W\241\306x5z3V\343>\325a\007=*\344B\255\306*\364\006\257GV\3435m\017\025f3V\3435>~ZT|\232\260\204\036\rL\231Z\225\260\303\322\274\272\336\002\010\342\264R<-5\2075Vi\025~\361\342\261\265\013\360F\3058\002\261d\233q\353T\345\227\025_v\343H\344\343\002\252I\336\253=Wz\205\205B\330\250_\247\025RC\315@\331\317\02549\034\346\244i\317L\361Q=\303\021\200q\364\250\303\022rM#\310@\3008\250\274\307\354\306\232\306S\3375\013\254\347\326\241te\\\271\252\336|jNEW\227Pp~A\201Tf\275\231\273\232\250\322\310\307\222jx\245\224\014\002j\302\227=sR\250&\237\222)3\'\360\203H\"y\033\234\324\353m\264sO\021\324\213\037\240\251\0262\265*\223\236\225:c\275N\230\355S(\315XN*\344MW\242n\225~\027\255\010_5z\026\253\211\216*\344X\342\256 \300\2531\034\021W\3425n:\267\031\253IVc\251\213\014b\232\247\232\2367\344U\304~9\251F\010\3105\377\331"
-byte_png: "\211PNG\r\n\032\n\000\000\000\rIHDR\000\000\002\000\000\000\002\000\010\000\000\000\000\321\023\213&\000\000\003JIDATx^\355\334Yn\3430\014\000\320 \275\377\221k\014\246\235\026\250\006\256W1\224\370\336_\2354\213$S\244\344\370\361\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000`RK{\200Z\014\000\000\000\000\000\000\000\000\000\000\000\000\000\000\006\365l\017\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0000-\367\232\000\000\000\000\000\000\000\000\000\000\000\000\340\005\374\254\245\256\245=\000\000\000\000\244g-\007\000\230\226\215\213-RA\000\3160\177\000\000\000\000\000\000\000\000\314\3075!\000\000\005\371\351\r\000\014\345i\001\007\000n\245,\006\000\250\340\255=\000\024ey\025\000\000\200\241(d\263\212\352\231\263\333\331Q\237o\030g\033\222\201\030\365\014\353\275=\000\000\034%\027\334C+Q[\2273\300j\003L\241K|\000\000 \231^Y_\257\327\005x\0101\247\365m\270\357%Ak\203Y\365\035\000$\246\353+X\273\361\342\312\341UB8\014l\337\t|4,0\032=\\\315\235=\276/\212\000\000@\200;\023\335\271\254\255\002\302\313\250%\001\240\013i\037\000\024\245\316&\001\303\020 \216\372\277\254$]\357\026\257P\310j\232\237$ \321\270\332/W\377\037\000\000\200K\276\3122\345\031\220\202`\304\303\246Py\253\233\004\000L\316\014\020.(\371\326\263\300\016A\021\tHD\212P\234\001\000@CM\000\000\231\231\251\001\200M\233\253\276\233O` \207\362\303CO\006\000\000\310GY\003\000\000\300>*\310\342j\r\200Z\337\026\000\000\000\356\347\266\313\000\000\000\000\014\312e#\000\000\300\005nF\367\032M\273\377\275h\341\253\272s\001Ca\316G\000\000\200\001]\330\257U\007\002T!\342\003\017\241\000\240\224\013\213\005\244wlJ7\026\000\n96E\000@g\252\221`~\001\000\000\0000\033\245uC\203\000\000\300Ord\000H\312\325\234\000\000\000\300\026\353\007\000\000@N\252\225\237\\\242\005\000\000\000\3005o\355\001\000\000\210f\033\270\032\033\335\000\000\261d\334H\302\001\352\222\007\000\000\324c\031\000\200\341X\300\270\211,\000\000\000\200\\\346(\371\325\333\000\000\000\003S\324\365\322\266l\373\367\213,I>\007\020\252\327\231?\307\362f1\275\006\003P\224\231`,\037\223\300\221N\333z\356\326\343\3743\354\364\373\313\007\327\371\005\3752\036\000\200\214L\336\000\325\324\216\374K\301\357_\357\033\003\237\"\327f\227\3107c\277\250~\211z\037&%W\201\016\336\333\003\014N\250d\027\247>\214@H\007\200\211\005.\224\313\376+\213\033g\244\245\254\000\000\000\200y=\255\377\000\000\300\334l\366\325\246\342\343\233`\320\3370m,2\324\243\317\0010\033@=\303\024(\264N\004\354\247\356\006(\313\024\000\220\321\275\321\371\336W\243?=\006\3779\261\326\001\000\0000\263\271\312\244\271\276\315\005\032\002\000\000\000\000\000\010b[\002\362q\r9\221\314\003\221>[;\366\034\277\275\207c?>p\320\3069\277\361\3606!\000\000\340\210\313\351\0270\034U\023\000\224#\355\007\230\333\037\020\217U\035\335\242\351\375\000\000\000\000IEND\256B`\202"
+byte_jpeg: "\377\330\377\340\000\020JFIF\000\001\002\000\000\001\000\001\000\000\377\333\000C\000\003\002\002\003\002\002\003\003\003\003\004\004\003\004\005\010\005\005\005\005\005\n\007\010\006\010\014\013\r\014\014\013\014\013\r\017\023\020\r\016\022\016\013\014\021\027\021\022\024\024\025\026\025\r\020\030\031\027\025\031\023\025\025\025\377\300\000\013\010\002\000\002\000\001\001\021\000\377\304\000\037\000\000\001\005\001\001\001\001\001\001\000\000\000\000\000\000\000\000\001\002\003\004\005\006\007\010\t\n\013\377\304\000\265\020\000\002\001\003\003\002\004\003\005\005\004\004\000\000\001}\001\002\003\000\004\021\005\022!1A\006\023Qa\007\"q\0242\201\221\241\010#B\261\301\025R\321\360$3br\202\t\n\026\027\030\031\032%&\'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz\203\204\205\206\207\210\211\212\222\223\224\225\226\227\230\231\232\242\243\244\245\246\247\250\251\252\262\263\264\265\266\267\270\271\272\302\303\304\305\306\307\310\311\312\322\323\324\325\326\327\330\331\332\341\342\343\344\345\346\347\350\351\352\361\362\363\364\365\366\367\370\371\372\377\332\000\010\001\001\000\000?\000\372d\361@|T\251.;\325\204\2375/\231\234Ts6qP9\300\250]\252\006|Tl\364\302\364\302\364\205\2517Q\272\215\324\205\251\205\251\205\351\206Jizc=F\317Q\263\324l\325\013\265B\317P\273\324\016\365\013\275@\357P\273\324\016\365\003\275Ww\252\362IU\244\222\252\311%V\222J\251,\225Y\345\252\362IUd\222\253\274\225ZG\252\357%@\357P\263\324e\351\245\351\273\251\245\3517Q\272\224\032v\352P\324\360jE5\"\232z\265M\022\0275\243mm\223\322\266\254\3556\340\232\372\210\3101L2P\262\363S$\336\3652\317R4\200\240\372\323$nj\273\232\201\333\212\201\237\024\302\364\322\364\233\351w{\323wR\357\244-Mg\250\231\3526za\222\232^\243/Q\263\324l\365\023\275@\355P4\225\023\275@\357P\273\324\016\365\003\275W\222J\256\362Ui$\252\322IUd\222\252\311%U\226J\252\362Uy$\252\362IUd\222\240y*\273\311P\273\324,\364\302\364\322\324\322\324\233\275\350\335\357F\352P\324\340\364\345jx5\"\265H\rO\n\027\"\264\255\242\351[\026p\005\031\"\264\341\030\300\257\242<\376)\246j\004\265*MR\254\325(\233#\025&\365\300\346\242\220\360j\273\265Vv\246\026\246\226\243w\275\001\351wf\223u!z\215\236\242w\250\231\3526\177zo\231M/Q\263\324M&*&\222\241y*\t$\315B\322T.\365\003\275@\362Uw\222\253\311%V\222J\255$\265ZYj\254\222UYe\252\262KU\244\222\253<\265]\344\252\362IU\336J\201\337\232\211\236\242f\246\026\246\356\244-I\2734\006\315\033\251w\323\203S\225\252E9\251\223\332\247\2122\354+R\336\016\000\305jZ\333\355\031\"\257\3049\305iZF\0168\257t\023Q\346\322\211i\3136*E\236\245\216~z\324\3516q\232~\374\217\302\240\220\325g5\021jM\324\271\024\264\335\324\205\251\205\3526z\211\236\242g\250\213\323K\321\2775\023\276*\007\222\241yqP\274\265\013\311P<\225\003M\232\205\345\252\362KU\336Z\257$\265^Ij\254\222\325i%\252\262KUe\226\252\311-V\222Z\256\362\325y$\252\357%@\362sQ3\346\230\315Q3\323\013SK\342\232\322S<\312O0\322\253\023R\250&\246H\211\251\222\002jd\2675n;S\351Z\026\266\230\0315\245o\000\004V\200\217\345\030\251\340\207&\265mc\333\212\365\345\2334\276n{\322y\370\247\t\352E\233\336\236\263\363V#\237\034\346\254$\273\200\006\206|\214\036\265Y\332\241f\301\244\017N\014\r.i\254\325\031zc=D\322T,\365\023=F^\233\276\220?4\311[\212\252\362T\017%@\362T/-@\362\324\017-Wyj\007\232\253\274\265\004\222\325i%\252\322KUd\226\253I-U\222Z\255$\265ZI*\263\311P<\225]\244\250\231\351\206@*&\233\025\023K\357Q\231sI\2734\340\245\251\342\006\306qN\020\023\324T\261\333\373U\270\255\275j\334V\313\351V\343\264_J\261\035\250\354*\302@\027\265O\032\325\310\027$V\2341n\002\257Am\355W\340\200\212\364\010\347\307z\224M\357A\220\322\tjE\232\236&\251\322n\0075b9\361S\211\201S\232\210\277\006\241v\246o\247\t)|\312C%F\317Q3\324L\365\023=D\317Q\263\323\013\322y\2304\217&ES\231\360sU\236J\201\245\250\036J\201\345\250$\226\253<\265\003\313U\344\226\253\274\265^Ij\264\222\325Y%\252\322KU\244\227\336\253I-W\222J\254\362T\017%@\362\342\242y}\352\006\224\347\257\024\307\2234\306&\221FM[\206\330\266\t\253\320\333\2008\0258\267\342\217$\016\325\"F=*X\342\315Y\216<U\330\220b\254\"\214R\343\232\236%\253\326\321\344\212\330\266\213\201Z\020\305\323\212\320\212,b\272D\223\245H\262`\324\202L\323ZL\032\004\336\365\"M\232\235%\251\322Z\231g\342\236\262\002\270&\230\355\362\324,\370jA%;\315\246\231i\215%F\322Tm%D\317Q3\324L\364\303%4\311Q\264\265\004\222f\251\313&\rWy*\007\222\240yj\273\313U\344\226\253\274\265\004\222Uw\226\253I-W\222Z\253$\265VIj\273\313U\336J\257$\225\003\311\216\365U\346\316qU\232Pz\232\214\277\245\030\315K\0349\0314\343\020\024G\030\335W\343\000%^\267\\\2408\251\366\361H#\3158ERF\233[\221V\202n\350*\302&\006*d\\R\371\1775Z\206:\320\266Lb\265\355\2008\2558#\315]\2111Z\213!\003\232x\226\236&\3051\347\006\231\347{\324\2517\275XI\275\352e\236\236.*h\347\354jO7 g\245E+`\212\214\311G\233Hd\246\031)\215%1\244\250\232J\211\236\242g\2464\225\033IQ<\265^Ij\264\262f\253<\265\003\313P<\225ZI*\274\222\325w\226\253\274\265\004\222\325g\226\253I%V\226Z\255$\225]\344\250\036J\202Ip*\244\216[\332\253H\371\357P\362i\3529\247.3VT\341z\323\032L\232X\317\315W\003|\240V\215\243e\005YQ\223R\252T\213\036jA\026jXSkU\301\027zz\255=c$\364\253P\307W\242\210\236\202\257\301\023\216\325\251h\217\351Z\220\306N3V\327\232\215\362\246\242i\217\2554\315\232\004\324\345\233\025<w\036\3652\317N\363\375\352D\270\367\2531\334eq\232V\223$s\232c>3M\363i\014\224\206Ja\222\243i*&\222\243i*&\2235\033IQ4\225\003\313U\344\226\253\311-V\222Z\256\322\324-%B\362UY$\252\322IU\344\226\253\274\265]\345\252\322KU\244\2235^I*\006\222\242w\305U\231\2306r1U\344rEBy4\001\221\232\t\367\245SR\003\305\000f\245\215y\253\321E\271sZ6q\376\354U\324\216\247X\370\247\252U\210\341&\254$\030\307\025:\306jd\200\032\235-\275\252\355\255\2139\351Z\366\366\001\007\"\256$h\235\252\324\030\354+F\010\367b\242V\347\212d\215\311\367\252r6\322i\236e\'\231N\022S\326\\T\3517\275I\346\322\211\261S\307q\317Z\224O\2200z\032y\227?Zc6)\276e\006JcIQ\264\225\023IQ4\225\033KQ4\265\023\313U\244\232\253\3115Vy\252\t&\252\362K\305Wi\260j30=\352\t^\252I%V\222Z\256\362\325w\222\253\274\225\023e\206zT\022*\201\313sP8Q\334\324N\352\005D\304b\252\311\311\250\310\342\224\251\034Rb\225E9z\324\250\265b(\3130\000V\254pm\214/z\277o\016\325\002\256G\036je\216\246\216\034\234\342\255\307\025N\221f\246X*\314\026\305\217J\322\267\260\347\221Z\326\366\351\032\361J\340\267\003\245:(\t\353W\340\203\221\305i\333BN8\254x\244\310\024\262H\007\025N\341\271\315V2b\224IO\017N\017R,\230\251\004\264\276m*\315\203\326\245I\371\253\002m\324\341/\03754\310\t\353Lg\307za\222\243i*&\222\242i*&\226\242yj\t&\367\252\322MU\236oz\257$\336\365]\346\367\250$\233\336\240y\263\336\2413`\363L\222`j\244\217\357U\244\177z\254\357\223\367\205D\304g\2265\033:\216\225^YO\255Ww\315D\315P\273S\013dc\2651\2054\214\212\010\346\220\217JJz\014\325\210\220\234V\235\225\267 \326\304V\300(5m \251\226<T\361\307\232\265\034^\325ac\253\021EVR\034\325\350\"\021\201\353W\243;\261\201V\024az\323\321I5r\336\002\304qZ\366\232ql\022+b\326\304.8\256\002\332~9\251]\267)9\252s\276\0235T\311\236\364\325\227\236je\226\244\017\232z\275<=\036e.\372p\223\006\245I\361R\211\370\2453\003MiH\347\250\250\332J\215\244\250\232Z\211\244\250^\\w\252\362MU\344\232\253<\365ZI\275\352\273\317U\336oz\205\347\367\250\036Z\204\315\357Q\311p*\254\22795^K\217z\254\363Tfl\3655\033KP\274\225\013I\315\004|\265\003\036i3\357K\214\322\021\232n(\244\013R\306\265~\326\014\221[6\261\005\305i\3068\025m\020b\234\023\'\212\267\004\036\265q!\317j\235m\372T\321\305\315^\206\016*\304v\345\215^\216\337\245Z\212\320\275]\203O^\365\245ml\221\364\0315\251m\021b+N\030zW\216\333\315\3163WU\216\332\255!\310aY\356\373M4IR\244\2652\311R\t)\342N(2R\211)\336f{\322\207\305;\315\245\363i|\3760i\206Lt9\025\033KQ4\265\013\315\357PI7\275U\222j\255$\365^I\252\263\317\357U\344\232\240y\375\352\007\232\240i\275\352&\224\261\353PI!\035\352\263MU\345\233&\241i*6\227\035\352&\234\372\324m1\246y\234\323\374\377\000\227\336\242\335\223J)\301\251q\2326\322\354\024\005\311\342\254\301\016H\255k8+N(\360\005]\2012*\332\256\005K\024l\304qZV\326\244\362j\364pc\0258\206\245\216\334\236\325z(0*\325\274\034\364\255\030\255\275\252\3446\276\325r\033ROJ\321\267\264\000\014\326\2041*\325\370#\3175\340\366\304\3479\255\030\237\"\243\230\355&\262n_k\232\204IR,\2652MS\243\027\351N.P\340\322\031sN\022S\204\264\341/\275/\231G\233\212i\227\336\232f\2464\325\003\317P<\376\365]\347\252\322O\357Ud\237\336\253I=A$\325]\347\367\250\036oz\201\346\367\250Zzh\226\240\236\\\325W\226\253I/5\023IQ\264\265\023IL2Ry\264\t*E\371\207Z\\\363\212r\232\225i\331\305(\005\217\0252C\201\232\263\010\303\n\327\264\003\212\321D\316*\354\021t\255\010\255\363V\341\200f\256\306\273j\334)\236\242\256\303m\273\265YX\000\355S\307\006j\355\265\2779\255(a\366\253\320\302}*\364P\340t\253\010\204\236*\355\274\035+F(\260+\347[i@\035j\364SzQ3\356\025\225zy\315U\017J$\251\026^kB\302\351\021\306\376\225.\245q\0236c\340U\024\237\326\246IsN\337\315(\226\227\316\2442\323\014\264\3235F\363Uw\237\336\253\275\307=j\264\223\373\325y\'\367\252\262\\Ui\'\367\252\355=B\363\373\324\017?\275A$\365\t\232\205\237\336\242\232l\367\252\222KP4\274\324O%F\322S\013\323\013Ro\245\017OW\251\025\263\315J\246\246L\236\005H\007\030\025b\004\030\351V6qDc\006\264\354\337\030\255\233Q\277\025\253o\035hE\037\0252\215\265j\004.FkJ\010:qZP\303\205\251\222\034\366\253p\333U\370-\353F\013p{V\2046\334\016*\312\333\373T\361A\203\322\257A\017\265^\212,\327\312\342\343\035\rZ\266\274\311\306j\327\237\232\251vASY\305\360i\004\224\365\222\237\347\020sH\367\004\367\253\320\342[2q\363\016\206\240\216~qS\211i<\332_7\216\264\206Zi\227\336\243i\252\t\'\367\252\322\\{\325i\'\367\252\357q\357Ud\270\367\252\322\\{\325w\270\317z\256\363\324\rq\357Q5\305@\363\373\324fjO:\243\232^3U\336Z\256\322sLi)\236g4\205\351\013S\013\320\036\245G\251\221\252\304x=j\334Q\026\034\014\n~\315\247\025n\025\030\251q\305>8\371\253\260G\202+^\315\366\221[v\307 \036\325}y\306*\304Q\226\"\264\355 8\351Z\366\326\371\253\253\027lU\210\240\311\351W\342\266\300\036\265z\013^\234U\350m\366\221\305_\202,\342\255\2545<PsV\322,U\313x\375\253\343H\356\303\3645j\033\202\033\255iC8q\357L\231\352\204\307kqQ\007\346\234$\247\211)\245\360j\354\027\330\217`\3075\037\335$\226\034\322\231\260q\232\014\352;\232w\2341\301\2443S\032lw\250\236\343\336\253Iq\357Ue\270\252\317qU\244\270\367\252\262\\{\325w\270\367\252\317q\203\326\240{\212\201\356*\026\270\246\031\363M3{\322\t\271\246\3136W\025U\245\250\313\363\326\230^\230^\224=.\357zc\032@\325*5X\215\252\344\'\245_\216N)\300d\346\254\304*\314q\346\255G\r]\206.\202\257\303\0161\305jY\260\310SZ\361E\2201Z6\320\217J\326\265\204q\305i\302\200\n\271\0149=*\374\026\370\355W\241\267\347$V\225\265\266q\221W~\315\362d\n|)\266\256$y\253P\305V\322\034\232\271\004\025\360\2142\354<U\370n\003\001\3175~\336c\236\265jG\371\001\315U\270\350\rU/\203G\231\357OY3J_\212\214\312A\340\325\210\216\340ri\246LQ\346\342\233\366\214t\245\027\031\357Q\275\307\275C%\307\275U\226\347\336\252Ks\327\232\255%\317\275V\222\347\2575Y\3563\336\253\275\307\275W{\214\367\250\036\343\336\240\222\343\035\352\023qQ\265\316;\321\366\240i\3136i%\223\212\255\346\363I\346\373\321\2734\326j\003\322\207\245<\322\001\315J\225f!\214U\270\252\354Uj1\232\263\022\325\330V\257E\036EZ\202\"\017J\323\202.:U\250a!\205j\333\222\240V\265\231\014@5\265m\026@\255+x\t\305jAm\323\212\322\206\r\243\245^\202\r\335\253F(6\201S\371Y\024G\001\315\\\212*\271\014\025z\013\177j\273\024\025\371\366AC\315K\034\230\357Z\326m\234\032\274\355\214UK\251;U\'\223\232o\233R,\274Pe\2464\265b\332u\311\031\244\231\3109\025\001\237\336\230g\367\246\233\232c\\`u\250$\271\367\252\222\334\373\325In}\352\264\227>\365U\356\271\353P\265\306{\324\017q\236\365]\347\347\255B\363\373\325y\'\367\250\032zg\3323\305F\323\025\251\240\271\311\353SK!\333\221U<\356h\363iVsR\206\336)\233\360i\341\252U\247\252\363S\306\234\324\350\270\253Q-]\211j\344IW!\216\257C\025hA\037J\277\0145\247on6\325\310\255\3623\232\263\014x\353Z6I\363\347\240\256\216\311x\025\271i\006@\255(a\307j\277\024Y\025z\336,\032\277\034u0\207\212\22689\034U\330\255\372U\350-\275\253B\033n:U\205\207\025\371\333qp%#\025\037(FkR\325\212 \3645p\\|\244\032\245sq\226\252\255.i\276m(\227\002\235\346\323\032J\201\247*\334\032\274&\0060s\332\251\3116\t\250\232\177zi\270\367\250\332\343\336\253\311q\216\365Rk\217z\247-\317\275T\222\353\336\253=\317\275B\327X\357Q\265\317\275C%\306{\324\017qPI>*\006\270\250\314\376\364}\243\"\244\212nj\341\233)T\214\237=9e\353NV\315L\217\203\232\225\200e\310\353DGuYA\315XE\346\247\2118\251\321\t5n(\352\3541\325\310c\255\010!\351Z\020\301\322\257C\rh\333\303\234V\204K\221\200*\3346\344\216j\3746\2758\255\033{\177j\332\261\210\341x\255\3735\300\025\255\n\016*\3641\373U\310\343\305[\214U\250\323q\025lE\302\325\350 \3168\253\360\303\200*\354Q\374\265*\307\223_\232&Ozr\312X\3435r+\362\212\024\366\253\037n\334\265ZI\362j?6\232e\367\247\th2\343\2751\246\250d\227\336\247\202\3531`\236\225]\347\250\032~z\323\r\307\275F\367\034u\252\262\334\347\275T\232\347\336\251Ms\357T\245\271\347\255Wk\232\211\256s\336\242k\236:\324ms\317Z\211\256=\352\'\237\"\240i}\351\206\\\367\247#\344\324\361\2229\251\374\354-V\022\376\363\255I\274\2065$rT\350\371\253\020\266~SS\"mqW\0253\203S\306\265j$\343\025j\030j\354p\037J\265\024X\355Z\026\360\023\216+N\336\330\361\305iAjH\351V\342\266\366\255\033k\177j\324\202\320\005\351\315\\\206\337\'8\253\360\333t\342\264-\355\361\216+b\312\3378\342\265\240\267\306+V\336,\201Z6\360\325\264\212\254\303\001$U\350\242\307\025j8\262EiA\017\312*\344QU\264\217\212z\'5\371\200d\241d\3058KS,\370\036\324\255&Fh\337\3054\311F\374R\031j&\232\242y\263I\014\330$g\2552Y\260H5]\347\250\315\307\2775\014\227\030\357Ud\271\353\315T\226\343\035\352\224\327\036\365NK\216z\325g\271\367\250\036\353\035\352#u\236\364\323s\357L7\024\303?\2754\313\232\211\246\301\251#\271\002\254-\330\"\245I\267\003P\226\303\324\301\370\316jHX\232\265\023sV#8z\321\2157\001W`N0jt\217\332\255E\035iZA\272\264R\333\216\225b+\\\366\255+k]\270\342\265-\355\217\025\255mm\362\343\275Y\216\323\236\225\241mi\216\325\243\025\271\030\342\256\301o\323\212\321\212\333\000qW \203\221Z\266\261\355\305hBGAZv\230\255(\312\216\225n\034\023Z\020F\r\\\212\032\263\024<\326\204I\200*\344KV\221x\247\252\014\327\345q\224\016\264\343&\361\225\350:\321\347\206#\024\377\0000\202*\302H\016\024\323Km4\205\363M/L/\232\211\344\250\032ZX\211\034\232m\304\237-g\3116;\324\rs\357QIq\357T\345\270\367\252\262\\g\275T\232~*\214\267\034\365\252\257s\357U\336\347\336\241k\237zAu\307ZSq\236\364\323?=iD\371\357Ly9\244I\252O7\025n\332\\\361RH\377\0005J\217\271jh\237mZ\211\262j\375\272\006`Mk[\250\000b\256$}\361\326\255G\027J\267\0249#\212\327\264\203\030\255H\241\311\351W\340\264\335\216*\364V\245q\307\025\243o\007N+N\332 +F\010\007\025\243\024@\257\002\246 )\025<R\250\305]\206R@\300\253\220\271\343\212\277l]\334\000+^\336\022\275z\325\215\376[`\324\361\310\371\310\311\025\243os\2023\326\265\255n\227\216kJ\033\205\342\255\307\"\372\325\330d\007\275\\\215\205\\\210\344T\250\274\327\344\373\277\251\253\026\222\205F\357\221U\374\334J{U\245\22384\345\237\r\351Ni1\216sL\363\262z\034z\320\322S\032N\rA$\234T;\362jF\234(\305U\270\271\005H\006\263\246\236\252<\376\365\023\334\344u\252\222\334{\3259.9\353U\245\270\310\353T\'\237\035\352\233\334\373\324\017q\357P\265\307=i>\323\357J.3\336\224\317\357J\267\030\251<\335\343\255\000\234\324\241\362*\325\264\2305<\215\223S[>z\212\270\2407J\263\n\342\264m\326\264\355\272\214\326\244_t\n\271\ng\025\247on\016\riA\036\334V\245\274]+f\312\034\2001Z&\317\010\033\265>5\tV\341\220\014U\270n\t8\305hB\354\325mm\031\306\342j\304V\244`\005\311\255\030,\345`01ZV\272l\214\303=+\251\3224\025\030f\255\033\3134\215p\213X\323[\261~\365\253\245\304\270\303\212\321}7\3149Z\210\332I\017<\323\026\362D\223\031\255;k\307 V\245\265\313`V\235\265\316\354V\265\273\006QW\241L\327\344\233\221\336\230\267&#\307J<\363+\014\325\270\337\013\315;~hv\333\0314o\302\001L2\323ZN\rA$\234TbN\365\024\363\325\031g\252SMT\344\236\253\274\365V[\214\325I\'\311\353U\345\237\031\346\250\\O\305Q{\217z\201\356=\352&\270\246y\376\364\341qR\t\262:\323\204\271\251\242\226\254,\271\342\245V\251\341\'5k&\247\26785z/\275W\342\033\207\025~\331pkV\005\300\006\264\355\323p\315iA\027\002\265m\023\245jC\006{V\235\2548\003\212\327\264P\202\2565\300\333\264Q\024M!\347\245h\333Z\202@\003&\265\355t\227\225r\022\265l\364)N\003t\255\353M\010\340\014f\265-<>\001\031\025\261m\242\306\0241\351V\323J\2107\313\320V\205\274\t\016\006\376*\314\237g\013\352j!g\014\274\224\0305f\013\030S\220\247\025mbU  8\247MhJ\365\006\251\0351C\023\216i\361[\204o\231qR\227\021\236\rY\267\270\031\030\255\375>p\340V\344\007+_\221\254\325\033t\244Q\216je\227\"\236\262R\311&S\024\326\223\346\3051\237\006\2432pj&\223sq\322\242\226]\242\251K=T\226~\265JY\272\3259&\367\252\3177\275V\232l\216\265B[\214\036\265\013O\270u\252\027\023\037Z\240\367\030\250\036\342\242i\351\206|w\247\245\316ju\270\305=f\315M\034\365f9j\314rU\310_\221V\301\315X\26785~\037\275Z\026\353Z\226\312\010\025\247\010\310\002\265\254\343 \014\326\315\2749\002\264\255\340\306+Z\326>+F,(\346\254\t\0168\2536Q4\256\000\031&\272}/\303\362\334\020YH\025\325Xx~8q\270d\326\365\275\204q(;@\037J\273\024Q\2020*\374\014\201\206\027\245[M\304\345F3S\305n\304rO5j;RF\0014\377\000\260\276{\342\257A\246.\320O5im\200_\224T\211\017\265XH=\251\376Fi<\215\2478\244x\003)\310\254\rM\232\335\310\355Ri\222\231\260+\242\265\337nA\355]5\204\276d`\346\277#\267SKR\027\305(zxzql\212Wp\361\002O#\212\204\276H\317Jb\202C\212\215\237h\346\251M.I\252R\313\326\251K/\025Ni\252\234\263{\325Y&\367\252\362M\221Y\367\023sP,\371\004\n\253u.\005e\313>3\315Wi\371\353L3\346\230e\367\247$\243\326\254\3070=\352e\224T\261\3123V\342|\325\310Z\257[\234\221Z\010\271\002\254D0\325\241\000\371\205j\333&Eh\333\2561Z\266\321\356\000\326\325\232e\000\305m\331\247\312+f\010\006\320j\334XJ\271\014[\2715\241\005\223N@Q\232\353\264\035\r\"dv\373\335\353\264\265)\022\200\024U\250\311\' U\310\324\2763\322\255\303\017\265^\202\037j\320\202,v\253\321\303\234U\310\241\305YHw\221\305X\021\355$\017J\231-\317\245M\r\250<\232\227\311\003\2659`\245k~*\027\213\212\301\327-w\200\000\346\233\243\332\030\216H\256\2628\303[\201\214\326\206\224\205x5\371\034[\024\322\324\205\250\335O\rK\276\224\270#\007\247Z\221Q@\246H\341FMg\\M\222j\204\262\342\251\313%R\226J\2454\276\365JY*\254\222\325i&\342\250\\K\357T\376\323\265\272\324WW\005\227\035\253&i\260\314*\263MM3S\014\364\013\216z\325\210\246\317z\260$#\232\236)I5\243o&qW\242j\320\266nEjB\374U\250\2715\243l\271\305k[\257\003\025\245n\207\002\266l\342\371A\255\2738\362+f\316.\005kF\333TU\253X\374\326\006\265\222\324\234\005\344\327S\241i\233c\014\302\272\213H\004`b\265 N\225~\024\034U\370S\245^\206>j\374\021f\264`\213\245]\212\032\260\230^\rh\331\306\010\007\025)\267\006A\352j\332\303\212\210\2349Q\332\244D\305M\260c\2574\2052qH\321*\236zU\033\233!3\223\216\0056\033UG\000\n\350m,\263\020\'\245^\267\264\330\331\257\307\2268\246\356\246\356 \322\356\317zpjB\324y\224\345\271\3320j\275\305\316\341\201Td\223\255T\225\352\224\322pj\214\322U\031\245\252\222IU%\222\252I\'\025B\342^\265\2354\265\013\\ey5B\342O\336Uf\222\230f\246\264\240\321\274c\255X\202aW\225\201^\265,m\216\225~\325\372V\224&\264my\"\265\240N\005]\205qZV\303\245l\331\257J\327\266\217$V\315\224u\267e\0275\265l\241G5iF\367\000V\335\215\267\312\240u5\325\351:Z\340\026\256\216\3325\\\005\351ZP/J\320\201qW\340^\206\257\302\265\243n\235+F\336:\321\202<\342\264\"\213 R\275\271\0075\245a\0032\364\253\266\366\331\230\203\330T\356\233MUu\006S\201R\242\343\212\265\344* -\311\250\223kg&\232\320\356$\347\002\231*\215\230\024\266\226\r#\203\212\337\216?-@\364\253\nk\361\261\372\324E\260i\245\250\r\315855\236\233\276\232\317U\244z\253#\325Yd\305P\236J\2434\225JY:\3259\037\255U\222J\2514\230\315f\334K\326\263\346\222\2534\274\325K\227\306\rUy*&\226\232e\342\225e\367\2530\267\"\264\242`S\255K\033\220j\365\263\363Z\326\307 V\235\261 \212\327\267n\005h\3003\212\324\265^EmZ\250\030\255\233D\316+f\316>EmZ\256\322+C~\000\305h\351\361\377\000\023WS\242[\231\244\007\025\326\302\241\024(\255\033n\325\247\005hCZ\026\353ZP\'J\321\267Z\322\201zU\350\027\014\017j\324\211jW\302\257\326\265\364\300\257\030\035\352\300\214\306\305\217z\257p\314N\026\241TpzU\250\343$\0169\247\313\033(\"\263\335\0369x\316\r]\202\325\345\0035r=;\246kB\013m\200`S\344\214\342\235\022\223\327\275~6\310*\253}\352c5\033\272R\207\244f\246\356\246;Ui^\252\310\325Rg\252\0237Z\2433U\031_\255U\225\352\234\217\326\251\316\365\233q\'Z\316\232LUs\'&\253]?\311U\013\344T,\336\365\0339\241$9\253\260MW\243\232\255C&Mi[\021\305j[>\010\255\213v\334\006+V\334p1ZV\331\342\265\255z\212\334\264\031\255\2535\351[\226\213\310\2554\371\000\255;\010\274\323\270\364\255kX\367\310\024t\025\332i1\010\"_Z\327\201\267\021Zv\307\245i\301Z0v\255Kq\234V\245\272\347\025\247o\037J\321\202>\225~\004\344\n\276\243h\024\256\234\203Z\232a \214V\231(\357\264\236MA4\001\037#\245U\270\275Kc\311\252\315\342DS\362\200\r1u\243q(\036\265\277mn\223F\247nI\253\361Z\355\351Vc\207wj\263\035\276{U\224\262\r\214\3243\333\2428\013_\213\256j\254\234\032\201\2174\240\344Q\232\t\246\023\212\215\2335ZSUdj\2473U\031\233\025Ff&\250\312j\234\255\214\325I\033\031\2527\017\214\326l\357\326\263\347n\265X?5\005\303\374\246\251\227\342\242g\246\026\245W\305X\205\371\253\361t\006\256\300rEi[\036\225\255m\332\266,\373V\325\243\014b\264\340\000\342\265mF1[v}\253v\314p+n\330`\003WP\371\214\000\256\202\3022#\000u\255\2552\337\016+\247\201\370\025\245l\331\305j\333V\244\006\264\255\273V\255\250\351Z\326\300qZ\226\344f\264\355\3008\253\361\2460j\332\034\214S\337\356U\273\'\333Wcm\315\223\326\237;\225\\\226\342\271\335G3\277\313\322\260na\222)\017\\V\357\206,\315\305\302\226\034W\241\333[,(0*h\243%\263\332\255\254\177/\024\221N\"|61R\317v\n\341*\251r\315\223_\214\016*\254\235j\273\234\032D4\247\2554\2654\232\211\232\241\224\345~\225NST\2465JcT\2455Fn\246\251Lz\3259\217\006\263\356_\255fN\375j\204\257P)\033\271\351P\\\034\203T\230\342\242cL\311\245\006\247\211\260kF\007\371j\3342`\326\245\254\235+b\324\347\025\265i\236+b\321\t\255kd#\031\255ka\322\266\254\3061[\266\207\201Z\360\310\002\n\321\323c2>\356\325\323X\340q[\366\200\"\203\336\265-\337&\265m\237\030\255kW\351Zv\355\322\265m\210\342\265mZ\265m\317\002\265-\273V\275\2475\247\022\356\305YX\261R\233r\370\247\306<\231\225kb(\025\227 \323n,\013\201\311\246\246\211\033\016z\326f\255\241l\004\201\305M\341\310E\274\340\032\355\342@\350)\340\005\372S\267\202q\232\215\243\004\361HWh\250%f^\225\370\333,%sTgLf\251Hy\246#sR=F\307\024\302\334TL\330\250]\261U\245\252SU)j\234\325B~\246\251M\315R\230\326e\313u\254\313\203T%<\232\20395\024\247\255S\220\365\250Y\250\355H\016jD5r\007\"\264m\2715\257j\275+b\323\202+r\317\234V\345\242\343\006\265\340\005\200\255Ke\300\025\251j\330\255ki\360@\255k@\362\001\307\025\267f\346 +\243\323A|\032\336\204\343\025\247j\330\305j\332\267J\325\266n\225\251n\375+R\331\361\212\325\266\223\245j\333I\234V\255\254\230\305lZ\311\322\265\355\233v+A0TU\220\301@\252\2238\363\207<\326\225\255\336\330\210\357O7\216{\325\253k\206,\t\253w\361\211\240\007\025\207\033\213{\205\372\327Ykr\004j{\021H\327\031r;T\311\353R\323[\245B\374\214W\343\324\261\202\rf\\\301\214\326d\321|\325\tM\246\225\333\007\006\232\334\212\204\365\246=WsU\345<U9j\244\242\250\314*\224\302\250\315\306k>\341\253.\344\3475\2339\316j\204\246\243\217\357\032\257/\014j\244\207\223P\236\2643`R\006\251#<\325\3109\"\264\355\3060k^\321\272V\275\247\314EnY\016\225\273hzV\345\260\371Eh[\364\253\260\2768\025\257d\002`\267Z\335\264\272\000aG5\263a\013N\343\322\272[\007\020\2463\315j\333\276\356Mj\332\267J\325\267|b\264\355\344\002\264\255\244\311\034\326\265\273\364\255;y\000\305j\333I\322\265-\245\306+f\316L\342\266\255%\305hD\373\273\324\354\347\034T+\031f\311\353V\242\214\212\271\0149\255\013x\000\253\336V\370\210\366\256[RV\216\353\217Z\332\322\357@EG\255\024\303\310qW\023\201\212r\365\241\217\025\013\032\374\201\224sU&\21405\221s\026\326<UFC\326\253\27199\250\322^\306\221\216\r5\271\252\362\n\254\342\253H*\234\302\251\312\265F~+6\341\2536\341\272\326e\301\316k6v\306j\224\247$\323\023\275V\233\2065U\307&\241#\232\206V\371\261H\rO\031\346\257[\363Z\226\243\245k[\016A\255\2331\214V\355\231\351[v\234\342\266\355\016@\255(\360\242\254\331\235\317\223\332\257\245\307\317\201]&\221l\316\001=\353\253\264\333o\036\001\346\256\333\311\226\315lZ\277\002\265\355\037\212\324\205\370\025z\0311\212\321\266\233\2475\257i.qZ\266\362r+N\332^\225\253m\'J\327\264\233i\025\265i.Mj\301&p;\325\324\005\252e\214\251\344U\230\322\256\302\265v!\212\271m\202\307\351Xz\235\240y\230\372R[A\205\r\351Zvm\336\257\243S\325\363\221\357A=j\007nk\362\032QU_\256*\225\312\003\236+6Q\315S\270\0035P\360i\373\203\217qM=*\'\305@\353\221U\245^\265NU\252S\214Vm\317z\313\270=k2\344\365\254\331\332\263\347\346\251IL^\246\253K\313\032\201\206j&^*\261R^\254Cf\322s\332\247\373)\214t\251\340\\\032\322\266$b\265\255\201$V\325\240\350Mm\331\366\255\333#\322\266\255\201\300\305Z2\025\034\324\326\367[T\363Z:o\357e\014zWccrQ\000Z\325\265\235\231\206MlZ\277J\327\266\223\245kZ\312\000\255\010\'\340U\350g\311\025\247k\'CZ\326\222r9\255h%\351Z\226\322`\016kZ\322Pq\315jZ\3167\001[V\262m\301\025\263h\344\220\325\251\004\343 \036\265\243\021W\030\251\204e\017\265X\212\254\207\332)\326\327`;sY\232\205\360W|\367\252\260_\371\273QOZ\335\264\341E\\\r\212T|\266i\345\261\232\201\217&\277#\245J\251\"`\325IW \326e\304eI8\342\263f\3475\\\212\217v\326\251M1\227\212\201\227\025^E\252\262\256+6\344\365\254\273\232\312\271=k.\343<\326l\307\232\243(\346\251\310)\230\300\252\3149\250\212\3224$\256j\005\217\346\344V\265\222\014.j\314\221+d\016\225^8\2005v\005\301\025\253j1\212\330\264\031\002\266\254\307J\333\263\343\025\265n\370\025$\262dTPH|\300\265\323i\253\264\014WId\377\000-k\332?\"\266m\244\340V\255\274\225\241\014\376\365~\t\362\0075\243o.qZ\366\262\342\265me\344V\255\274\331\255Ki\270\353Z\266\222\364\255H\217B+b\302\347v\024\327Ce.\320\005h\306\33785~\033\235\204V\275\264\213:T\245<\266\366\251\0226\234\354^\264\347\323\332\325\t\316I\025\312\370\201\332%R:\232_\017Fd\303\032\353a\371TT\205\350G\371\261R\0318\250\232J\374\232\225*\254\221\3259c\353T\356!\334\246\261\256\342\3300*\213\n\211\305\021\311\374&\245\307\025\023\256j\t\023\203Tn\006\005e\334\212\311\271\357Yw\035Mf\334/Z\316\235z\325\031\205T\220TdqU\234`\232D\214\261\251\214x\\zT\036N[\245[\205v\201R\311 Q\212H\216M]\201A5\247\000\255{1\300\255\233.\010\255\253n\225\243\034\205EJ$\335Kn\300L\t\365\256\237OpTb\267,e\347\006\266\255d\344V\255\274\234\326\244\022\340\016j\3543g\275h[\313\322\265-\245\351Zv\323r9\255ki3\216k^\326N:\326\245\253\216+b\326A\201[\026\257\3235\245\027\312C-l\330\334\226 f\267#\227\0305j\'\311\253\326\323\264,\010\255\350\034\\\302\rO`\0147\004\236\365j\357/\013z\327\'\342K\"\361+\001\300\244\320\223d*+\240F\342\202\364\201\271\315K\277\"\253<\3376\017Z\374\256\222,\325g\202\240\222\337\332\251\315o\301\254;\373|1\342\262\245\217\006\241d\310\250\374\254\034\325\200\231QLd\340\372\325y\227\0035\235p:\326M\317z\313\270\035k2\341z\326t\353Y\363\255P\231*\243\246j6N*\274\211\315>\004\306jO/r\223M\tM$\251\250\367\357j\263\n\326\205\272\363Z\020\036EkZ\234\001[\026\235Em[\034\001W\003qR\243\374\264\330\344&e\002\272}9\360\242\266\255e\303\n\334\263\227\245j\333\315\203Z\020\315\234U\330e\255+yzV\234\022\364\255Kis\216kZ\322~\225\261k6Ei\332\315\310\255\253I\272s[\026\262\342\265\255\244\334\005jZ\276\302\ro[\260\226 \001\346\256[6~S\324U\3458\025r\303S0\037/\031\004\326\374\027J\n\266z\325\271\245V\217#\275b\353\314\242\323\025\235\245\034 \255u\223\212<\312v\372Q%%\304A\243\363\007Q\326\277.\245\202\253\264X\250\035=\252\254\320\326E\375\256\354\326\025\304\005I\315Uh\3526J\221:b\207L\212\247p0\re\334t5\227p\275k:t\353Y\327\tY\263\245g\314\225Fd\346\253\030\262j)\023\002\253\230\367\032\230C\201\2009\247In\321\257\265F\220\344sL\270\217\013\357U\241\214\212\275\nb\257\302\265v\005\371\253Z\333\265kZu\025\255nzU\321\322\237\t\311\"\246\267@.A5\320Y\234\001\212\324\267|b\266\354\344\340V\245\274\225\241\014\225z\t+J\332NEiC\'J\324\265\223\245k\332\266qZ\366\256EjA/J\326\264\233\2475\265iq\310\255\253iq\203Z\320>@\255{\t\366\220+^1\270\206S\315^\214\357L\036\rX\323b\016\344\267j\325\332X\214v\253V\323\231\030!\350+#\304\327\037:\240\246X\035\261\212\276$\342\223\314\245Y}\351\333\375\352A&Q\327<\021_\231\217\017\265Wx2j\026\200\n\251<x\315f\335C\220k\n\372\337\236\225A\341\305B\320\360q\326\201\023*\340\201Q;\024|\036\235\252\235\310\315e\334.sY\363\245gN\225\235:u\254\371\322\250M\035P\232:\203\313\250%\210\365\246\307\0179\251\241\205K\023\336\246h21P=\261AUe\2148\301\250\243\207\025r\030\252\344i\264U\253u\311\255;u#\025\255j1Z\220qW\223\221NE\303\324\355\230\3105\263\247\313\225\034\326\254\r\322\266m\033\345\255+y9\025\243\034\230\305]\267\222\264\355\345\300\253\360M\222+Z\326^\225\265e.1\232\331\212PT\021\326\255\3036\010\346\265\255&\367\255\233I\272V\335\254\374\n\333\261\234\025\000\365\2558\'\001\206\rm\332O\225\034\326\224RdU\333V\332\331\255\024\227\006\255\304\341F\356\365\313\352\367\006\343R\306x\006\257Z\266\024U\235\364\206JA%<K\232\2229:\212\374\336|\265Wu\371\275\2527@\001\346\252\274j\315\315Q\271\200\020p8\254[\273B\306\250\315`q\300\252\302\324\251\344Sd\212\252\\\301\225\'\270\254\311\324\342\263\346\\\325\031\323\203Y\323\245P\232:\317\236*\243<UFh\252\273EP\264{\210\030\241\342 `T\221E\264T\255\205\025Zg\315Vhs\223\212`\217\025f\024\253\033\t\305\\\264\217\025\247\002\364\255+q\214V\234\0035z!Sm\357N\037\274\030\255]>2\2522kf\014\n\322\266~kN\335\273\325\330\237\232\320\267j\320\211\372sW\355\344\306+Z\326P1Z\366\222d\212\327\206l(\346\256\305?\"\265\255%\3169\255\233YzV\315\244\335+^\326_z\327\266\227\245j\332\336\210\310\004\361[\026\267\"N\207\"\264!\234\2560x\253\320\334n\031\315Y\232\360G\003s\316+\231\205\374\333\246s\3175\261\013\340T\276e4\311G\231J$\305K\034\265\371\326\310j\027CU\344CU\244J\255*\022*\214\260\363UZ=\244\344f\252O\021c\234UG\206\252\334E\301\342\261\356#\344\214Vd\311\203U&\217\212\317\236:\2414}j\224\321V|\361\342\251I\026j\007\213\216\225\032\301\311\342\217 \263t\247\3718\250\245\214\232\256\320\0269\305K\035\266\374qN:\177\034SE\267\226zT\321\245[\2011Z\020\247J\275\002\364\255\030\001\342\264a\253\000qL\013\265\301\025\261c\312\212\324\204\326\205\263d\326\235\273U\270\233\232\275\023\220*\314S\020j\375\274\347\212\326\265\237$s[v3q\311\342\264\343\270\316\000\351W\355\246\311\025\257i.1[\026\223t\346\266-&\351[6\222\364\255{yx\034\324\302B\356\006q]\006\234\306(\302\326\264Rg\025ie*8\254\333\355BS\362g\203RY\r\252+I$\300\247y\224y\224y\224\242J\2229pk\363\366D\305@\351\355U\335*\274\211U\244O\312\252<|\221\212\255,UVH\252\244\261\342\263\256W\322\261\356\301S\300\315e\334r\346\253\310\231\025Jx\252\214\321U\031\342\306k>X\267\032\255,\030\355UL98\247\233m\213\234SV\037jSoQ\233\\\236\2245\237\035)c\264\301\351W\"\264\335\332\222]3\'\245Vk#\037j|\021\035\325\241\024X\253\221&*\374\002\257\304\274T\340`PFMhX\223\200+Z\002I\255\013~;V\204\007\200j\334M\310\253\321\277\025b#\3175z\'\002\264\255\037\221Z\366\367\033@\253\366\363\022kN\326r\254+j\322\\\343\232\327\264\224\006\031\351[PH\027\005O\025\257i7Nkb\332P@\253\366k\346\\(=3]\034cd\270\355\212\2215\010\343l\026\253\261\337\251\\\346\250K/\235>{f\257@\330\025dKK\346\322\211)|\312z\275H\217\315|*\366\204\214\342\252KnA5Y\241\347\245U\236-\247\030\252\217\021\367\252\323G\216j\254\242\252H*\224\303\212\315\271\\\346\263\314;\211&\260\356Sl\314=\3523\037\025ZX\252\234\220Vu\314]\252\253[`t\252\263C\236)\022\310(\311\034\323&\267\364\024\301o\2008\243\354\304\362h\362=\251~\317\305\t\006\343\214U\230\255H \212\274-\303\307\323\221P\275\206\361\322\253\235<\306r\005L\220z\212\261\0345a# \325\310\201\305N\001=\252x\241\'\234U\373U\n~\225\243l9\315i@\277(\253q\364\2531\034U\310\317\312\rX\213$\361W-\301&\264\341\220 \000U\310&\311\353Z\226\262\364\255X[v\017z\323\264\270\306+b\332|\343\232\331\265\237\2475\263g?Nkj\326~\0075\261\246\334\004\233&\272kf\022/\231\236\265\231\252@Q\303\251\371I\251l\331\231\002\2268\253\361\240Z\260\217\212\224KO\022S\204\224\360\371\247\253\324\210\365\3614\322\000\010\252.\334\363PH\340t\252\222?Z\253!\315S\225Kt\252\223F@\355T\345F\3015J@Xt\254\371\34289\030\252,0\rb^\307\376\220N:\324~VEC$URX\275\252\233\332\344\344\212\253q\026\321\322\240\216\317vX\212l\220\234\340\n\215\355\360\207\216M4[\361\323\232\r\266i\277e\305/\331\317\245*\333`\364\253\t\036*D\0305aP0\024\255\000\364\250\214\003=*\3046\252EN\266\2438\251\343\267QVc\205}*\300\213<\001C\017(\200*\375\2708\031\255H\324\355\002\247F\355V\023\214U\310\233\214U\330_5r\'\355VQ\200\357Va\223\006\265\254g\000\363[\020J\0161ZV\354\t\255Kc\216\225\253k)\030\255\213I\372V\325\254\335+R\322\343\0149\256\256\306\340\213r=\252+\373\201\344*\236\244\321e.\334\003ZK.E=e\251\004\264\365|\324\201\300\247\253\324\213%J\217_\023\3149&\251\312\300f\251\313(\025JI\200&\253Ir*\264\267 \n\243-\316MW{\232\200\270c\305E4[\201\342\263%\207\004\212\316\275\201H\317qT\302\202*)#\252r\200\rA \310\252R\303\274\364\251\222\323\021\364\250\236\316\241k|\016\224\337\263dt\243\354\270\245[`h6\234\322}\227\232C\001SJ\261{U\210\343\305K\345qLhFx\251\"\\T\313R*\232\232!\203W\"\003\255D\356\036o\245\\\201\271\025\246\222t\315L\215\316j\324m\322\254F\334\325\250_\232\273\021\343uL\222d\325\350[\201W\255\333\007\255lZI\322\265\255\245\344V\255\264\275+V\335\263\216kV\325\272V\275\254\244`V\2242\343\006\266\364\335Q\261\260\236*\335\305\307\231\036\017^\324\353yH\357Z\021Np9\251\326Z\225d\367\251D\225 \222\236$\247\254\231\251\322J\370\276\341\272\326e\304\230\315f\334I\311\254\351\24695RI\210\252\322LMV\222J\204\266ic\034\324\356\233\227\212\247=\271*Me\334A\273\"\250\313hb \343\203Lk}\313Y\363\332\260n\225\t\200\221\322\221m\366\366\247\210\370\351P\313\027\265W\222\023\212E\204\342\232\326\364\236A\002\232\024\255<a\2527#8\3055W\236j\322\"\342\236TP\020\032@\270lS\302\324\250*U\025a8Z\2451+q\327\212\322\265\354kN\"\031y\353S\240\342\255G\322\254G\332\255\305\305YS\232\261\037j\267\013\342\257\300\365\247o&\010\255[i9\025\253m/J\326\265\227\221[6\222\364\255X$\351W\343\233\013V\255f\"E\364\315l\313.\000\036\325,\022\344U\330\245\253Q\313S\244\202\245\022S\326J\220IR,\2252?5\361\235\323u\254\273\203\326\262\356\033\255g\314\335j\234\215U\235\252&\031\246\205\247\257Z\263\030\342\234\326\371Rk\032\3460\256ER\272o\335\355\305E\034\213\264\206\\c\275V\221\222B@\250\315\270\013\234Tm\006E3\310\3155\255\363\332\242kL\366\246\275\266\301P\264x\2460\342\253\310\330\250K\212ap*30\024\013\275\275\352T\275\315K\035\330&\247F\337\315L\253V\026\335\230p*U\260\227\322\236\266\314\235H\250\'\265-\310\2536\237\"\341\252\354O\310\305_\210qV\243\006\254\240\253H8\251\307\0252IV\"j\275\003\364\255;w\340V\235\273\326\255\264\235+Z\326N\225\257i\'J\330\265}\300V\214c U\270\001R\017\275_\363\2677\322\254\333\311\305^\212J\264\222T\351%L\262T\212\365\"\275J\257S#\327\3077#\255e\334\360\re\\V|\335MS\222\240aM\013N\021\346\205\217\346\253\360\333\022\0056\372e\202-\253\367\215aK\226$\325+\210\213\236\005Ux\335F1P\254$\276J\325\203\025E\"b\230\253\3159\242\3435\021Zk\240u\367\252\023\251SUY\260*\244\317\326\252<\270\250$\270\305Vy\311\246\371\204\232\236-\355\320\032\320\202\322f\306\024\326\224\026S(\031C\217\245hAc#\014\3545a`\221;\032\2272\250\345MR\270\224\202wg5V;\354>\030\344U\320\302A\225\306*\324\033\200\351Zv\255\225\031\253\250*\312U\224#\025(\351NNO\025f/z\271\t\255\033w\306+R\331\262+J\335\361\216kZ\326N\225\257j\371\305lY\311\203Z\366\357\221Z\266\252\036\022s\323\232\256\327b\'#5=\265\372\221\214\326\235\275\300lsW\242\222\255\243dT\201\252Uj\221^\246V\251U\253\344Y\343\316k*\356<f\262.\027\255f\316\265Q\326\241e\240-;\245X\265\203\3149=\005M4\273F\026\263g\206I\333-H\272y=\251[O_Ja\323\224\216\202\253M`\024\036*\204\220\355\'\322\252\310\273\217\025\013.\323R\006\004S$\003<T8 \373T7\021\006\031\254\331\223\031\025\237p\275j\204\252M2;7\231\260\007Z\277\017\206\346\223\037)\253\366\376\021\225\230|\204\217\245t\272g\202\001\332\305@\365\315t)\341x\"\213\260j\226=\036\335T\002\006j\177\260B\006\024\n\212M&<\356\030\315 \322\223\030=\353\033U\320\202\222Pd\032\347.tgF-\264\212[[IC\200\001\255\350t\346x\200\350{\324\360\3324x\006\257\307\027\035*\312E\305\007\217\245*\314\007\031\251\222Q\330\325\210\344\315^\200\212\320\204\214\n\275n\370\255KY2qZ\226\317\203Z\366\222d\212\330\265~\230\255[y3\212\325\262\230) \236\242\252\313n\3573c\246jX\354\244Nz\217j\275k\346!\343\221Zv\363\347\031\353Z0\311\232\260\016i\352\3252\265J\246\245S_*\315\027\006\262\257!\340\361X\2671\3435\227:rj\233\246\rB\313M#\024\306\342\264\254X\030\033\007\232\226;_0\232\220\331\205\355H\326\370\035*\264\221m\250\030\340\323^!\"\326u\325\260\301\343\212\3111a\315V\234\000MT3a\251\333\367P*9y\025Jh\263\232\245%\243Hp\005I\006\201$\25420+\250\322< \2743\014WW\007\207a\211\027\"\254\255\234p\214\005\006\206m\2358\250\213\223\336\241vaQ\026`z\322y\344w\245\027\'\326\237\346\253}\352\253wo\024\312x\002\251[\332\256\376\235+EaU\031\357H\341s\322\237\030\305N\203 \325Y\246Q\221Y\222\\\235\334U\233{\254\220\ri\301( V\215\264\203\"\264\340l\325\310\233\025\241l\374\212\324\267\223\245kZI\310\255\233Y1\212\325\267\223\245i@\371\253\321\r\3075z\036*\307\226>\362\360i\254\177\210p\302\254\332\334g\275iD\331\002\246\025\"\366\251\224\324\252k\346\033\210\375\2532\3610\246\260\356\243\353YS\307\212\241*\363P2\324ei\215\021=\252{V1\214z\326\326\2367)\315K\"\222p\005G\3441<\364\252\3271m\004\342\250\030I4\215\031Ze\314@\302Ms\376Qi\210\3056\366\304\210\211\002\271\367]\256jt\\\323\366\340Tn3O\202\301\356O\312+sM\360\3039\037-t6\372\0046\340o_\232\256\254i\020\300\034\nG\234t\315@\363\016\325]\230\261\246\347\024\307l\324L\325\033T,\330\246\371\207=i\255&z\232\026P\247\201R}\243=\371\245\017\232\235\033\245N\207\000\325\013\370\\\002\313\322\262\262A\346\245\216J\320\264\234\214\003\322\266-\311 \032\326\266c\216j\344rsW\255\236\265m\232\265m_\245lZ\311\220=k^\331\376QZ6\357Z0=i[\277J\272\203#\"\2334$\374\313\326\241\001\243;\207\036\265\245gp\010\034\326\214GuM\267\035\351\301\200\251\021\301\353_5\3163Y\227`\021X\267j0k\032\351z\326|\213\223Q\024\311\251a\2632\036G\025pi\343\035)\321i;\333\245j\333\351\315\n\205\333I$!\r\002 \027&\250N\252O5Y\325\024\034\016j\234\261\226\'\024\010\267&\rVm>8\311lsT\357\343\002\006\372W\0374d\314q\353S\305\021\305\022\220\253P\306\246I\000\002\273\017\017\350\316\352\245\224\201]:[\375\235p\000\250%~\271\353U\245sP\026\037\215F\306\230^\243g\367\250]\275\352\"\324\205\35269\250\230\342\230M0\265>3\223S\241\251\321\252t|\n\227*\351\202:\326E\375\250F\312\212\246\251W-\301\310\255\253\027e\300\307\025\261\003\374\242\254)9\253\326\315\322\265\255\237\030\255[W\351Z\366\255\322\265m\344\351Zp>\000\255\033w\351ZV\357\322\264\255\3335m:\322M\010+\221TQ\374\231=\253Z\326\340\260\030\253D\263z\323\323=\307\025*\360+\347\031\216Ee\335\036\265\217w\336\262.W9\252\016\274\323\355\355L\215\322\265a\263+\2161W`\261.y\025\257i\247\242\014\220)oBE\031 V3\2171\252;\203\204\300\254\331\006j\264\253Q\343?Zr\216*)\243\334\rcjh\3026\035\253\231\223lls\326\241k\200:\032#\205\356[\200Mt:.\207\231\025\230\034\327on\213m\030\003\265Csq\357Td\220\363P\261\317Z\215\210\025\023\265B\362T\017%D\322TM\'\2754\311\212cKQ\2313H[4\231\247\241\301\251\321\261\326\245W\251\003\361RG-GpC\325U\210n\253q\"\016\225\241m(N1ZPO\307\265YY7\021W\255\337\245jZ\266\354V\265\261\306+Z\331\372V\255\273\326\235\273\361Z6\355Z05h\333\311\214V\204o\220*br\275k:\352=\255\237Z}\225\301F\332kb\031\262\005XYs\326\200y\342\276s\235\260\246\262\256[\255e\\\016\246\263g\\\346\252y\005\233\245mi\366\003\000\342\264\322\327\'\245Z\206\337\025)8\004\016\225\237|\373\360\243\265T\021\361U\356\027\"\250\272\346\2420\356\250\332\r\204\322\004\004{\3243.+#T\000\306k\224\276E\004\200r}\252\265\275\223H\343#\212\3514\353\017,.\027\223]=\224Ko\020 sR<\205\252\ty\252\355\234\324r\022\006*\264\217\212\256\362\324/)\250\036J\211\244\246\027\250\313\323K\323\014\224\273\351C\373\323\204\225\"\311R\031\302\323\222l\367\251VNhg\007\2751N[\336\254\307\"\216\265n\t\320\340\003Z\020\363W\241Z\273\017\030\255;g\306+Z\325\267b\265\355N1Z\226\347\245j[\266p+J\003\322\264!n\225~\026\255\010\037\"\254)\315G2eH5Er\262\326\275\261\312\214\032\266\244\216\265\"\032\371\302s\301\254\333\203\220k6z\244\351\223S\331Yy\2568\256\212\336\314G\030\030\251\374\2208\002\207]\213PH\333S\336\250H\274\346\243#\212\241t\3308\252\330\335K\260(\250\244\301\025\tQ\237z\255p\007#5\211{\013\3341Px\252gD\003\255hZ\350\361\306\025\261\315Y\220\210O\000\017AR\307;Hq\333\025d\374\251\315V\232u\214d\326e\306\254\221\223\363\014\n\316\223\304\n[\007\245!\326\240=M!\277\216O\272\302\232f\r\322\241i\306z\324/8\250Z\344z\323\r\310\354j)o\002UI5uN\207\232\256\332\301=)\351\2531\355R\215I\332\256AvH\344\323\332v~\202\245\212VQSy\315\201\315=f\317\006\255\301\206<\324\330\031\342\254E\016pz\032\277n\356\270\007\245jC\222\001\253\261t\253\366\335\253^\320\364\255{bx\255H\017J\322\266n\225\247nzV\204F\257@\325~\006\306*\342\232s.\345\254\373\210\214O\270t\253Vs\340\212\323G\334*d\036\265\363}\301\305f\\7Z\317\224\346\231\034%\334\014V\376\237c\345\200kGf\005\004\004\\\367\252\362\020G\277z\2473rMU~\336\265^i6\016\274\326m\303s\223U\314\240rM1\256\206p*7\270\035\315U\232\375P\360y\254\255CS\010\244\203\363UK]QI\311<\325\365\270\363\263\216je\225\207\025^pI\311\244\216\343\312\374*\246\241\342O$\220\017J\347\257\274G,\331\001\270\254\211oe\224\234\223P\231\330u5\033\\\340\3654.\242S\241\251\023[x\377\000\213\212\265\036\271\014\203\34685f;\330\245\034=2b\243\220sT\246\274*>QY\3277\256\375\352\231vcS\301\0331\034V\254\026\300\n\260\226\313\234\325\250\343\002\245\010=jQ\267\035iZt^3B\3123\307J\267\014\335\006j\354n\030\325\350z\n\275\026\033\002\265-\027\034v\253\351\000+\221V\255\306\rkZ\216\005kZ\366\255K~\242\264`\030\255+sZ\021\032\275\r^\205\252\354G T\353\315G<a\224\212\251\010\301\372V\255\273dU\265j\371\256\345\261\232\312\2709\252\333\t5\241\247Y\231$\034WK\035\247\226\203\216h1\001\311\351U\346#\360\252S8\002\251H\374\373UYX\3475VE,rj\225\331P\017=+\036\342\343\223\315R\226\353oz\241>\240\300\234\032\241q\177&8\254\273\251\244\233$\223Ie\2748\004\344WQf0\202\256p*)\230\216\365\223}}\034\010\334\363\\\275\345\301\236BEV\021\026\241\202\245S\271\230\n\243$\365]\356}\352\007\271\367\250\374\362{\323\243\277\222#\225cV\223]\224\0141\310\251\006\260\033\255/\333c~\325$R\302O<U\250\246\213w\rW\242\221H\030j\262\216\001\306i\306\351\023\253\n\211\265\020~\355 \272$rh\022\022j\324.M^\210\222\271\025v\006<V\225\273\234V\215\277Q[6\377\000(\007\034V\234+\2712*X\206\032\264\355\273V\275\267j\324\203\214V\205\273V\214\rZ0\034\325\370M]\213\030\253p\234U\244\034\323\335r\265\234N\311H\253\2609\035j\364m\232\371\256\343\232\250\320\026=*{}1\244#\216+\241\323\354\026\025\034U\346P\001\252\023\311\270\373\016\325\237pI5M\321\211\252\322\214\036j\007#\025Rf\302\222O5\203\250]\374\304\003X\323\315\326\250M!&\2537Zr\302\262\256\332\211\264\302\t\307JrXy|\343\221Wa\224\307\301\025?\333A\035*\031\256\013\247\035k\n\366\302Y\234\223\232\244t\326S\3104\311\2410\257\002\261oge\'\255e\313+1\315Vy\rWw5\037-OX\211\247\213fn\324}\225\251\206\022\0174\365\217\336\236\261\267\255J\233\207CV\342\232A\336\254\013\211\010\353H\031\330\362jTr8\251\343rOZ\267\020\315[\211qWa\223a\307cW\341 \342\264\255FqZ\266\353\214V\315\250\312\n\320\204\341x\251\243\353\232\320\203\265j[61Z\326\315\232\323\200\016*\3645\241n\330\255\030Nj\354&\256GV\243j\235y\252\263[\203&EJ\220\235\276\3654LT\340\327\317\r\021cWmt\354\000H\346\264\255\354\200\355W\026 \213\305W\270\311\310\007\212\246m\313\223\330Ui\242D8\316MQ\230\021\223\332\263\347l\236\225VG\306I\254-N\377\000\222\250k\ny\t\315R\220\222j\273\255B\313MV\330}\350\222\377\000`\347\232\254\372\244\204\035\243\212\245.\255(n\365$\032\204\222\2209\2558e\332\240\267Z\223\355\nN1Jv\260\344U+\273_1\t\025\203w\242\3110\'mb\335\351o\027\360\232\240\326\016\307\030\250\333L|\375\332\016\234\361\214\221\212ER\247\356\322\264\205GJ\214\316GZ]\352\302\230H\024\3372\245\215\271\253\220\220z\324\374b\216\224\340y\251c\253\2216*\354OWa\371\306*\324\005\24385\261f\331\305k[\267J\330\263#\025\245\007\245ZX\270\253P\014\032\322\267\353Zv\315\322\265m\333\245h@j\374=\252\374\007\002\257B\335*\374G\"\247S\212\231\036\234G9\253(\240\2504\331\"=@\346\274\036\326\333{\214\212\330\212\3338\030\253in\024Se\001G5Q\223~Y\270QY:\226\244\261\215\221\234V\024\327\344\022sY\363_\261<\232\214\335\356\035k7P\2758*\207\353Xs\222I\252\222.j\263\216j\027\025\t\031\353PM P@\034\326|\304\261\247\333G\271\271\351Vd\323\222A\220\274\323\241\262\362\207\000T\305\002\236H\2464\241N\027\006\240\222Y\273SE\323\001\206\246KxB\220\005g\\\\+\003\271j\213I\026N\000\315\"\250f\366\247K\022\025\371\261Y\323\311\014@\2163YS\302\327\014v\036=\252?\354\227\352^\221\264\367N\206\233\3667c\212\232-=\217z\266-\243\205>c\315F\030\026\300\251\325}\352P\234u\247\244Y\351V#\204\372U\230\323\025n(\201\253p\256\323\232\321\200\207\306kN\325\024\034\326\275\263/\025\247l\000#\006\265!5v\003V\320d\364\253\366\353\322\264 \004V\225\253t\2558{U\370M_\210\364\253\220\265_\205\270\2539\371i\321I\223V\243!\2705f<\247N\2253\200\353\307Z\361\013Kb\244q[1A\265A\305#\214U;\211\025\017=+\013V\325\225Wb\034W1qu\274\236j\205\304\370\357T\214\273\3155\330\343\212\2455R\220UY*\263\212\201\361U\344\3438\252\0236I\252\256Njkm\331\315Y{\262\0063\305C%\353c\013\305A\346\263\236X\323^b\243\216*\023s&xjc\274\255\357U\244i\333\216j\t\022Le\316\005T\373DH\3075Z}c\3138E\342\263nu\211\\\3655\237%\334\222\036I\251\355\256\345A\200j\332J\355\311&\246RMH\033\002\233\346\260<\nO*I\2179\251\343\261+\311\251\226\n\221a\366\251\222\022\2475:\236zU\230\3005j<\016\225a\006j\324C\030\255\033w\351ZP?J\325\265\227\245j\333\311\232\322\267l\342\264\"\347\025\241\006\016+B%\300\253\220\034\032\324\267n\225~\036\325z\023\322\256\3048\253\260\232\262\\c\002\230\247\232\265\024\244b\257\305\'\034\324\353\310\3105\377\331"
+byte_png: "\211PNG\r\n\032\n\000\000\000\rIHDR\000\000\002\000\000\000\002\000\010\000\000\000\000\321\023\213&\000\000\001\212IDATx^\355\3351\016\3020\014\005\320*\367\2772\025\003\023FA@U\322\374\2747z\214\322V\262]{\333\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\200t\255\006\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000`\270\275\006\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\230\314^\003\000\000\000\000\000\000\000\000\000\000\000\234\257\325\000\000\000\000\000\000\027rh$\207\0240\000\000\000\000\000\314AN\037\000\000R\035j\377\001\000\000\000\000\000\000\000\000\000\000x\245M\031\000\000\000\000\000\000 \221j0\000\344\361}\007\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\200\261\354\026\004\000\000\000\000\000\000\000\000\256B?\023\360\244\325\000\000\000\000\000\000\000\000\314K\031\234\0077\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000`$\323\240`U6f\002\000\000\000\000\000\000\000\000\000\000\000\000\000\300\347\374\237\013\014\324{\005\031\034\322\321;\260P\267\032\2005,\366\244\003\000\300\202$>\000\000\000\022\250\351\000\000\360\206b\000\000\000\000\304S-\002\000\000\000\000H%\003\374%\007\006\000\000\000\000\000\000\000\000\000\000\000\000\000\000\220\315&\026~b \001\000\000\000\000\000\000\000\000\000\000\000\374\335\035/,\023\360\002\312$\322\000\000\000\000IEND\256B`\202"
diff --git a/core/res/geoid_height_map_assets/tile-5.textpb b/core/res/geoid_height_map_assets/tile-5.textpb
index ac2a9ba..0e43c84 100644
--- a/core/res/geoid_height_map_assets/tile-5.textpb
+++ b/core/res/geoid_height_map_assets/tile-5.textpb
@@ -1,3 +1,3 @@
 tile_key: "5"
-byte_jpeg: "\377\330\377\340\000\020JFIF\000\001\002\000\000\001\000\001\000\000\377\333\000C\000\004\003\003\003\003\002\004\003\003\003\004\004\004\004\005\t\006\005\005\005\005\013\010\010\007\t\r\014\016\016\r\014\r\r\017\020\025\022\017\020\024\020\r\r\022\031\022\024\026\026\027\030\027\016\022\032\034\032\027\033\025\027\027\027\377\300\000\013\010\002\000\002\000\001\001\021\000\377\304\000\037\000\000\001\005\001\001\001\001\001\001\000\000\000\000\000\000\000\000\001\002\003\004\005\006\007\010\t\n\013\377\304\000\265\020\000\002\001\003\003\002\004\003\005\005\004\004\000\000\001}\001\002\003\000\004\021\005\022!1A\006\023Qa\007\"q\0242\201\221\241\010#B\261\301\025R\321\360$3br\202\t\n\026\027\030\031\032%&\'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz\203\204\205\206\207\210\211\212\222\223\224\225\226\227\230\231\232\242\243\244\245\246\247\250\251\252\262\263\264\265\266\267\270\271\272\302\303\304\305\306\307\310\311\312\322\323\324\325\326\327\330\331\332\341\342\343\344\345\346\347\350\351\352\361\362\363\364\365\366\367\370\371\372\377\332\000\010\001\001\000\000?\000\355\240^@\305^\013\307J\216D\364\254\353\333c$$\250\344W){\033\243\220Ee\274\233N\r@\347q\247\305\037\034\212{E\362\325)\243\366\252n\265\003.j\'LT,\202\253\3128\252\216\224\325\213-Ne\3300*\027\250\271\3154\266\005B\314sQ\371\204S\322\343\007\232\237\355q\221\214b\241\231cu\'uQ\026\310\344\232\206k4\301\305f\313m\206\351Qy\030=*T\213\007\245[\2163\351V\0211\332\234\"\311\351R,>\324\343\032\251\353\212P\201\272\232pD\035\251\331_JQ\317AOU\377\000f\236\0015*)\253(*\314k\236\325j5\301\253\321-^\205j\374+\322\264!\216\257\305\035\\\215qV\343\025f5\346\257B\231\253\221\245[\212>j\322\200)\341\373\nx\315J\242\247\215FsS\203\307\0252\034W\017\034D6E[\t\224\2462\014sPI\030\333\310\256wW\262\004\026Q\\\205\344L\214qU\"$\310\001\255\025N\001\245#\212\247:\216j\204\213\315@W\006\241p*\273\325i\0275\003-4\014Tl3P\277&\230W\212\214\255F\313P:\324{M;i\244*\304w\244\021\277jw\222q\363S\r\242\021\234\212\257%\262\251\342\230\260\200zU\210\340\'\265YX\000\\\232v\305Q\3154\221\351Q\225\014zT\212\240p)\342<\365\247yB\236\261\014p)\333\0058%J\213S\242\325\230\326\255\306\271\355W\242J\277\014}+B\030\353F\004\253\261\216j\324kV\243Z\271\022V\204)\305\\D\346\256G\036\0274\214\010\247 \251S\255L\271&\247\034\n\2259\002\255\302\231<\327\036\251\206\351V\226!\266\242\222,s\212\257\"\022\207\025\221y\021\332w\n\3455\033#\274\2208\254\'\210\3077N\365z\026\312\ns\217J\2470\311\252\217\037z\255\"sU\234T\016\271\250]8\250\031j&\025\036\332\214\307\363S]qQ\025\2462\324f<\320!\366\245\362}\251\2736\236E5\363\216\006*\003\274\232M\222\021\306iD\016\335jT\265\\\344\324\3425Q\300\244a\336\240`\305\263\212M\2714\241\005H\261\343\232\220\001N\243\236\324\000jE\0254jI\253(\225f4\253q%^\2059\351Z0\250\035\252\374J8\253\360\255[E\253Q\255\\\211j\354I\322\257\302\265v5\351V\321N9\250\237\031\241jd\0315a\027\002\244\0315j\024\030\315[\207\357\375:W*c\300\251P|\234\320W#\221UZ<?\326\251_@\032\"}+\005\355\204\214A\025\316_\332\005\231\270\252\211\031S\212{\003\212\253\"T\016\274UY\024sU$Z\256\302\243+\232\201\322\242)\3154\307\3050\307Q\274f\242)M)\232O/\232p@\0055\360\005@\334\3230\017\024\2061\236\005H\213\330\001R\010\217\\T\236_\034\212aJ\210\241\'\035\0055\220\0163L\010=i\330^\324\240\032x\\v\245\333N\013\223O\tN\013S\306\225m\022\254\306\236\325n%\253\261/J\275\020\351W\341Z\277\nU\324J\265\032\325\310\226\256\304\265v!\322\256\305\305L\317\204\305A\324\346\244QVa\025aG\313OE\346\254\246z\n\265\n\363\\\361\217\'\2458G\201HP\212\202H\362sT\356\223\367f\261\204_\276<u\254mV\334,\205\200\254GQ\232\215\252\031\007\025ZJ\251\"\325gC\232\205\243\250\3323\351P\272T,\2304\004\310\244)Q\264y\355Q\230\275\251\246/j\214\307\212c`T.\t\250J\232@\2252(\034b\244\300\035)G\245;\006\220\257\025\023c\322\241h\363\336\223\312\367\024\345E\247\200;\nx\217\"\227\313\301\245\331N\333\3058\016j\304kV\343\\\325\250\322\255F\265r%\253\261/J\321\201+F\024\342\256F\265e\026\255D\265v!Wb^3VPT\233{SJm?Zz\212\23585aNjd\034\325\250\327\240\253\210\002\212\303\331\355F\314S\031j\007\025Ru\005H\"\250\033|\022\330\254\035Wo\314;\3277\"\220\306\240aQ\225\315A\"\014\325y\020UwQ\232f\300i\215\t\003\245@\361Ug\212\231\267\024\205)\n\037J\214\2450\256;TN\265\003\'5\031Z\214\257=)6\201Hr)\273\232\234\254jEcR\003\3051\2004\302\202\233\345\344\373S\304j=\351\352\200\366\251Dy\024\246>\370\244\300\317J@\311\273m</5b%\342\255\306\225i\005[\215j\344IWaNkJ\004\351Z1\257\002\255F\265f5\346\255\306\265n1W\020|\242\254/\025*\323\312\345y\246\250\346\246QS%Z\211sWbL\014\221K,\253\032\034\232\317+L\306\005W\235\302)\365\254\311.\333uBf2\260\024\267\001\226\330\221\326\271{\341\271\215c\313\027=*\263EQ:`UY*\254\202\253\272\324}\rI\031\007\345=\r6Hy\252\317\026:\212\201\243\246\004\244)L)\355Ld\250\032>j\027Z\201\226\243+M\"\215\200\323J{P\023\024\365\000\324\2332\265\023)\007\212L\032x_Zz\306\rH\020/z^\005!q\332\232y\246\264Y\0359\251a\004\214\036\325n5\307j\267\022\325\264^j\324IW\241J\275\nsZ0\'J\277\032\364\253q\255Z\215*\314kV\321p*\312t\251\226\246_j{p\264\325\353S(\2531\246E\\\213\n*Y.c\212<\2223XW\332\226\342@<V\231\036\325\023\234\n\312\274s\222+2CE\270\335\'\025r\347\002\034\037J\347/\"\033\216\005eK\027=*\253\246*\244\313\305g\312\016j\006Z\217f{SZ\016*\r\245Z\254(\336\230\357Q\311\027j\254\361\032\204\246\r\0052*&Z\215\205B\353P:\324\014\234\324e)<\261\232_.\223\313\244)J\261\340\346\236\334t\250\233\336\220\001N\033E(qA\220b\242.I\342\234\240\232\231\022\244\333\315.\3148\"\255\304\271\253\221\247J\267\032U\270\222\257\302\235*\364)\322\264a\\\n\273\032\325\270\326\255F\265f1\317J\235z\324\350je\353V\242^3H\344g\024(\253\021.\346\0259\221cS\236*\244\372\232\247\nk6\343Rg\007-Tw\264\357\355]\211\342\241\224qY\027c\255g\312>Z\257o)I\352\335\314\341\227\255eNCf\263\245A\232\2472b\250L\274\032\317tl\364\250\2323Q\355\3074\326\344qQ\030\211\355RD\2305+\304\010\315V\222,\366\252\357\027\245B\321\221Q\262\032\210\247\034\324L\225\003\245BR\230V\233\266\223\024\204RS]\261\322\242,M\031\244-\351M>\244\322\026 qM\3114\365\031\251\220T\3523R\201\3058\251$\n\267\014d?>\225z4\342\255F\265n%\253\320\255_\205zU\370\226\256D1V\323\000T\351\326\254\307\232\234T\3103V\021y\253 \355J\213\253T\310\274\325\204;W\245W\271Y$S\316\005a]\220\231\033\263T\025\232Y1\236+N\004\n\242\273\006\002\240\227\001I\254[\2627qY\316x\"\251\225\"\\\321+\035\330\252\3563U\2359\252\263G\221Y\363FA\351Ud@*\006@{T\r\037\265 \200\372T\202\334c\2455\241\332sJ\027\326\232\360\2022\005Vx}\252\273\307U\3351P\262\324N\265]\327\232\214\255D\311Q\225\246\221L\"\223\024\205sQ\225\3054\216iBf\230\350s\3050\202(\003\232\231\026\245\013R\n\225~f\002\256,9\301\035\252\314c\236G5n%\342\255F\231\253\221\245\\\211j\354C\245^\212\255\307V\223\232\263\032\325\270\326\245\003\232\225\0075j0:\323\235\2060)\261\365\253\np\000\251\227\2474\311\220\272\234\032\346\265\004\362\344`j\255\240\033\363Z\212p+\252\226P\243\232\316\270\271b0+6f,MRpsM\332B\356\305VpY\363M)Q\264~\325ZD\346\252K\016{UI-s\332\252\275\271\007\2450[\367\305?\310\366\245\362\206:TRG\236\325Y\243*iW8\344S^ FES\226#\232\252\351\353P:b\240t\250Y*\026^j2\265\033/5\031ZiJo\227AJ\215\224\322,y\352*Q\027\035)\031\000\250\314c\322\233\345\217Jr\255N\023\345\243a\251#R\032\264b\344U\205NEZ\2123\332\257\302\203\035*\312\256*\314KWbL\325\310\324\212\267\030\253q\212\267\030\300\253H8\024\363\326\244\214U\220p*6ni\350x\251U\261O\022c\275L\016V\271\215^P\'j\255fr3Z\000\361]=\316zU\007L\325Yb\246G\030$\356\\\323g\215v\340\014U6\204g\212i\207\035\252\'L\n\244\313\226\250\335\001\025]\222\241\222!\351P\371X\2441\373SvS\035\006*\254\211\315F\023\332\224\256*\274\321\036\265JH\371\252\357\035Wh\352\027LUvJ\215\222\243+\232aZn\312]\236\324\236]0\305\226\351N\021\201\332\224\214\016\005B\352z\324x4\355\264\340\225 S\212pZ\221W\025<M\206\305hF\003\n\265\030\013\203\232\273\031\033\263V\223\346 U\310\243\253\221-[@j\324C=j\334iV\321F*`\330\247\003\232\2318\024\346~)\2523\311\251C\000:\322y\271<t\247+\222j\331p\260\023\350+\212\325n7\336\020\017z\265d\010\210U\302x\256\306x\2623Y\356\254\033\030\2440\356^j\006\210&j\273\214\324;9\246\262\361U&Q\212\242\303\rMa\232\201\227\232\215\227\"\243\331\355M)Q\264~\325\033&j\274\221T^Y\007\245\005)\217\036S\025FX\360q\212\250\350EWu\250\035sP\262TE2*3\036\r1\243\246\354\240!\247l\317\024\236X\035)\245)\n\323\031\001\025\021\214f\215\235\251\301qN\3059G5 \034P2\255W\255\337+V\324\234\365\253\260\223\305h\302+B\030\317\004\325\350\243\253q\303V\2221SF0\330\253\033\200\342\225y\251\223\000\212yp(_\230\344\364\247\026\354:SX\361\232\025\262jh\371p(\324\'\362l\334\203\332\270f\224\315\250rs\315o\333\340D*Fj\357\331r1U\336\021\311\252\316\230\252\362.EVh\371\250\312T.\274U)\224\363T\335y\250\312\324n\265\021Za\\\nf)\n\212i\217\212\205\242\250\232:\215\223\212\210\361\326\253\317\020a\270U\'\217\034\032\256\361Uv\214\347\245B\321\373T&:c\'\2657g\2654\307F\316)\205pi6\032_.\230\340TEM0\251\244\300\240\003N\0035\"\245H\026\224G\223V\241M\275j\334K\223Z\020\'J\320\210c\034V\214$`U\370\270\301\253Q\216r*\300\351O\035jA\315J\265 <R\257\'\232y`)7SX\223J\274T\361\023\274b\250\353\262\355\263a\232\344\254\206\353\242}\353\241\214\341\005\016\374W\245\225\302\346\253\311\320\325)\033\006\253\221\223Ld\2462dUI\020\203U\244L\366\252\217\036\r@\313\212\205\326\242\333C\'\025\026\312@\200\232\0311Q\225\250\231*\027J\255\"\363Q\373\032\255<g\265Te\250\231\001\250Z<\324/\030\025\003!\246\204\244d\346\215\234S\0319\246m\346\224\216*3\036M4\246(1\002)\202\036zS\374\216(\020\034\324\202\023\216\224\276^)Pa\352g\004c\025v\331~Q\232\320\210U\350\372U\310\215_\201\270\301\253\252jd\344T\275\351\312j@\302\236\032\220\276)\003f\236\r>\224u\251\342\341\263\336\2615\3713\0063\326\261\364\350q\363\036\365\256\016\005F\357\305z\254\203\002\252\310\274U_\'{\023Q\274\033y\002\242+\332\230\311\305V\222:\252\351\236*\264\221\340\363U\244QP4t\337,b\230\311\355Q2S6R\025\250\310\2460\315A\"\342\253\025\313Tn\230\2462\007Z\253$>\325U\342\305B\350j\007Z\200\2574l\244d\346\220%&\314\324f/jo\227\315\036_\265\'\225\232C\035(\217\035\251\342<\323\304C\024\377\000+\332\243d\035)\004X9\251\025A<\325\270\260\005Z\211\271\253\321\034\325\350\205]\210\340\325\310\316j\324t\362y\240f\245\\c\232\013\372R\014\232x\025\"\324\270\342\201\326\247P\0262Msz\273y\267\001\007\255%\274B8\305H\315\212\206F\257_q\220EV\221\017LP\261m\213=\315B\312\017\006\252J\233[\332\242 \032\202U\342\251Jv\266j\274\256\254*\233\365\250\310\244#\212\215\210\250\331M7e5\200\025\031\003\322\243+\212\205\343$Uf\217\006\241qQ\021\264\344S\035\327o\"\240\"78\250\244\203\216*\244\221c\265V)\316)6\373PV\233\266\215\264\214\244SB\022zS\374\260GJo\226=)\014C4\024\244\nE=G5&\336)\206<\236\224\322\204Sy\006\247\2175a\016\0105\241n\300\342\264b\305YL\223\305_\210`\n\262\247\002\22795\"\212~\323\212\002\323\324S\300\342\234\274T\203\030\247\306\273\2152\366\341m\355\311>\234\n\347\243\314\363\231[\271\253\'\000T\016\330\252\356\365\355,*2}i\254s\326\241\221Fr*\234\343*MT\315F\374\325;\204\342\2502\235\325\033%FW\024\322*\026Ni\n\234Tnq\305G\3114\204S\031y\246\260\312\325vNMV\225y\250\031x\250]\005@\321\200sM\335\203\212\202^j\253&M&\312B\224\302)\n\363\232P\240\360i\341\024\016i\010\002\243`{SB\234\323\274\262\324\276Q\245\010}*EZ]\225\033(\246\010\213\267\002\257Am\201\310\251\036\330\237\273O\2127\214\362+B\007$\201Z\220 \332\r[Q\212\220S\227\255N\20350\240\n\\sN\002\236\253R\005\251\031\322\010K\023\\\305\375\343]\335\354S\300\251\241@\250(\221\270\252\22275]\332\275\300\217\226\242\"\243j\211\263P:\361T$R\030\342\240b{\324\017\310\252\357\0379\250]*\007Z\205\201\024\303\327\232R\006\332\257*\234\346\230\006E!\024\025\342\240~\016\005B\334\036j)\023#5]\227\031\250\030T.8\250\031p3P5FE&(*1Q2\203L)I\202(\301=\315\000{\324\212\027\034\322aI\342\245D\006\236\312\000\342\243\"\200)[\201U\231\362\330\025z\326/\227$U\261\2000*h\3075dF\254:T\321\333\250l\212\275\032\2201V\024T\201x\346\234\027\0252\034\n\225i\364S\224sS*\324\221\250\316\343\320V>\263x\0262\212k\032\321\tb\355\336\257\347\002\241\221\252\253\265Wv\257u\030+La\336\230\302\243+Q\272|\271\2522\'\314j\244\321\367\025X\255F\313PH*\273\212\205\307\025X\3474\274\342\232F\356)\230\000\321\267\232F\034TE\006rj)P\036\202\241\333\301\252\322\016MWu\250\030d\325yW\236*\002\246\220\255&\321A\034T{i\254\242\231\266\202\231\246\354*iH\371r)\213\220\325aM.I4`S\325\0052D\310\250\243\200\2313Z(\241\020\001OQVcQ\212\263\030\305YC\201S\2415a\rJ\005H\242\234\006)\301\261O\rR/5:-L\253\315%\304\253\014\004\347\265r\027\222\233\213\242\001\34354K\265\000\2473b\253\310\365Y\332\253\273W\274#eqN<\212f)\207\2555\271\030\252\262\256\006j\214\300sU\031y\250\234b\253?5\003\017Z\211\300\"\253\270\301\246g&\235\266\230\303&\200\264\256\237-FS\345\250]qU\334aj\254\213\315Wa\315Fc\357P<|\364\250\032>i\205)\n\323H\246c\232\nf\231\345\322m\"\202\271\246c\007\245!Nr)Fi\3034\361\322\244JW\031\024D0sS\257&\245U\315Y\2163\334\325\244\003\0252\214\364\025*}*u\315XOz\224\nv>Z@*H\324U\230\343-\320U\205\214(\250\347\235`\214\223\332\271\275CSiIU<U;t$\356=MZ\316\005D\357U\235\352\263\275B\315^\363\033\032\260\005.\312\205\320\347\212f\323\336\253\312:\212\316\234`\232\252\315\316*\t*\273\016j\tEC\332\241q\223Q\205;\252]\274SJ\322\016\r9\206V\232W\344\342\253J\274UgSU\335*\273\2450`qM1\006\344T/\t\035\252\022\236\325\033-DE0\320r\005&}\250\340\322\025\244\331N\020\223A\207\035\2516R\355\305(\006\214S\324T\350\242\247A\316jl\340f\254E\261\272\234U\224P:\034\324\243\216\265\"\232\231\016ju\351K\221@\345\252\314j8\253J\301\023\336\206\223j\344\326>\245\177\030VBy\305s\250\014\323\356\355\232\276\200(\024;qU\235\252\273\265WsQ\023^\363\023\032\271\021\334qR\260\001j\034\344\032c\364\252\362\216+>\341j\223\2475\013\241\252\3161U\244\316\352\204\234\032C\203M \003E4\321\301\244\301\247\001\362\325yW\232\255\"\325vZ\205\326\240d\346\233\202)\303\004r)\215\022\236\365\013@\247\241\252\317\0378\246y=\3151\227\034b\231\267\332\224\'\265;e<EN\010E\014\265\031JB\236\324\233)BS\302T\212*U8\342\245^jU_J\225\031\222\246Wby\251\325\215O\035O\277\013M\335R\241\2531\236)\346U\034\223\370U[\273\264X\030\206\344\n\345.%\222{\234\003\236j\344\021lA\305NN\005B\355\305Wv\252\356\325\0030\250\213W\276\333\200\307\025\245\014AFOZl\374t\250\020\363C/\025^A\305R\230f\252\262\361Q2qUd\217\025RH\370\316*\253\247sL\000\322\021M&\222\224-.\323\232w\226@\250\244Z\201\2235]\343\250Z:\211\243\250\232>i\245@\355MaQ\260\342\2532\363@L\323Z,\366\246\030\271\245\021\323\204\\\363N\021\322\025\3057\214\320R\223e!JP\224\241)\301qNQS(\251\226\244\034\324\213S%YN\224\254iTqV\020qR\027\001}\252\255\304\247\313f\007\240\256vi\345\222B\245\2163V-\242P3\216j\346\000\034TN\330\252\2621\252\257!\252\317-@\322\023Q\0279\257\241`\005n1\357Z\352\006\320qP\315\311\250@\305.2*\t\005T\221rj\263\246*\"\271\250dL\325Y#\305Vx\262j#\026;To\037\030\002\232\260\023\332\217 \346\236\">\224\361\027\265)\213\"\240\222.\rUd\250\331\006j&\217\332\240x\352\"\236\325\023%4\245F\321\361P4DR*\034\323\214d\016\225\036\337QO\021\361K\345\361\322\232@\025\033\014\232f\312B9\247\201\305 \\\265<\247\024\230\346\214{R\201\212\220T\202\244Z\225z\324\311\326\254)\342\224r\334\323\267\000i\341\317\2552Iq\225\007\232\251.\346\3435VK\022\351\272#\363\016\265\n\273A&\3118\"\254\254\301\207ZF \214\325i\031q\315@\301J\014\n\204\307\023\003\203\315C\373\224\310\3175\032\307\026\342Y\270\257\241b\205\214\275*\371R\261\363P`\263R\355\246\221QH8\252\2169\342\240e\250\212\340\323\0361\212\253\"sP\230\306y\243\311\004t\246\033q\236\224\206 \005 \210zS\274\241G\225\307J\211\320\366\025\003\241\3475Y\343\346\2421\323Z>*\027\212\240h\3523\036{S\014G\322\232c>\225\031\204\236\324\317#\236\224\276W\035)\206\036i6\001H\330\013\212\201\201&\232W\024\3023MaJ\006V\236\006\005\007\232B(\242\234\rH\265*\324\313S(\251A\342\214\220x\240\034\236i\373\360*\256\377\000\230\234\322\226\315\"\311\264\361T\357\224I\363\257Z\247\034\254\255\264\325\245\223\"\231 \014\rU\221[\261\252\305Xg\232\201\220\346\242`\330\353_R,h\234\201QJs\300\250\200\300\351M9>\324\230\250e\342\251\277Z\217\031\246\262Tex\250\214y=)\215\007\265\013\027\035)\216\235\361Qyd\232_/\024\334\200i\330\310\340Tm\031\034\324\017\021\'\245@\360\221\332\2431\037J\215\242\343\245@\361\361\322\2411\323<\256zQ\345f\232\320\373Tf<v\244TRi\222\"\216\225\003\014T,=*2\204\323J\000)\214\275\315D\374TF\236\237v\236\242\224\250\317\002\232E7\275\024\345\025\"\324\253S.ju\351N\035h,(\0075\034\357\265x\252\341\370\245\014i\254\370\346\243-\237z\253s\030\021\357^\010\246A.\345\353\315NX2\324M\327\245Wp*\007\025\023\001_M;\222i\244\214g\275G\272\233\273\232F8\346\240\220\344\325Y94\305\353N#\212\210\255=c\342\203\036x\305\036A\364\250\336\034T^N;S\032#\236\225\030\265f9\251\204!@\030\241\240\310\351P\264\001y\305@\360\226=*&\207\035\252\027\217\332\253\311\027\035*\003\0274\276H\2464U\033\246:\325yF:\n\200\014\032k\363Q\024\3150\240\025\031\317aQ\260\356j&\250XsL*\000\245^\230\247\201\212\\f\221\207\025\021\0304S\205H\246\246NEL\242\244\007\024\273\270\240\036i\335\005A;(_\230\324!\327\265#8\365\250\231\211\250\363\207\251\22614l\246\263$F\266\271\307j\262\207+\221H\336\265\003\214\032\205\252\006\007<W\323n\240T-Q\226\346\22074\214r*\0065\003\212`\034\323\361\305 \034\325\204A\266\237\345\202i\345WnqU\2353\315@E \217\'4\355\273V\232\027\'4\273)J\006\030\"\241x\200\355Q\275\266\344\310\252\022DC\021\212\204\307\221\214T&.i\273;Tl0j\ty\025U\3275\tJiJc\'\245D\312\007Z\211\215@\374\324L*2\270\250\330SA\301\251G#4PNj2)\000\247\001J:\324\250qS\253\nxn(\335\223J\r<\310\002\326e\334\205\244\340\361Q+7\255H\r!l\nb\235\322\342\254D\373%\036\206\253jQ\226>`\250\255\333)R\265B\3759\252\356*&\257\246\237\247Z\256\325\013\032ny\244&\230\325\023S@\357O\307\024c\232\220t\251\024\343\255+\032\211\360\006\rE\263\'4\354`{\323v\026\353N\t\201AZP\234S\0352*\"\n\212\257$a\273sU\274\262\037\030\250\245\213\346\340UwM\240\3256\004\232\211\226\242)\3150\306*6P\007^j\007\340qU\336\240j\214\203M)\216MB\352I\250\231j3\301\247#\343\203N\'=)\246\222\201\315;\"\200i\353R\255;w\024\240\340S\267TRI\216*\204\257\271\350SRg\212c\036)\320\241\332d4\363\326\222\361\317\331\016\006N+2\316_\230\251\253\347\221\232\211\352\007\025\013\n\372T\267\025\013\032\205\271\246\342\222\214dS\031i\240T\212\274P\027\232v\332P\246\244\013\232\206D$\322\204\342\217/&\237\345\340Rl\243fi\3730*7\003\246*\026_J\205\327\332\253\272\214\362*\027\030\311\252r\215\306\252\310\230\342\242)Q\225\000\032\205\224c\232\201\300\354*\263\365\252\362\n\210\306@\311\244\340\016\325\023\234\232\204\203Q\260\250\330TD`\323\220\323\262)\t\244\024\3409\245<S\220\324\303\245\035\005&\352\025\263\234\324\022d\344\325R\tjx\030\024\361\322\230\365a\177\343\330\001L&\235\"o\266#\332\261\020\230\356\361\357Z\200\345*7\250Z\242j\372;vi\247\232i\024\3021I\212P\264\205i\002sN\013\212pZP9\247\005$\323\366\020)6f\234#\000Rl\301\244\"\223m=R\206\\\n\254\343\234\324-\355P\271 T\016x\250\033\200sU\335qU\231rMB\343\035*\006\342\253Hj\273\232\205\252\027\0375A&I\301\246m\342\232W\212\215\226\242aQ0\246\025\244\333\212CI\232\005H\2645*\234T\301\250\'4\323\322\221O4\3761\212\253,a[\212`\031\247\201H\313\221R@\300\257\226\177\nq\214\206\344S\230\205\214f\271\351\330\177hq\3235\251\031\314b\221\252\026\025\003\n\3720S\261F)\254\274S\002\363R\252f\224\307G\227\355F\312]\270\240\'9\251\02503A4\252\274\323\310\342\232V\232W\035\250\013\315H\023\345\246H*\254\202\252\270 \361P\276qP05\014\200\342\253\276j\006#\323\025\004\207\212\255!\252\316sP0\250\230\036\325\023\200\277Z\204\256MF\324\200ToU\330\324li\271\243\212a S:\267\024\247\212p4\244\361\212\001\346\236\032\227&\216\364\243\255:\230\3005B\321\262\362:P)\304TeH9\025 \231\372\032\t2g5\205p\240_\340\036\365\253\010>P\245aP8\250Z\276\214\002\235\203J\007\024\025\240GR$f\244\331\353N\330\r4\307\3155\223\240\247\254|R8\343\002\221c\346\227\0304\355\274R\025\246\3554\001\203R\250\371>\225\024\202\252\270\252\354\271\252\263\0208\025BI\260z\324M)aQ\227\300\346\242r\030d\032\256\334\234\032\2570\317N\325Y\207\025\033.MF\303\265@\353\315FF*\026\034\323\017J\211\352\263\032\214\232i4\274\232c\n#\03148\301\246\203N\355IN\006\236\r8S\200\247\021\306)6\342\224\256T\325}\270\245\034\322\355\246\021\212z\361\023\034v\254\031>k\354\373\326\274C\367c\351C\212\201\205B\342\276\213\214\202\264\360)\312)\341sOT\025\"\256\005;\031\355J\027\024m\243`\353K\267\232i\217-NT\366\244h\271\351K\345\340Ry~\264\206>(\362\300<\212q\\\'\002\253\3108\252\3169\252\322\215\243\216\265\231u.\320Tu\254\311\030\223\232El\234S\23521P\210\310lSd\030\037J\251!\252\315\313`S\\aj\003Lj\211\205D\370\252\354j\0075]\215D\315M\007&\245\310\305FNO4\241\202\232\034\202\271\250\327\255?\265%\003\232\225G\024\3608\247\216\224\360)v\203F\334\016\225]\303g\247\024\325\353O#\212i\024\262\376\356\305\233\326\260#\033\256\363\357[\0100\224\214*\026\025\003\327\320\250p\265<d0\251\300\342\236\253R\001N\003<S\302\322\355\245\013K\266\230\344\001\307Z\024f\246T\035\351\3053\332\223\313\244)\212@\224\273)\245x\252\262\255@S\034\232\317\272\3178\254{\216\033\221\315Rp\\\234t\244\2162\032\255,C\0315\033\247\031\035\252\224\255\203\217Z\256\3000\307z\252\343cS\034\344Uv<\323\t\342\243c\212\255#Uwj\256\355P3\032\211\2157q\007\212vx\347\232B\337\205&\356i\331\342\201\305;4P>\365L:S\327\255H\005<\np\024\374Pc\014\270\305T)\266B)J\322\005\313b\242\324\330Ge\264V5\222n\233uk\205\302\323\030T/P=}\010\237v\236\231V\253\2502\271\251\025jM\264\345\024\340)\364\034\nM\340Td\206oJX\3075:\212\231E<-\005\001\352*#\036\r&\332\211\370\252\356\275\315V\226\251\311\030`I\254\351-D\222{TRZ*\360\005@b\nzPH\013\212\256\354\002\232\312\272r\030\340U?8\347\255\014\341\2075\023t\342\240bA\346\241f\250\236N*\263\275@\355P1\250X\342\243-Q\347\234\203K\270\343\232C&)\276`\025$d\260\346\244\343\024\231\346\236\001\357J\007\315S\252\361O\333\212\220t\247\001\315J\242\235\216i\300UYS\022\223I\266\234\211\316k;X?\273\013T\354\023\0038\255 8\250\334T\016*\006\025\364\"\014\n\221E[\204\360\001\253\010\265(ZpZ\\P~Q\232\210\266\016i\243\0079\243\0254c\212\224S\301\311\305[\21523J\313\307J\205\226\242~*\007\300\025^CT\344\334OC\305V\22398\250w*\365\252\362\260&\251J\3305Y\233\212\257+qY\327<\346\262\246r\215R\307\"\262\212s\343\025ZF\035\352\263\363\336\253H\304\032\254\356j\026\222\240ij\026|\324l\324\320\364\355\374R\026\2461\251\"|\032\230\266E*\014\265[\013\204\243n:T\250\274S\310\247(\251TT\201i\330\245\002\242\222<\266{Sv\361OT\302\023X\032\213\231.\n\203\221\232\232\322-\261\216*\321\034T/U\336\240j\372\031W\212zu\305M\037\016\r_\214n\031\251\200\002\227\0034\340\006*)\272\201P\3435$Q\344\344\364\247\030\300l\366\247\001\201N\035jE\034\325\330\370ZV\306*\006\252\322\036j\']\340\3253\220\331&\240\221\267\0021\212\252\374\003\315R\221\360\335j\264\217\236\365RF\311\252\356j\274\206\250\334t5\213t\334\232[Y\003\246\t\346\245\222L\034\032\254\362\202j\007\222\240f\334j\'L\212\255\"\221U\0379\250\211\300\250\231\251\273\351\301\351wS\031\252H[\236j\312\363SF\274\325\240\016\005<.jUZv\316j@\270\247\001\212\220\nv)v\321\267\"\220G\226\305C}\"\301\t\003\251\025\317\252\031\256\013\037Z\321\2156\255)\250^\253\270\252\357_GF\200\241\372S6\235\3254c\234\342\256\304H\024\362\3314\364\346\244\002\242\224e\251\250\2718\251\210\300\300\246\362E.>Zp\025*\216*\312\034(\024\254j\t\017z\252\334\234\321\301CT\2350\344\365\252\322\232\253.6\363Y\227\r\363qU]\252\263\236j\002q\326\243r\rS\235r\ra^FA&\250\307#\306\374T\322\\\026NG5XHKu\245\222E\333\214\325G\220\347\203Q\231\330w\246\231\367\016j\007`j2\271\025\003\241\315B\331SH\032\235\272\221\216jH\201\334*\344}j\354)\222*\340Q\216\224\005\305H\243\332\2368\355N\034\323\302\373S\302\323\361F\005(\\\364\247\235\261FX\327?\177pg\230\2504[\301\265rEY\306\005F\325\003\346\253\275Wz\372L)\t\305\t\026j@\230\251\001\"\236\t\251\321\224\nq\223\216)\230\'\232z(\316i\314F)\024qGSNQ\315L\243\212\224t\246\226\250\035\263\305@\346\242g\307\031\340\324\016\371\031\025Jg\2523I\3335JS\221U\\\325Y\016\016j\254\262\017Z\252\323d\365\250d\220\342\263\256$R\010\"\263\300_4\361I0]\243\034U\031$\021\236\rWy\263\320\324-6\017Z\215\246\3175\031\230SL\271\246\2311\336\221d\014y4J\237.EV\344\032p\346\236\006M\\\211@\213=\352\324\020\226\347\025\243\024AG\"\245\306\005(Zp\004\236\224\340\005=G5*\343\024\341\326\227\212\007&\245A\203\223T5;\200\020\242\237\255dA\016\3717\032\320T\300\244j\201\352\273\232\201\352\006\257\246\000\036]\n\2705 \024\355\264m\245\301\245\004\324\313\215\264\361\200(<\232\017\024\224\365\0252\322\223\201P\273\361P\027\031\344\324NsQ\034\223Ue}\271\025FY9\353Te|\325g5^R\000\254\371\245\352\001\254\371d9\353U\032S\236)\246V+\315S\230\026=\352\253(S\234\325yd\031\301j\245q\317C\232\250r\rA!9\342\242.GZ\211\236\2247\035j\'\223\234f\221\031\263\232\264\262\345v\2654\246NE*\241\024\360\234\325\270Wq\000V\254*\252\200T\333\261J\244\261\251Gj\221T\236\225\"\307\223\315.\314\036\224\240b\226\223\222x\251Qq\311\246\334>\310\211\2549KM9\006\254\305\026\325\034T\207\201Q9\250\034\325w5\003\232\201\253\351\264\033\233\025\"\257\315N\013O\013F\303K\263\332\215\224\340)NH\247F\0079\241\272\320:\324\252*A\300\250\335\252\254\217U\213\374\324\222I\264Tm8\331\214\325\031_$\325\t\237\006\251\311 \252\3176;\325if\005q\336\263f$\223\212\247\266I\037\030\246\264a\007<\232\214\270\3060*\tYpk.\341\362\373A\252r\3061\235\374\32578\352j\t\037\266j\263\277\275V\222_z\201\246\347\255\'\235\357B\266\346\346\247\\\nvOj\222)\212\234\032\264\256\206\224\272\366\251\355\233\347\255(\332\245\000\232\236%\305N\213\226\253 m\034\014\221Ud\235\222_\230qO[\210\334u\346\236\034\023N,\000\246\371\252\017\024\241\311\250.\245\312\355\252\261E\203\223\326\254`\005\250\334\324\014j\0275\003\232\201\315@\306\276\241\215v\362jLqN\013O\002\227m.=\250\332qQ\3644\274\232r\360\r%9jU\245f\300\252\322=T\221\352\020\3375U\270\234\324BM\313\357L~\225\235p\330\315e\3176\334\325\006\237{\340f\227\2675\013\2202j\234\263\355\310^*\234\223\022z\324&N:\325;\211\361\3005\225q<\212I\004U\031.\244\317&\253\274\356z\324FBj\007\223\236j\254\262b\253\231i\276a\315M\034\225ad\036\265 \224b\205l\234\325\204j\235Wq\253P\215\254+F2x5i9\025b1\212\261\020\313\375*\302\221\232\257w\002\261\311\357U\205\272\250\316iw`\342\245Q\221\232O/\234\322I E\300\250\000.\3315&0)\t\342\241sP1\250X\324,j\0075\003\032\372\224\360qOZ\227\256)\300S\200\243\024\275\25229\244\307\024\023IOZx8\025\034\217T\345z\252\355Qo\301\252\223e\345\300\245\t\265j\031d\254\333\231\0075\217tI\316*\224jD\231\251\035\360:\325I\246\033N\rfO8\007\255Q\222\351W\275V\226\364\343\212\247-\300\332N\356k6I\333\177\'5^Yr:\325f\230\201Q\375\243\265G$\274\365\252\322\313U|\317\232\227\314\031\251\342pj]\370\247\243d\340\325\310\243\316\017AS\252\340\325\210\370\253*\325z\007\312b\257B8\251\301\033\270\251\342?=[\0108#\255Ar\334\212\200\234\216h\n\247\236)\306DE\252\315p\316\330^\224l$e\251\352\000\024\214j\026j\215\332\240f\250Y\252\026j\205\332\240s_T\205\311\251U{S\300 \323\2058R\221IL4\334\361IH\r=x\245f\300\252\262\311T\344z\201\236\242v\001ri\261\000\331j%\220\0055\227s6\001\254\271%\017\236j\224\254NEV\334\007SU\247\234m\3005\235,\303\004\223X\363\334\356\224\200x\252\262L\000\344\325)\256\200\035k>k\337CT\336\357=\352\273\\\373\324/u\357Q\371\371n\264I0\307Z\254\363g\275@d\301\2442\361\326\246\202nz\325\325\220b\247\210\214\346\257$\213\267\203R\207\025:IR\306K8\025\257n\200\'5l8\003\002\236\215\315Z\211\276aW\200\371s\350+>\342_\336\022{UG\231\211\343\245 \226Lb\234r\303\223O\211@5+\035\274S7Tl\325\0135D\315P;TL\325\0135D\315P\261\257\254UMJ\253\212x\\\323\202\214Q\267\006\214SH\246\221\221Q7\006\220\320\r(5\024\217\306*\244\257U$z\204\265FX3\373\n\014\312\203\212\247s8\307\006\261\256g$\360j\231c\234\223U\346\230c\000\325)$\371z\326u\305\301\307\025\2354\216\312rqYsH\251\336\263n.\361\336\262\347\273\'<\325\027\270$\365\250L\331=j)%\003\275C\346g\275\'\233\212\215\356\017\255Df\367\246\231s\336\232$5,r\2259\253\221\316\307\025v)\t^j\3129\003\255L\222\234\3435f7\367\255\0136\005\362kZ7\371i\341\271\251\321\252\314rU\227\270\"\002\027\322\263\335\362\204\223Q\251\024\361\212q\"\225\037\rN\221\352\"\374Tl\365\013=F\317P3TL\325\0235D\315Q3W\327\n\243\025\"\347\275J\005;\024\021M8\2461\246\026\366\250\234\212fx\2434\326|Uid\252rI\326\253<\225\013\310\000\252\223N\300`UG\273!pMT\232\345\210\344\340U\tn\027>\265RK\203\3175RI\262z\325\033\273\235\211\200k1\356\200RI\254\313\273\376\300\361X\367\027\204\347\232\313\232\344\223\326\250\313>{\325V\224\347\255 \177SQ\311&j0\344\320\315\305Ww\346\242g>\264\335\347\326\236\255\232\235\016M]\213\240\253\2616*\300n*X\316M[\210\372\326\205\273a\270\2558\337\345\353R\006\346\247G\340\n\261\034\2035.\360\313\267=j\233\276#\306{\323U\352@\374Q\346P\036\203&i\254\374T,\374\324e\352&z\211\236\242g\250\231\2522\325\0335}x\265*\324\200\323\201\246\263\001Q\263\372TM%F\322Te\363Q\371\2304\246Q\212\201\345\367\252\322I\357U$\222\252\311\'\275V\226^:\3259\3468\353Td\227$\363U%\227\336\251K \346\251K7\275V3ry\351Yw\327\031;Ee\312\314\300\362k>\340\343\275eN\374\236k:W\344\325I\036\252\264\230\246y\324\323&h\363\000\2464\271\250\331\370\250K\363@|\323\325\252\3126*\324RU\264\222\247Y*x\344\253\220\277\025v\031p\302\264\243\227\345\034\324\302J\225\0375:I\212y\223\234\203PL\307#\236)\201\352A\'\035i<\312Q\'\024\027\367\246\031*6z\214\275F\317P\263\324e\3526jajal\327\330\013R\203N\0243\342\242g\250\231\352\026\222\2422S\014\225\033=Df\307z\211\345\252\357/\275U\222J\251,\275j\234\223q\326\251\3137\275R\222lg\232\245,\376\365JY\375\352\234\222\344\365\250%\224\"\365\346\262n\246\031\316k>K\2360+>i\207$\234\326U\304\343\'\025\235$\371&\252\313/\025U\234\223I\300\034\232a|SK\322\027\250\335\352\022\374\320$\251\222J\262\214\010\253\021\266*\302\275L\262U\230\244\253\320\313\212\267\033\022r*\3443`\341\215\\Y2:\325\210\333\212\260\255\353J\314;S\035\267!\035\352\272\311\316\r?\314\2442P$\245\363=\351\206OzcIQ\231*6\222\243g\250\313\323\013S\013\023HZ\276\304\024\360h/\212\215\236\241i*\026\223\336\241g\250\313\323\031\352&\223\336\240y*\006\227\261\250\036_z\255$\265Ni}\352\224\263U\031f\347\255R\226c\353Te\233\2575JI\275\352\263\312z\346\251O?^k\036\356\357\031\254\231n\230\236\rT\222vn\365RP\304d\3259\001\355Udoj\256\316j#!\007\232a\226\2433R\031\270\353L3qL/\236\224\002jtlU\230\333\236\265iZ\246W\251U\252\304lsW\241$\342\256\306\370\253*\371\031\253v\355\317Z\274\215\317Z\230I\357A\223\214\323|\317z\255#m\227>\264\276g\024\323\'\275\036e\036e#I\3150\311Q\231)\205\351\205\3522\364\322\364\233\2517W\331#\245\005\200\250\231\352&\222\241g\250Y\352&\222\241y*#/\275B\362\325w\227\336\253\274\330=j\007\233\336\253I?\275S\226oz\2434\336\365FI\275\352\234\263{\325\031e\346\252\274\252\243,j\214\327@\236\rg\334\\`\036k&y\201\'&\250;\214\232\201\210\353P\311&*\224\262\202x5Q\334\032\254\357\315Ww\250\213\324L\306\243.i\273\351\312\334\324\310je\253\021\346\255#qS\255L\265b.\265\241\020\302\365\251\325\275\352\302\023\212\267\013`\216j\342\2775\'\231G\230qM2b\243\225\262\231\035EF$\312\322y\224\236e\036g\2754\311\357M2S\014\224\322\364\322\364\322\324\335\364\233\250\335_d\227\305F\322TM%B\317P\264\234\365\250^J\205\245\250\036J\210\311\357P\274\236\365]\345\367\252\262KU\236~1\232\253$\336\365NYz\325)$,z\3259\337\000\363T\036ny5N\342\351\020u\311\254\251\356\214\204\363U\332L\014\346\250\\K\327\232\314\236^j\241\227&\242iq\336\253\311.{\325\031\344\367\252fc\232cI\232\201\332\242\335\315\007\245D\324\334\363OZ\260\202\247QS\2409\253(*e\310\251\220\232\263\026sW\020\260\253\t\353V\343n*tl\032\260\262qO\337\317Zpn84\326~y\246\357\312\221\353U\303\320^\233\346R\031)\246Ozi\222\223\314\244\337H^\232^\233\272\215\324\273\253\354fz\205\244\367\250ZOz\215\244\367\250^J\256\362{\324-\'\275@\362\373\324&Rj\'s\212\251,\270\357U%\233\320\325ff<\324\022>:\232\251,\243\034U\031f\300\'5\233qpq\301\254\271\256X\023\315P\226m\304\344\325v`;\324\022\313\307Z\317\270\224\016\365\233+\3565\003\270\002\253<\236\365ZIj\244\262\023\232\252MD_\232k6j<\321\272\232ri6\234\324\210\rYE5e\026\254F\230\253\n\271\251\225*eQV#\035\305ZC\221S\247\0252\032\231Z\247\007\013K\272\244V\244f\346\242g\301\315D_\232izizazizizO2\227}\033\3517Rn\244\335J\032\276\302y}\352\006\223\232\211\244\250\232J\205\345\367\252\357&j\006\226\241g\317z@x\315E+\200+:y0MT,Y\251\256\333S\255g\3157\315T\345\227\216\265Fi\307J\241<\240\326M\324\230\'\025\236\362\234\346\242i}\352\t$\033k>bI\252r6*\254\217Udz\252\356j\2731&\242s\212\2074\322sHzR\001N\002\234\007\265N\211S\242\325\230\326\254\242\324\312\2652\216)\340sSG\232\262\206\254!\251\327\025*.MM\216\202\223\245=Z\234\330\252\357\334\325p\371\'\353HZ\230Z\243/M/M/I\276\227}.\356(\335I\272\215\324\273\361_]<\265\013I\357Q\231=\352\'\227\336\253\274\276\365\003K\212\205\345\311\3115\013INY\206\314T\022\313\226\306j\244\305H\3115X\262\2579\252w7\000\214\003Y\362K\234\363Tn\'\300\"\262\344\270 \236j\244\263\346\251L\340\203Td\034qU\237 Uvz\255+U)MU\220\325I\rT\221\2105\016\354\323\030\023Q\2254\334Q\212P\016jEZ\225PT\312\240T\350\265a\024T\352\270\251@\251T\032\225V\245AR\250\251\220\325\2049\253Q)<\323\317\007\232i4\344>\264;\324r\034G\232\243\273\014i\013f\232Z\243f\250\313SwQ\272\215\324\273\250\337I\272\227u\005\373W\326\317%B\322{\324M-Wy\252\006\227\336\241y}\352\026\226\2432S\014\330R*\264\263\221\3005NY\333\326\252\311p}j\243\315\234\344\325g\227\216\265B\342N\t\315c\3157&\252I>;\325v\227=\352&~*\274\207 \3257l\032\255#UI\rU\221\252\244\215U\334\346\242\305!\3054\323\010\346\224-=R\245T\251U*EZ\225\027\025a\006j\302\255H\253S\306\276\3252\255J\251\305H\022\234\027\232\232>\r_\207\033)\254z\232\210\223\234S\201\305F\362sI#\342\036j\223\037\232\220\2654\232\215\215FZ\230Z\223u\033\251wQ\272\215\364\027\244V\347&\276\260ij\026\227\336\241y}\352\273\315\357U\336oz\211\246\343\255Be\367\2464\330\357Q\231\262z\325ye\025JY\272\3257\227$\344\325g\232\252\311>;\325\033\251\276^\265\2174\274\232\246\356sP\264\204SL\271\024\326|\325I\271\252N\3308\250\035\252\254\246\2529\252\354Ni\2314\224\020i6\232z\255J\251R*T\252\265*\247\265J\022\244U\305XCV\021r2*tJ\231V\236\000\006\244\030\247`S\224U\250O\312E)\351L4\235F*\274\334sLg-\025V-M\335\232B\324\3265\013\036i\204\323wQ\272\215\324\273\2517SY\351U\253\352\271$\307z\256\322\325w\232\253\274\276\365\003\313\357P\264\276\365\031\227\'\2555\234\343\212\214\270U\353U\345\233\212\241$\274\232\251$\270\315T\226n\274\325\031g\353\315Q\270\270$b\250\271\'\232\201\263\232a\217#\255WrP\342\230_\212\202G\343\255S\224\325v5]\352\263\n\204\2574l\366\244\333N\t\232\014t\241*EJ\231PT\252\2652\255I\266\224-J\252j\324+\212\262\253\315J\027\212]\274\324\252\231\024\340\224\340\2475*\002)\335\3151\215D\317\3155\260\352A\250v\262\361\332\240\225\010\344w\2503\203Aji5\033\034\324d\323I\244\315\031\243u1\236\232\016i\341\253\352Y%\343\255T\222_z\256\362\373\324\017/\275Wi}\352\027\230\016\365\021\270\305/\332GL\3242\3161\326\250\315t\000\353T\245\273\003\275U{\215\3035Ri\275\352\233\271\'\255W\220\214f\2531\250\231\271\246\226\"\253Lr*\266\343\320\324\022\276:\032\252\314MD\306\240rMBFi\002\nv\312iOj\000\247\000\r9TT\312\203\035)\341EH\252*UZ\220-=R\247D\036\225aV\246E\251\200\247\005\315<\014S\351\312*U\034\323\010 \232c\n\201\352,\220i\333\276^j2FpG\025Vh\312\234\216\206\240\335\316\r!4\302j3M&\232M4\2654\27579\245\006\234\032\276\235\222^*\234\222\373\325W\233\336\240ij\027\227\336\253\274\265\003\315\212\203\355\030bI\250&\274\367\252\022\334\226\357U\332L\216\265\027\236\001\306j\031d\356*\263\313\317Z\211\237#\255B\306\242cLf\030\252\3625A\301c\232\212U\034\325fQQ2\324\014\265\031Z6\322\320E&\332P)\300b\244Zx\251\024T\252*e\025\"\216jt\305N\270\"\245A\232\233\024\341N\002\236\242\244\013\223\315?a\0074\2143Q\262\361Q\024\317j\205\242\347\212aLSH\317\007\255F\303+\264\325\031\220\253f\243\007\"\232i\206\230\306\243f\250\313\323rO4\354\321\234\322\203_I\274\276\365RI}\352\254\222\363\326\253\274\325]\345\367\250^n*\264\223q\326\252<\307\035j\263\312OSP4\225\004\223\200:\325V\237\346\353O\363\003\'\275Vs\315Dd#\2750\311\232c\277\025\tcLn\225\003g\250\250\035\352\0265\0315\033sQ\355\346\227m\033ph\"\223\024\001\315<\014\214T\212\230=jt\210\021\326\235\345\221R(\251\005IR\'\275L\246\246C\212\260\274\212\220\016)GZ\220b\245SR\021\221HV\243e\250\310\305D\335j6\250\233\255D\302\240\221C-Qa\265\2150\232i5\013\270\002\240f&\2234g\002\214\346\2274\003\315}\022\362\373\325Y%\252\317/\275Wy}\352\273\313U\336_z\253$\276\365U\345\367\252\3575Vy\375\352\264\223g\275ViNiV\340\203\214\323\313\356\250\236\231\237zBj&<\3237Tly\252\3562\325\023\000*6\250\3174\334\021\326\202i2(\316iv\322\2055\"\241\316sS\205\004sN\000\203\201S\205%y\240%<\nu=jd5*\324\350j\300?-\000S\300\251\200\332\2715e0c\030\240\342\242`\rF\343\212\252\343\232\215\205FED\365\021\372U+\205\301\316*\241$\034TO%BI\'&\232i\271\2434\003K\232Q^\374\362\325i%\367\252\257-Wyj\273\313\357U\336_z\253$\265VI}\352\254\222\325w\222\240y*\026zn\376i\353!\365\247\207\334)\271\346\232Z\243\'4\302y\246\223\336\230~\355V\220\363Q\022)\244\323I\246\021F\017zr\216i\304\220)\273\216jE\222\246Y\001\251A\025\"\310A\366\2513\236{S\201\247\365\247\001OS\212\224\032\225\033\232\262\207<T\370\300\241~\360\253\022\220Tc\322\244\201\206\334S\237\025\003pj6<T\r\311\2465B\325\023sP\276{Ui\033q \365\252r\2569\252\254*2i\205\251\271\244\315\024\240\323\301\257\377\331"
-byte_png: "\211PNG\r\n\032\n\000\000\000\rIHDR\000\000\002\000\000\000\002\000\010\000\000\000\000\321\023\213&\000\000\002\217IDATx^\355\335\341n\2020\024\006P\303\373\277\262dq\233\313\2546\020\004i\373\235\363\263\022\025\250\264\367\366\202\227\013\000\000\000\360\312T6\020a.\033\000\000\000\350\235\020\177\201X\030\000\000\200\036\r\032\360\013\323\001\000X4\350\\\230\265t\000^[\352\031\342M\272\243\323\002\000\000\000\000\000\000\260\215\025g\000\000\000\000\000\000\000\340c\024*\000\000\000@\036\371\000\000\000\000\000\000\000\000\030\307\322\377@\326\251 \000\000\000\000\000\000\000\000\330\344\273\354b{\325\006\000\000\000\000\000\000\000\231\016\277\313\337R6\000\000\000\000\000\000\000\211N]/\277\226\r\000\000\000\000\214e\372M?\035~[\010\000\000\000m8\265\014!\330\211\201\367|\342g\003\000\000\000\000\000\000\260\217\347\245\337\242\000\340y\003\000\000\000\000\200*\267\030\001\000@S\254\372\307\021\225\001\377\030\005\000\000Bx\"\\\272\311\344\037\330L>\021\000\240c\327\262\241\352\0366\n\037{e\342\016\000\000\000\334\311\023\204;\252\003\034\365\276\000\000@\n\005\t\000\000\000\000\260\017+\370\000\261,\267\000\000\000\000@\010\311\3000\345\t\237\237Z\2061\354\216\001\000\000p$\341$]\320Q\001\000\000^\332\347\226\330}\336\345\024\342\305l\177]WG\000\000\000\332\320q\204\r\000\000\000\000\000\300G\251{\003\036\271*\204H?\321\n+\000\000\000`Qz\372\000\000\000\000\200\321\3342^\262^\214G\257\376\254\346\216ws_hp\2167-Q\013\013Y\2121\310\220\364I\343\\p\307\331\023\000\310c\034Of\366\017\220\314(\000\000\000\000\217\304\312\000\300\030T\001\000\3002Y\200\r\3328h\357~\013S\245\316\275\333\001\000\000\200\332\254\272\326\316\316\304\245\000\000\000\034\241\022\330\337\233+/W\333\241Iyy\225\325?\321\325\033\366\"\357\\\003\000\000\300!\346\361\262\006\000\000@\377\004*\000\000\000\260\262VV\020\235neG\001h\215\001\014\000\2003\010\243\341,\242@\250H\371q\244\354\'\025\327\262\201(\346\340\220\3155 \335l\036\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\374\360\357\347\000\000\000\000\354a*\033\000\000\000\240[\375VS\210\317\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\340\246\337g\t\001\000\000\000\000@[b\236\202\377\005\355\265M\274\251\013\246j\000\000\000\000IEND\256B`\202"
+byte_jpeg: "\377\330\377\340\000\020JFIF\000\001\002\000\000\001\000\001\000\000\377\333\000C\000\003\002\002\003\002\002\003\003\003\003\004\004\003\004\005\010\005\005\005\005\005\n\007\010\006\010\014\013\r\014\014\013\014\013\r\017\023\020\r\016\022\016\013\014\021\027\021\022\024\024\025\026\025\r\020\030\031\027\025\031\023\025\025\025\377\300\000\013\010\002\000\002\000\001\001\021\000\377\304\000\037\000\000\001\005\001\001\001\001\001\001\000\000\000\000\000\000\000\000\001\002\003\004\005\006\007\010\t\n\013\377\304\000\265\020\000\002\001\003\003\002\004\003\005\005\004\004\000\000\001}\001\002\003\000\004\021\005\022!1A\006\023Qa\007\"q\0242\201\221\241\010#B\261\301\025R\321\360$3br\202\t\n\026\027\030\031\032%&\'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz\203\204\205\206\207\210\211\212\222\223\224\225\226\227\230\231\232\242\243\244\245\246\247\250\251\252\262\263\264\265\266\267\270\271\272\302\303\304\305\306\307\310\311\312\322\323\324\325\326\327\330\331\332\341\342\343\344\345\346\347\350\351\352\361\362\363\364\365\366\367\370\371\372\377\332\000\010\001\001\000\000?\000\364kU\301\025\250\251\362\364\250\246\217\003\"\262\265+3,$\257\336\025\303\352\221<n\331\025\207$\305I\252\322\266\376\224\266\361g9\251^\337 \326u\314X\317\025BT\305Ut\315A$dUw\214\032\2552\201\232\317\226<\324K\006\343R\262yC\025^J\200\236i\205\360*\t\034\346\2423\025\247\305v\001\346\255\213\350\210\3069\252\3271$\312H~+/\354\013#\036x\252\327\032b\201\305d\\X\225\'\212\257\366S\236\225<Pc\265^\206,\201\305[\216\034v\247\2102zT\251k\354*C\000\\\034\200i\336V\356\246\234\260\242\373\323\360\202\201\203\332\245E\343\356\324\201sS\304\206\256D\265r$\315\\\2051\212\322\267L\342\264\355\223\245j[\'N+V\326#\305j\333\303\232\277\004aj\374+\300\253\260\2475\245m\036{V\204\021\364\253\360E\223W\221\002\212\224H\007\003\255=rju^\225f(\306j\322\034\n\261\021\300\2572\212\337kt\255\004\213)Lx\2069\252\262\3046\234\327)\342-00.\242\270\rJ\003\033\034V|,L\2305\253\024_(8\247\225\342\250]F9\254\251\323\223UY0j\031FsT\344\340\325I\224\232\252\361\323\025pj)>bj\274\235j\"\225\023.j\'J\255\"b\241\332i\333O\275\014\030\214v\246,n:S\374\206#\346\351Q\266\232\034f\252M\247\210\315D\226\240\036\225j+\\\343\212\273\035\236\006H\251\004*\203\232B@\372T,\241\333\030\251\0220\275:\324\202\"z\323\276\3168\315H\226\340t\025\'\227\212r\307\355S\307\035Y\215*\344)W\241L\326\225\274}+R\332,\342\265\255\242\351Z\326\261\364\255(W\025v$\311\253\360\245^\202<\326\255\254U\243\024x\255\010!\3434\255\220)c\025<g\236j\312\034\325\225\312\201SE\310\025z\336=\304W\237\244xaW\243\203\345\250f\267\307j\251,D\251\000v\254-F\022\312w\016+\205\326\264\322Y\210\034\032\345\346\2670\313\322\264\255\237*3RH=*\205\310\316k>HsT\346\217\025RE\252\262&j\274\221\361U\244J\201\227\025\021Nj\027\213\346\246\274x\025\003.j6\216\241h\263\332\220[R\233l\036\224\236HS\310\246\277\3128\025Y\335\311\246\355\220\2163@\267y:\212\232;\000O5i X\307\002\207\034{Ui2\307\247\024\302\245\2158ER\244]\352eQO\300\240\223\332\200\rH\2435b%&\255\305\035]\206:\277o\027J\322\266\217\245kZ\307\322\265 J\324\266\\b\264\"LU\330R\257\300\235+J\336>\225\251n\230\305iC\037J\277\022\034TR\360i\022\247\215rj\334I\216je\311\253\226\321w\253\326\340y\230\354+\2100\205\025<+\225\346\206L\366\252rC\265\353;R\264\022D\330\256V{\0213\225\"\271-gM\t3`Vtq\030\316*V^*\234\361\325W\217\212\245:U\t\223\025U\326\241d\315V\222:\256\321\344\323L<Tm\rC$F\2411`\323Z,\323<\201OX\200\244u\013U_\222j2\001\342\232\320\016\242\244\216<q\266\246[s\234\342\246\362}\2526\213\322\2411\226b)\217\0268\250\304C=E?b\216\364\252\r=V\236\022\224&MH\"\247\252b\254\301\036j\374Qt\253qG\355W\340\216\264m\343\351Z\226\353\322\264\355\2278\255Kh\372V\224Q\364\253\260\307\322\257\300\225\245o\035i@\235+F\001\212\264e\302\032\252N\346\251PU\273q\315\\\215x4\364Nj\354|`\n\271l\2375rf\035\335\252D\207\002\221\243#5Vhrj\205\354x\214\375+\2350\376\377\000\247Z\300\361\005\220V,\005s2F\001\250\236\253J\271Z\247(\340\325\031\2275JX\311\252\357\017\265D\320\324\022EU\236>i\004y\024\206*\212Hj\026\202\230`\036\225\033C\212\215\206*\274\2715]\224\323Dd\232\2368\361S\004U\344\001\232x>\224\356\324\233=\252\027\002\253<E\211\346\232 >\242\234\261\001\336\245\010\007AR\010\267\n_\'\006\234\"\247\004\342\236\253\315Z\2119\253\320\246j\3641\325\350c\253\360\'J\321\267NEkZ\307\322\265\355\242\300\255\030S\245\\\211*\365\272t\255\030\026\264m\323\212\273\030\251\266\232a\213i\366\251\021j\314\\U\270\333\"\247\215y\253\260\247AZ\021 E\256h\307\203\322\227\313\305F\351\232\255\"\216EQ\271@\312A\254\223g\227-\216+\234\327\302\374\303\275q\227\010C\032\252\353P\262f\253\313\025T\226!T\344\214f\2421\003\3051\355\210\0358\252\322\333\342\252I\007\265C\345\343\265\006<\323Z>:TF:c&\007J\202D\252\322G\315B\311\315D\311\232h\214-!;i\276i\247\254\2075\"\271\'\232\2306EF\352\246\242h\2050\303\223\355R\010\000\003&\244H\207\245N\260\344b\234a\357M\300\3161H\0317c<\324\2019\253P\'\025~\030\352\354KW\241N\225\241\004}+J\336*\327\264\217\245k\300\230\002\257B\225n$\311\025~\024\351W\340^+B\020B\325\310\306\005N\2435!M\313\3151W\232\2361V#\253\260.H\255\033x\261\311\025,\262\210\224\223X\354\202\243+\212\257r\3425\'\275c\\j$1\025Y\356\314\304\016\324\267\nV\335\210\353\\f\256\014\214\331\256r\342\016O\025M\355\352\007\207mS\234c5FQ\232\251\"\363Qt5$L\t\301\351M\226\333\232\245-\276\017\"\253I\005F#\2441S\032.j\'\213\332\253\274X5ZD\305Vu\250Y)\245i<\260i\246!\351H#\307j\221@5*\305\221\322\242\221\n\236)\270&\236\253\236\265\"\302\t\251\226\020\275\351\330\024\206@)\204\356\2464\033\307Nj[pq\203\332\257\302\230\253\360.qW\242J\275\004u\245o\035i\333G\310\255{X\372V\254)\300\253\261\'J\273\014uv$\253\321G\200*\354}*\302\032\262\234\342\245\'\ni\211\311\251\320U\270c\310\255\013e\n9\253Ot\220&I\256wU\326\301$\003\305i\021\355QHv\212\305\324\246<\363X\2236sL\265\313\313\307\255j\\\200!\301\364\256CS\200nb+\002\342\016zU9!\305Q\270L\003YW\000\344\325GZ\204\307\272\230\366\274Ur\205\032\255\306<\330\360z\324\023AT\345\203\025\\\305\203Jc\310\250]1P\272\324\022&j\254\251U^<\232\211\2424\321\016M/\223\212C\027\265#E\351J\220`\346\245~\007\025\003\014\3474\201A\247\000\253\326\236\256\007J\032QP4\244\236)S&\254\305\037\255K\262\227\312\303\002\005]\267]\325\243\004x\305_\206>\225~\010\353J\332>\225\251m\027J\325\265\217\002\264\241L\342\264!\217\245]\211*\344+\203\322\255/\025f3V\023\255]\267N9\242V\031\305$b\254\302\233\230\n\275\275bST\356u\244\207 \036k\"\357]iA\371\270\254\207\270k\247\300\351^\200\334T\023\014\212\302\324\0279\254\211\206T\325;Y\374\253\201\365\255+\313\240\3109\355X7\2046k\"\342,\232\317\271\213\031\254\273\204%MeL\204\223\305Wx\211\355Q\024\307Zk\034\216*\273BX\364\251 \213k\n\263,\001\205S\232\014\366\252\222[\325f\210\212\211\343&\2411z\324\022GU\244\216\253\264\\\324f:aJLb\232E&3Mw\333\322\241g&\2234\322\376\224\207=I\246\357\307Jir\324\344\004\325\210\227\025i\006j`\270\024\346R@\253\326\361\025q\221\332\265!\217\212\273\022U\350\022\264\355\223\247\025\251l\235+R\004\340V\214\013\322\257\305\200*\304G&\256\304sV\200\351S\306*\324k\315]O\221*\022w5O\032\346\255\303\204\035*\275\357\2312\220\274\n\346u\017\335d\026\311\254\2375\246}\271\342\265\254\341\n\242\275\t\327\216j\274\300`\232\347\365\"7\034V4\207\250\254\347R%\310\245\236B03U%\344U9#$\325+\210\262\rd\334\302A<U\tc\000\325w\214\036\325Y\342\250\305\256{T\313g\221\322\232\366\333\017JU^9\246\313n\010\310\252r\333w\305T\222\037j\253$X\250\035*\274\211UdNj\022\225\013\305Q\024\246\025\2460\3053\006\221\3235\021\216\230Tf\224G\236\325\034\221\234\324d\021@\344\325\210\322\247T\251\227\212\231~b\005_Km\312\244v\253p\214\234\021\203W\355\322\257C\035_\202>\225\243n\230\255\033q\322\264\255\372V\204&\256\3043W!J\277\nT\340b\246\214b\257@\235\315I#\205\030\024\310\271<\325\264`\000\251\343\351L\271R\352@<W!\254Db\221\263Y\266*\014\204\326\344g\n+\273\232`\213\223YWw\304\251\002\261.\244.y\254\331s\232\217g\004\342\252M\227|\324f:\212Hj\244\320\325\t\355\263\332\263\347\260\335\332\251=\231^\325\030\263\317Zx\264\013\332\234\266\376\325\014\320\347\265Sx\212\032r\234\216E6H\003\014\212\316\236\014\023T\244\217\256EU\226<Ui#\252\357\025@\351\203P\262\324.\2315\033G\315F\321\323LT\236]D\353\216\324\213\016\343\322\246H0:P\361\001\324T-\002\223\322\243\362\006zT\211\035YH\370\243g5,HCsZ\326\334\212\266\221\347\232\273o\021\355Zv\320\372\212\273\032b\256\300\235+F\010\363\212\320\206<c\212\275\002\325\370W\245_\201p*\354+\220*S\306*XFM\\C\201\327\212\215\337\232|g\212\235_\037Z\224M\214sV\025\267/5\307\370\226`\2635fi\247q\315k\251\300\256\326\364\361\214V\\\261\3475J\342\016\017\025\0040+1\014).-\320&\024Vs\333\014\361L6\274TRE\212\316\225w1\250d\213\"\252\274^\325Z[p{U\177\263b\221\241\3050\307Q\311\020\305S\232*\205c\245\331\212\253s\001\344\343\212\315\232\032\251,5U\341\252\362E\216\325U\342\346\241h\252#\036j&\217\024\337/&\217(\032O\'5\033A\223OX\000\035)J\340p*\t\025\217j\213\006\235\2634\345\216\246U S\225=\252d\217\025f\006\332\325\253\010\016\005]\201\002\340\346\264a \2605z3\270\201Z\020E\323\212\320\2011W\342\034U\330\027=E_\206:\277\022\014U\200\333qN\r\232\261\027\002\244i0)\213\2275:\220\243\255!\234g\002\234\262d\325\364p\261g\332\274\373\304\327\233\356\230\003\337\025&\222\270\214\032\324\335\201^\203u\006\345\254\251\220\253c\025\033[oZ\256\366\376Y&\252\3123U\314\\\323\036<\n\245p\234\034Vd\213\2065\033.EV\2219\250^<\212\207\313\3155\242\250\236*\205\343\342\252\315\006j\017$\203A\212\231$[\220\212\314\270\213\007\245Q\226\"\rT\221*\254\211\232\257$DT-\036GJ\201\241\301\246<Y\246y^\324\242*Q\036i<\220)\246?JiB)\217\020\"\240h9\243\313\247\254x\247\343\332\234\243\0250^)\006Q\205i\331\313\221\212\275\0319\353ZV\314N+V\331s\365\255[h\216\006kN\010\272U\370m\211\253\260\301\212\263\022\340\325\305`\242\225N\343S\3061\212\233xQH\244\271\366\247\2311\300\246\263\034SQ\262j\304G,\005K\250\334\375\236\321\317\240\2571\275\2727Z\207\'\275t\226\003lKV\235\370\257St\310\305S\226\330\022MUx\266\346\251\314\271\006\251<Y\250\332,Uy\023\002\263\356T\214\326t\211\223Q\024\250dJ\201\222\242+\201L+\232B\231\2464<Uw\202\240h*\'\217\002\241#\035j\245\325\270q\220+:Xq\301\252\222\333\372U7\207\223\305W\222\032\201\242\305F\321\323\014\\SL<Ry|S\n`\323v\022i|\254\323$@*\002\231\2462\232hZ\024\032p\031\251\022:\234\'\024y;\215\\\266\213eh@\2315\253k\027J\326\201q\212\327\265#\002\265 \350\t\034U\350\207<U\265\344T\200\343\025(9\251\222\247\007\002\201\2265)`\274f\233\270S]\213\nT\342\254B\330aU<K?\227d\343=\253\316\354\301\226\370\237z\353-\316\324\002\236\362q^\304c\340\232\2557CY\323\276\rT\177\230\324O\035D\321dU)\220\203\355T\346\2135\237,8&\253\274x\252\322%BS\232G\217\212\204\307\311\244\362\30144x\025\013%B\361\325y#\252S/5\020\364=*\235\324=qT]1PI\0305^HsU\244\207\025Y\343\3054GMx\350\021dTo\0253g4\244\014T&\"\306\232b\307jF\267\014*1m\223\322\244\373\'\035)\005\267=*U\267#\265?\311\"\225\027\0168\253\022\002\000\305hX\256G5\253n\274\326\244\030\300\255\013sZ\226\217\221\203ZQ0\307\025b2j|c\024\365j\231\\\001O\017A\227\024\320\344\367\251\024\323\305*\365\2530p\300\232\303\361d\377\000\350\2543\326\271M\036\334\227.}k\242S\265i\222I\305{\214\313\201\355Tf\\\203TZ\330\312\307\322\242\222\323g#\245B\311\333\025\023G\305T\236,\325\031\"\317\326\251\315\016\t\310\252r\306*\263\303\232\217\310\0305\033\305P\274u\037\226i\031}j&\030\250\331sU\246\\\n\242\351\271\2529\"\305F\361\007\\U\031\255\261\236*\224\260\025\250\0362*\254\251U\231\t=)\004t\326\212\220GM1d\364\250\332\014\036\224\317\'\232_#\035\251\206\014\232C\016)\313\016;S\304Y\251V\337\245<[\324o\027j`\203\006\246D\316\001\253\326\340(\342\257@\374\326\225\271\311\025\247n+F\016\rh\302sW \353S1\346\221I\251\320\014sJ\322\001\300\244\311jz\212\231*P2(\003\232\265\n\355R\306\271O\023\311\346\270A\3275Z\306\330C\030\342\2553b\253\313%{\364\203p#\025Jh\360:REm\2662\306\241t\007 \212\241<[\033\332\240#5^d\340\326l\347kUY\335XVt\274\232\205\2054\257\024\307\300\025\003\251=\251\236_\2555\320\n\205\325}*&LT\022\302XU)\"\301\250$Z\256\303a\317jl\256\244r*\253$r\034Uy\25508\2523A\216\325M\243\346\233\263\024\030\351\273(\n\0055\320\212h\217\'\245?\312\004t\246\371#\322\232\320sA\213\002\220&*E^jP\234Tm\016M0\306E7\033MY\204\346\256FpsZ\226l\016+^\337\240\253\261\036kF\334p*\374gh\247\026\311\247\242\223SllR\004&\236\253R\252\323\324`\324\312x\247D\233\332\226\372\345m-\3131\300\002\270\362\306\366\351\244=3\305\\\332\025j\t_\025NY:\327\321l1Q6\017Zk\020EV\231\007QTn\327r\361Y\341\271\250\245\3475\237w\036A5\225\"\035\325\013\307Q2b\232W\265W\222>i\245\016*7 qP\236M!Z\211\322\232\303+U$\217$\3259\343\346\253:dUi#\315Vx0sM\335\216*\275\307\315T\036,\265\'\225M1\342\230W\024\302\274\323\302\356\030\247\254 u\305!P\275\252&\036\224\300\255\232\177\226Z\217 \323\204X\355R\242f\235\345\324O\030\250\274\202\355\305hZX\372\212\261%\221#\345\247\333\306\360\343\"\265\255e\316\005mZ\307\225\004\326\204k\212\230\032r\234\232\263\022\346\254(\245\013\315(^i\312*EJ\224-N\n\333\304Y\215r:\356\252o\'\362\220\374\243\212KH\274\270\305>V\300\2523=T\221\353\351R2\265\003\n\211\352\031:UY\027\"\262\347B\216qU\235\252\264\247p\252rE\223\232\257$X\252\362-VpEFy4\245F*\254\350j%\031\244\"\202\274Uy8\351U\244\340\364\250f\217p\315Sd\306j\273\255W\220pj\253\2569\252\362sP\025\246\340Pc\342\242x\363Q\030\351\270\"\227\223\336\200\t\357R\"/z\n.p*h\342\315H\321\252\255D\313B\2559\206\321U%\223-\212\275a\006\341\222+IT(\300\251\241\031#5u`W\035*hl@l\212\324\201\n\200*\334b\246U\315<&*x\315X^i\342\227\024\364\\\324\310\225<Q\345\262z\n\307\361\026\242!\205\221O5\312YFe\224\310\336\265\254\033\013PM%R\225\352\244\257_M\257+Q\270\357Q:\344TE3QI\027\312Mf\317\026X\325\013\230{\212\244\311Q:\325iV\252H\265^A\305T|\203J\t\3051\206\356*=\241M!Nhe\340\324\r\020&\240\236 G\025_g\006\252L\274\325I\023\232\253\"\363U\247\\\014\n\250T\346\232R\233\345\214\322\225\030\250\212sLt\250\366\342\203\026zS<\262\206\234G\031\024\304\310j\264\206\234X\236)6\212\221c\3152h\370\252\321\332\227\223\245k\303\030\2121\212\225Fj\334)\305\\\205qW\"lU\250\234\325\270\316EN\242\245Q\232x\030\247\253b\244W\251S\346\253\021\245XT\247O\"\333\302I\364\256\017Y\2727W%A\3434\353h\374\264\025+>\005U\232J\245+\325Y\036\276\237\211\3621N<\212f\332\215\261\232c\214\214U)\342\352k6\344\016k=\323\232\202E\300\252\222\325g\036\265\004\200\036\225RE\301\250\363\223N\t\336\243u\311\241R\226H\276Z\213\312\312\325y\027oZ\254\352\0005Fe\346\252:\363Q\030\273\325Ib\313Uw\213\232\210\305Hc\342\232\313\216*2\274\3224y\250\314$Rl\"\206\\\212\217n\0161\3055\243\347\"\234\271\024\361\232\221jX\305,\213\221D\013\203\232\262\274\232\235\0235n\010O\341W\343@\005N\252\017J\2361\355V\243\315Y\216\254(\247\343\345\246\201R\304\225r(\267t\025n86\214\232e\305\302\333!c\332\271]k_2\202\250p+\032\325\014\217\275\273\325\360v\212\206Ij\234\262\325I$\252\316\371\257\250a|U\220\271\002\224\305P\313\031\007\212\213a\357U\256\027\031\025\223t\2705A\333\234Ui\252\243\216j\264\342\253\212\257*\346\240\010wT\3418\246\262f\232\006\016)\3542\264\302\237\'\025Rx\370\252r!\305T\222<\325Yc\250\200\002\232\360\007\344Uim\361\332\253\264X\250\2311P\262\346\243#\006\203\300\3157w\265\030\006\232R\220E\236\324\341nOjSm\216\324\236V(\331\212r\203JsOE\2531-Z\215q\212\262\016\0279\2536\3409\373\325r4\332x9\025:\361\332\246F\253\0216j\324})wv\240\r\315V\241Z\275\033,k\232sM\205\311\254]gS\215\020\241nH\256,\223spq\367sZp\250E\024\347n*\234\257\326\252J\365VF\315Wc_P\333\275_\201\2676*\303.\026\240\316sQ\311\323\212\2478\310\254\273\264\316k2X\260j\274\261\232\251\"\342\251\315\235\325]\210\006\232\300\023L*\001\351E4\322\020\r!\006\234\243\"\253\\%S\2310*\243\255W\221}\252\263\305\3153\004R\200\030|\324\307\266SU\336\320\036\206\251\313\006\322EE\366ni\216\233x\305G\267\332\234#\245\021{S\326\017J\220E\266\206\\\324f:i\216\223\3134\010\363R,u2.*t8\342\247A\232\231S\322\254G#\307\336\247I\331\217\265Y\215\315Z\213\255Z\017\265i\233\31154F\256D\325)\230wlb\252\336_*D\3047A\\6\245y%\325\301\000\236MY\262\267\330\240\232\270x\025\014\217\305S\225\372\325I\036\253\310\365]\236\276\245\265\001\216;\326\275\255\270^M-\326\024qU#<\322\310\274UIW\"\263\256W \325\027\217#\245@\361qT\247\207\031\342\250O\016F{\325)\"\357Q\200i\010\246\023IJ\022\227a\315<DqPL\225U\343\315U\226\032\257$\'\322\240h\252\027\206\230c\307jc\014TL0*\244\253\223M\021\346\232\360g\265Dm\361\316)\313\017\265<A\203O\020\342\232\311\212i\000\236h1\361I\345\323LT\242:p\216\234\251\212\221\005N\213V\023\212\230sR\240\251\342\352*\344})\356\324\253\3235f\025\342\254y\201ET\272\270\371I\007\240\256J\362\376ied\334qRX\333/V\344\326\220@\243\212\212V\305R\232LU)f\252r\317U\236bM@\322\232\372\276\000c\270\307\275o\304\001@j\033\254\032\254\027\024\270\310\252\363-g\314\233\211\252rG\203P2g\265W\226,\212\247,\030\252R\301\223\322\253\233|v\250\236,\017z\215-Kv\245\3731\317J\221m\317\245<[\373S\314\031\025Zh0\rRx\261P\274C5\013\303\236\325ZHqP4U\013\305Q\230\252\'\203\212\253$84\325\217\232{Dq\322\243\331\317Jr\303\336\234b\310\351M*\026\242\220g\245Fc\346\221\205=W\"\223fMI\345\001I\266\214{S\225qR\251\301\251T\324\313\322\246N\265b>\242\255\241\300\245\0371\2517\000jE\220\372\361L\226\343nGz\243;3\0023\301\254\351\264\263\"o\217\357\372Ut\221\255\237d\203\004U\350\356\003\257ZI\030\021\223T\346e\306\rTdS\036GZ\256\326\361\270<\363P\010\241\214\234\234\232\205m\320\271,\303\025\365|p3M\234w\255`\214\221\363U\233.\324\241;SJ\342\240\224pj\214\243\004\232\253\"\344\324\014\2305\034\261\014f\251\315\0275T\303\223\322\217\263\006\355Q5\220\317J>\314\024t\246\213aN\026\303\322\227\354\374\036*\031##\240\252\322FNsT\344\213\255@`\366\2464>\325^H*\263\301\216\325\013A\236\324\306\267>\225\033C\355P\265\266\343\322\243\373)\035\251\337g\2465\2679\3057\312\301\245l*\364\252\2162i\23309\2462\223\364\250\334`S\220ejD\\\014\320M!S\326\212)\300\324\250jx\352\302\n\260\212ju8\024n \322\206$\323\374\315\265Q\245-!$\367\244g\315\"M\260\361TuT\023\215\353\326\263\240\271h\316\323WRm\302\243\231C\203TfV\307\007\212\246\312\312O=j\264\210s\232\205\213\000y\257\266R\331#9\3075\035\303\002\010\025X\000\275z\323X\223\320Rb\253\316+>n\rC\214\323\036:\211\227\"\240hKTOk\337\024,\030\355L\226,t\025\001\204\223J!\307Zi\3004\354\0028\025\023\302s\232\255,%\217J\253-\261\035\252\023\006{Too\307J\255$<Uv\2075\021\267\346\217#=\251\215m\355Q\0301\324SV\025f\246\315\n\216\225U\224\001P:\372T,\204\323\014X\024\306N2j\t8\250[\232tc\345\251\025i\305\007jc)\246\367\242\234\2435*\n\261\030\251\322\255G\322\236\016)Y\205\"\261&\243\272\227bqU\026J\003\232G\223\025\013>\352\243y\016#\336\274\021Q\332\317\274u\344U\242\341\207\275W~\2705Z@9\252\262.*\007Q_gK1\316*6#\0315\031~i\233\362i\035\2603Uf|\232\2457$\324K\326\234\313Q2S\243\207#\221J\320\202:S~\313\355Q\313m\201\315A\366lv\250\336\003\236\225\017\330\232F\310\025:Z\004P1\315+\332\344t\250\032\320)\316*\254\266\345\217J\205\355\266\366\252\362A\355Uf\267\366\252\255o\315\002\330c\2455\240\307J\205\342\307Z\2538\333\320U`0I\246\311\315Wd\315F\321`sQ0\301\340TN\274\344\324\017U\334f\230P\001B\016\325\"\214S\261H\303\"\240a\203E={T\212qVb\346\254 \251\224\342\235\273\336\232\016MH8\025^\344\215\207q\305VVQH\322\001P<\205\270\250w\025j\235\"\373J\262\237J\307\270\211\254\2561\330\325\270\337r\202\r\017\353\351Ud\034\325w\252\322\003\236+\354\327LT\017Q3b\233\277\232I\033\"\2539\353U\244\025\032\203\232\223\034Sv\325\250\242\033jO$\034T\236R\205\004\n\2514`\234\342\252\260\246\210\267\034\323\304a\0050&\343N\021\322\230\203\014\021U\344\266\003\265C%\236\364\310\353Y\223\300T\221\212\256\321d`\212\200\333\363L1`\3242&\016*\274\340\021\305Q\2253U\332:a\212\243x\373\001P<x\353P\276\005V\220\346\253\270\250\331q\326\241q\232`m\246\247\034\214\321\232\031\263P\270\315 \024\360)\303\255M\023b\254\243\202*P\334R\027\311\3059Z\2442\000\265\223\251NY\360\017\025U%oZ\2247\255\033\261Q\006\335 \025j\t|\251A\252\332\334f_\234\016\005U\262\223)\217J\260\365ZA\232\255 \252\357_gJx\342\251\271\305@\315L\335\315!l\324m\315@\342\230\027\275H\027\2126\324\2508\251\220\340\363Ns\305C&\000\346\253\030\367\032xM\243\336\230P\277\322\236\261`R\230\370\241b\246I\026EA\202\231\252\263\302$\347\034\325\023\tW\301\025\024\366\340\036\005Tx\212\202j\214\271$\325gL\324-\026MF\320\324N\200\003\353U\234`qU%\252\317\315B\302\2431\343\223P\312\271<T\016\206\241a\203O\216\\qO,\017Ji\246\322)\311\247\344R\203\212\2219\251\2235&\374\n\003qO\rP\3136\321\214\326e\324\273\232\233\031\315J\017\024\307j-\243,K\366\0253R\337J\005\2418\311\305a\351\363\2370\203Z\207\221P\310*\254\202\253\272\327\331\005\362*\274\206\253\275F\005%\030\315F\351LU\251Q2)D|\323\266\323\202\232\221W5\014\321\222i\022#\216\224\246,\323\3048\024ytyy4\361\026\005G\"\201\306*\263\307\315W\222?j\253\"\002zUy\023\0315B\344\026\'\212\2414[~\246\240h\2526@3\232\256\3500sU\245QT\344\034\325I\252\003\021\306\177\235&\000\3543PJ\334\342\240`j\027\031\250]sP\260\301\247\306\334\323\363McM^\264\3409\247\036)\361\036j\300\340R\203\201\357M\337J\222d\232\253>I$U\026\313=H\243\002\244\035)\222t\2530ql\007\2550\2659\343\363-\310\256o\230/1\357[h\333\220TRUw\025\003\327\327\241\363Mnj2\264\306\\SqN\013\232k%4ER*b\236\0234\005\247\204\311\366\251\0262\0057\312\311\247\254\030\024\236V\r#-&\314\323\322*VL\n\2470\3475]\375\252\t\016\005U\224\344f\253?|\325YS\275R\2252j\273\256*\273\214U9\217Z\247#Uw\346\253J\274\346\240\224\261\342\242\331\305FR\242u\250]j\027Z\210\307\232M\230\2444\231\315 8\251R\225\371\241\016*\312\267\002\202\331\246\223MC\203R`~uJx66EF\006i\300P\353\221R\331\270*c?\2059\342!\272T\207\344\217\232\345u\'\002\377\000\217Z\327\2669\210P\342\253\270\252\3569\257\256V\237\2126\323$N*0\234\324\311\036iLT\276M\'\227N\362\361@\213\234\324\251\025+\032UNjB\274S\0318\246\024\3074*f\246H\360*9\227\212\247*\325)\001C\305V\220\361U\\\021\315A(;j\244\204\325w \347\216j\264\247\031\2522\232\251)\252\2563P:\236\325\014\213\264d\365\252\354\2715\023\361L\0035\024\234\n\255!\250\\\3233\315!\3051\210\025\037V\342\224\361O\007\201N\310\301\244\007\025\"\276)\333\251\001\311\247\001\315:\231\"\357\252\357\013\'=\251\026\236W\212\210\251\007\"\246[\246\003\004f\202\346^+\231\324\223m\3663\336\266m\007\356\227\351O\220Ui\005W\220W\327@S\260i\312\271\024\024\342\220C\315K\034U0\213\035\251\336P\364\246\2309\246<X\251\022\036\006hu\300\300\246$$\232~\334\032p^)\nz\323\n\322\001\203V\021r\265\004\253T\245\035j\254\213\232\247s\204\030\025\2315\306\322y\252\357rXu\250\014\200u\351P\310U\201\332j\234\234\234Uk\201\221\201\320U6\031\250\035sQ\272\343\212\255*sP2\342\240u\246\036\005A/J\247!\346\241c\232i8\240d\324l)\"\031jYW\024\300qO\317\024\224\345j\221Z\236\005<\nq_\226\220.)veMU\331\203N\0034\025\246\025\305>!\303\037A\\\315\351\363/s\357[v\243\021\001Nq\305V\220Uy\005}q\013\006Q\353R\201OE\247\205\315H\221\324\321\240\002\237\264\032Q\036()G\224\r\002>i\255\026\346\247\244T\217\0074\242,\no\223\232\0144\202\000\0175&\300\023\201Uf^\rR\225sU\'\033\006{\326=\365\306\300Gz\305\232B\306\230\217\270\342\235\"n\\Uq\023+SfL\017qT\2465I\371lS\034mZ\254\365\023\214\324.;\324\022\014Ui\rU\225\252\253\232\256\357L\017\223S\203\201Q9\311\241X!\247HC.j\005\344\324\203\245%\003\232\231\005J\2435\"\216)\3523N\331\2326b\252\312\010\'\216)\213\326\236W\212k-<\201\025\244\217\355\\\241\375\345\347\343[\360\014 \241\305W\220UiE}a\021\3323V\242`\342\254\"\324\210\27052-<.x\251\002b\235\262\200\224\341\0352B\000\367\244A\237\255N\221\323\314`\216\224\236I4\215\036\007Jh\216\227\313\024\322\200U)\323\031\252\315\027sY\227\331\000\342\271\353\303\363sY\222\202\347\002\233\024D5]H3\311\250\345\217\214\201\322\263\356\037\004\3257\001\201\365\252R/\226\331\246Hr\265Q\316\rF\307\025\013\260\034\325I\237\255T\221\372\325I$\252\322=@\346\231\270\203\305?q#&\220\277\2457~O4\374\361H\274sO\316x\242\220}\352\260\235*U\353R\252\361OQ\212\220-?m\006\020\352F*\213\305\345\312E8\257\024\315\2318\246j\315\344\330\021\353\\\316\236\236e\306k\240D\302\323d\025^J\253%}_\037\335\002\244\217(\302\264b\033\224\032\231\026\245\013\201OU\301\247\205\247\201\201JF)\013\201\336\242r\035\200\024D>n\265i\005N\253\232\224 \305\r\010#\221P4;M!J\206L\n\251\"n\346\252Lk:h|\314\237J\310\271\261\363\244\300\351U\245\323\204}\005W6\301\017JRB\251\252\3228\000\326&\241.\t\305g}\250\347\255#\310\034sP\277\003\203Udb\r@\357U\345\227\212\251$\231\252\262>j\263\232\256\355\212\205\236\242-\316E8I\3074\3230\024\3230\025$2\0313S`b\233\273\232\221A4\241~j\263\032\346\245\013\212\221\005H\243\232\225\026\244\333NU\252w1\021.i\241ic\213-\232\317\361\021\305\260Z\307\322c\344\234V\332\216*9\005U\224UW\025\365|C\345\025*\214\325\353f\371@5r5\315N\251N\tN\333\216\224\247\345\031\250\032NsL\00414\233jx\0275az\324\241\252\344\021\344S\335\000\025\003\256j\t8\025^@\000\346\251\314\334qT\'$\232\2451<\212\257\225RsU\256\034\023Y\267\017\202j\243\275S\232N\rd\336\374\300\326\035\314\206&\251a\225YG\275>@;UYXt\252Rw\301\252s1S\315S\222J\257$\325ZI\352\273\313\232\205\244\246\t9\247\2113M,*7j\226\336L\032\262_\"\204\031j\274\2106f\201\036*x\227\212\224\216)\310\271\251\221j`\234S\266\323\224b\241\270\210\263g\2650F1\322\244\216\034)5\315k\322\231&(\017\002\2156\337lc\212\321\333\201PJ\005U\222\252\311_YF\274T\221\360\325b\036\034V\234\013\270f\254*\342\235\264\032xN*\033\236\000\003\275V+\270\324\220C\226\347\245H\360\200\331\355OE\000qN^\2652/5\243\007\013\355O|b\252\277z\2473sPH\246@Eg\260`\307\'\245W\232M\300\340`\325\t\006\320Mg\317&\033\223U%\227=\353>w\3115RG\342\252L\325\235vN\rs\267\357\311\311\246\330L\035qVe\233o\004\361T\345\234\023U\244\227\323\245U\222@\374\032\202H\211\025Jd#5FL\202j\0268\025\003\277\2750I\357O\022R\227\250\335\351\366\317\226\346\256\251\315X\205y\253\240\035\242\244U\315N\251O\362\363R,x\025\"\256*U\024\360\264\241(\331\221\212`\207,\0057P\220Z@y\344\327 \352n\256I>\265\255\004;\020T\215\300\252\322\216*\244\243\025VN+\353\270\"\014\277\2050\256\032\247\205y\255+s\201\322\246/\223ONjU\\\3247\003$\n\2164\344\017Z\263\267b\361L<\212p_\226\234\242\247E\342\255\302H\\S\234\346\253\312j\224\207s\023H\000 \372\326|\321\376\360\346\251\334\021\316*\204\337v\262/\030n\342\250\310\365JV$\325f>\265\014\2046j\205\322eMs:\234$\022EeE;C\'\025jK\35719\034\32531f\306ie\220\005\306j\214\263\020x5\021\274e\352i\215u\274r*\244\254\rBW\"\253I\031\315W`T\320\262S\203\323X\346\245\200\022EhE\326\264-\343\334Eh\254C\035)Bm\355R \366\251\027\351R\016i\352\225\"\245H\027\024\273E(\\\324\201DHY\253\231\326\257\276\321)E<\n\202\312\323\003q\034\232\275\263\002\242z\255%U\222\252\313_`\306\230@E\t\016\342ML\261m\251\221\212\324\201\363V\242*\027\2558\312\005Fr\3074\350\323\346\315L\304`\323\021h<\234S\224sVPqS\'\024\326j\257+\366\252\262\032\205\244\333\306x5ZW\316qY\327.9\025\233q/j\314\2709\346\251Jj\224\307\004\232\2454\300\016\265E\3569<\324\023Lv\232\310\275\231\030\020G5\217\265<\323\351E\302\250N8\254\331d\020\234\346\252\313u\236\206\253=\306\017Z\212K\235\325\017\332\0055\247\rL3c\275 \2349\344\322O\027\313\221T\317\006\236\274\323\200\311\253\366\321\201\036j\355\265\271|\034V\275\265\266\321\315X\013\201N\013\232r\256O\002\244U\247\252\347\212\235\000\305<S\216):\232\232$\301\311\351Tu\253\261\034%A\344\3275\004\006iw\036\225\253\034AT\n\034Uy*\254\225VNj\254\235k\354\270\320yt\210\2705(\\\323\302Q\263\024\354\020)T\325\204\306\332\221@\002\203\311\240\214RT\221\255N\202\236N\321U\344\227\002\252\2312\335j\031\0335\003e\217\265T\236M\231\002\262\347\227\336\263n%\311\252R\266j\254\344*\326]\315\300\031\025\221q9\311\346\250IpA\340\323M\313\021\203Y\327YsT\035\002\234\346\253\31778\'\212\315\273\031\034\034\326y$\032\2573\034\361P\031\010\353P\274\234\320\257\307Z\212Y\210\3434\310\335\263\232\273\035\306W\rLh\267\034\212U\214\203R\010\316E^\267\\\341Em\332F\021\006j\320|S\225\267t\251\200\340\n\225T\366\251V\022\307\232_+kS\302\342\226\220\223\232\226$\344\023Ks\'\227\0315\314\336\312\3273\021V-m\302(\342\254\036\005C!\252\322\032\251!\252\262\032\255%}\235\032\356l\n\225S\r\322\236\022\236\022\227g\265\036]\002:\221F0)\304\222)a\034\363J\347\232@9\251\320T\243\201L\221\361T\247\226\251\264\23756Yv\255Dn\206\323\3175\233s6\342k.\342\\\032\317\232QT\245\270\002\252Or\031q\236k\032\351\311c\212\316}\362\266\320)\255\007\226\016z\324%\327\030\305W\235\227\006\261oe\303ak:x\2163\277\232\317\220\221\234\232\2534\270\357Ud\227\025N[\214f\252\275\327\275 \272\317zE\223{rj\302q\336\236I\355SAq\261\260E\\I\021\271\247\227^\325=\233\342J\331\205\363S\200MX\2019\253(\233\232\256\"\010\307L\221U&\2721\313\317\002\245K\270\344\035Fi\342E\'\255<\221\212\217\316U>\364\341)&\240\275\2371\355\254\350`\313\226=j\342\250\013Q\310j\264\215U\2445VCUd5]\315}\251\004{NML\007\036\346\236\250jEZv\312]\276\324m\366\250\317\006\216I\247&Fh\'&\234\242\246Zs6\005U\232^\265BisU\267\374\325R\356\353\031\252\3130a\326\243\220\361Yw\215\2675\211ws\2635\225%\337\230\345A4\203\246I\250$\300\311\2523\334\210\363\267\257\255g\315t[<\325f\233\336\250\335\335\354\007\236k\n\366\356E$\201Y\263j/\336\251\313z\355U\332r\325^Y\216j\224\363U6\234f\233\347\363SC5\\I}\352Q8\035\350Y75Z\215\317\025e\027u]\266]\214\t\255hI\030\364\253\321|\302\255B1V\241]\316*\352\340\036j\256\243j\034\002x\025E,\202\363\232xm\207\0252e\251\255\t-\232W\220D\235j\241&g\311\351R\201\264R\026\305A#Ui\032\253\310\325]\315U\224\325W5\366\341\343\212\221\005L9\305<-<\n\\Q\212\211\327\234\322c\002\202i)\350jU8\025\024\322`U\t\345\252RIPy\230j\241x\333\344\300\244\216\"\213\315E<\270\254\213\331\201\007\232\347\257\337$\201Y\221)\363jy\037h<\325\033\213\200\024\340\3265\335\320\004\363Y\263_*\344\346\251\315\251\341~Z\317\270\274\334\t-X\327\027\214\317\313dU;\213\215\300\3257\271 T_l\355P\315q\234sU\'\232\250\264\331cG\233\315Y\202@\306\254y\200S\322M\307\025z\332-\330\364\253h\2305n\036*\344n8\255+YA\\V\235\260\310\253@\200p*\304\007\016*\360\217\200{\324W\255\300\025P\266G\2654F\t\315I\271\"\\\346\252K|Y\260\202\223cH2\306\237\032\205\241\332\240g\250dz\254\357U\344z\256\357U\244j\255!\257\270\002\2265:&\005<)\006\244\024\341N\"\232)\255Q\223\305% 9\247)\305=\233\002\251\317/Z\317\232Z\250\362\324N\340\002I\250\241\002F,i\323J\021Mc^\334\200\016\rbOp$$f\263.\034\3621\315S\335\264\363\326\252\335]\005R\001\254\213\213\236\2715\201}}\272R\024\361Te\270\000\034\236k:\346\370(<\326U\316\245\214\363Y\322\3529\357U$\276\367\250$\277\317z\203\355Y=i%\270\001G5R[\234\367\252\255>\033\255!\270\343\255Mks\363\016kI%\030\253\020\020[5\251\024\212\027\002\247Y\005Y\216^*x\230\273\001[\2261\000\203=kE$\0100*H\337\'5v\006\344V\222\r\312\rg^\316\014\207\320Vt\267Lx^\224\213r\370\305)fu\344\323\240\214\006\253.v\n\217}G$\225Y\336\241y*\264\217P;\325wz\201\332\240v\257\272cCS\252c\255H\0234\365@h\331\203K\266\230E1\206EB\334\032Bx\244\034S\201\250\245\227\000\325\t\345\252\023IU\331\363P\273\357`;\n_=b^*\215\355\330\333\220k\236\277\273c\320\326a\221\213\022MV\270\270\000\034\036k6i\270<\326M\345\346\001\3075\221sr\356\017j\304\272\220!\'<\326M\336\243\267<\326%\336\242Ny\254\271\257K\036\265Y\256w\036\265\014\323\355\037z\253\031\311=i>\320W\234\324R^\037Z\204\334\363\326\230\323\347\275F&\251\241\270*\300\326\204W\204\201Z\026\323\222*\354R\234u\253\021\334\036\231\253\220\312Oz\324\323\3344\234\326\374\022\341EJ$\346\254D\376\365r\031j\361\275)\t\307\245d\313.\365bM@\204T\253\212y`)c\223\rO\226L\324%\370\250^Z\201\344\250\036J\256\357P\263\325wz\205\336\240w\257\275#A\212\225s\320\324\3528\247\355\244+M \n\215\216)\214\365\004\244T`\346\214\323^@\242\251\3175P\232nMR\222Z\202I\260\247\232\243svP\020\265FMD\205 \232\241s|\314\017<VT\367j\t\3475Fk\323\353T&\271\311\353Y\367\367\236Tg\236k\r\357\201\311&\262u\rX\000B\232\347\257u\"s\315a\335_\026\'\232\314\236\3539\346\250IpI\353M\022\234\344\232\212y\262*\025\2274\254\374UI$\301\250ZSQ\371\247=jE\2235b6\316+F\333\265i[\266\332\270$\310\251bm\306\257\333\236kR\315\266\267\025\267\004\271Z\231d\346\254\305.\000\253QJ\001\253\036`pW5BY6\243\003\3275\032IR\254\274u\2453d\320%\245i\263\336\243ip\265\003\313\315B\322T/%Wy*\027\222\241y*\026z\211\232\276\372J\231jPi\340\323Y\300\250\232Lt\250^Z\205\345\250\232L\324B]\246\225\247\030\353U\244\237\255S\232~\274\325\t\246\252sM\216\365N\342\343\345\353Y\3677\'\034\032\313\236|\223\223Tg\234\343\031\254\351\345\353Y\327\027\030\357T\232\347\223\315c\352\267\274m\315aO3\260<\220+&\355\260\016Mb]\311\327\232\310\270\223\223Y\363IT\336\\w\250\376\323\305F\323\346\220K\264SZ\340\036\365\014\222\203U\336Ni\004\231\251\021\252\334O\214U\373yj\364S\325\224\233\336\255C(\255\013ikF\332\343\004V\304\027\037-X\022\324\361K\223V\243\227\035jF\237\236\rV\271\220\344s\301\250\226Z\224MG\235\357J&\240\313Lij\027\226\241ij\'\226\240y*\026\222\242i*&z\214\276k\357\364\251\224\324\213CI\212\201\244\250^Z\257$\325\013MQ\264\330\250^Z\204\334\220qP\311q\357U%\237\336\251M5Q\236~\265\2375\316A\346\263\347\271\353\223Y\263\334c<\326u\305\327\275g\\]{\326|\367\031\357Uf\230F\275y\254-B\340\023\234\326T\327\300\002\005e]\\g$\232\303\275\272\000\232\310\236\353$\325\031\347\310\342\250\3111&\233\3655\033\311\216\364\303.{\323L\225\033\313\212\256\322\322,\334\325\210\246\253\2218\"\255B\3705q$\253\t5[\202l\326\225\264\340U\370d\311\310\255\033k\255\244\0065\241\034\333\207\006\255C%[Y:f\234\3161\221Q\310\373\220\216\365Qf\303`\324\236u!\232\2015/\237\357Li\252&\232\242ij\'\226\241ij&\222\2432Tl\371\244-_\240\213\305H\246\225\244\305D\362T\017-Vyj\007\227\336\241ij7\227\336\240y\261\336\253I-Vk\216\2435ZY\361\232\247,\376\365\237s?^k:{\234\003Y\227\027\030\'\232\316\270\2715\231qs\327\232\317\236\353\336\250\313pk>\352\354\363\315`j7\340df\260\2565\023\223\203Y\363\336\263g\232\316\234\263d\232\317\230\021T\346\223\002\251\274\265\t\234\212\215\247\250\215\306)\r\316*6\271\315D\322\346\221X\223Vb|U\330^\256F\365e$\251\322J\263\004\2075\247l\304\342\264\241\223h\346\256G&y\253\326\222r\006kR\'\301\253\002lw\2452\344f\231\346\3259\337l\271\365\245\363\270\246\231\250\363\250\363\251\2555F\323TFZ\215\245\250\232Z\215\244\246\031)\013\323w\327\350X\351J_\002\241yj\027\226\253I/\275@\362\325w\226\240y\361\336\241k\212\255%\307\275U\222\343\336\252Ks\203\326\253Ms\357T\346\272\254\371\356s\336\263nnz\363Y\223\334\373\326|\3679\357Y\227\023\362y\252R\314\000%\216+6\346\374d\200k*\356\363\203\315`\336]\006\'&\262\245\220\022j\253\221\234\346\253\3156\005g\3178\347\025\237,\241\263T\345\223\006\252K-@\322\324/!\250Zb;\323|\332r\311\223V#l\325\204\346\254\302H\253\3217\025e*\302U\273~\265\251n\274\003V\321\361V\242cW\355\230\202+E%\351\315M\347{\320\'\374\251\246lTS>\370\311\356*\005\237+\326\220\315I\347Q\347\323L\376\365\031\236\230\323S\014\264\326\222\243i)\236e\'\231F\372\375\r2b\242y\252\007\232\253\274\331\252\362M\317Z\202I\252\264\223\325i&\250\032j\257$\336\365VY\361T\247\270\367\252r]pFj\224\367]y\254\371\356z\326l\367\005\311\031\252\0272m\007\232\313\226\344\223\311\252\027w\251\030?75\207w\250\031I\000\361TZn\2475\233yq\327\232\306\272\270\353\232\316k\214\223QIq\216\365Rk\214\326e\324\276\206\263\332\344\2065\023\315\272\253\310\365\\\2774\036\225\004\225\036y\251R\254\304*\324c\025j sW#\025b<\212\261\031&\256A\234\326\204,\300U\270\315^\201\270\253Q\311\203V\343\233\"\244\363i\352\371\035y\246\274\271\353\326\231\346\365\025Qd\3014\031i\206jC54\315L3S|\337zO6\220\311L2Sw\322o\247o\257\320\207\227\035\352\274\223T\0177\275B\363Uy&\252\262MU\244\232\253K>;\325v\2375\014\262\344U\031\3566\236\265B{\2368<\325)%cUe\224\216\246\250\334N\000\353Y\263\334`\023Y\027\267\247\007\006\261no\230g\232\312\271\273.y5M\334u\315V\232|\014\n\312\273\270\003<\326=\304\333\215Ty\000\025RY\261\232\251,\365\237q>sTY\2715\013I\317Zc\276j\035\324\273\3150\234\3236\234\324\321\203V\342Z\271\022f\255\305\036*\334k\232\235#5e#\253Q\014U\350\216EY\213\217\245Y\214\342\254#\325\224o\226\237\346f\244I1C\311\315@\362`\324\r/\314M5\244\250\314\224\303-0\313M2\322y\264y\224y\224\205\351\246JO3\336\234\036\277@\345\237\035\352\253\317\223\326\240y\275\352\027\233\336\253\311?\275U\222|\325W\236\253\274\271\357MV\315E3\205\006\262n\246\3015\236\362njk\271D\315e\335\\\344\326t\323\365\346\263.n\307J\313\272\270\006\260\357\345\3018\254yg9\315B\327\034Ui\246\033z\326M\323\226&\250J\330\025Fi*\224\322U)e5NG$\324\022\266\005W-Mc\232a\351@\024\340\264\365_j\261\034uf8\352\344)W#QV\021*\314k\305H\006\rO\027\025r#V\3435f0*x\327&\254\343\000\nL\342\244F\247\270\004g\275U\227\255S\3632\315H\317Q\264\225\033IQ\231i\246ZO2\2172\235\346P^\232d\243}8>+\357\231\'\252\357=B\323{\3242O\212\251,\376\365Y\3561\326\253I>M@\363\373\323\243\270\001H\3175Z\342\343<f\250\\\220\3039\252d\252\234\346\251^^\014`\032\307\232|\347\232\316\273\272\332\0175\2115\347\314rj\205\305\336\356\365\233u(`k.Py\252r\022*\263\311T\247z\317\235\252\204\315Tfn\265Bi\0105\\\271&\242\220\026\250\212\221L\332h\333J\024\346\245D\315L\221U\210\343\002\254\305\035[\2121V\243LT\3521S\240\251U*x\324\n\260\202\247\215\261V\3429\253\220!cS\023\206\346\230\3074\350\315:G\305C!\371\t\254\322\373\\\323K\346\230^\242w\250\213\323\014\224\233\351w\323\204\224\031)7\322\207\240\313\201\212\373\312I\252\007\237\336\240{\212\255%\317\275U\222\343=\352\274\227\036\365]\356*\026\2334\303q\264\037Z\251qtW\247Z\317\236\365\217\031\252\023^\020\0175BK\235\331\346\251\313?\006\263o%\340\234\327?us\206<\326|\327X=j\244\227\033\252\273\311\221Ufl\203Y\362\311\202j\234\322g5Ff\2523=P\231\352\244\2475\001\034\322\021\3051\205FW\232P\224\365\216\247H\352d\212\246H\352x\323\025n!\322\255\"\034T\312\225f%\253\013\035M\034|T\253\035=W\232\263\027\025\247j\006\332I\017&\241-\316)U\361L\226\\S^O\334\234\326t\215\316i\245\251\214\325\023\232\205\233\025\031zM\364o\305;\314\243}\036e\036e5d\311\311\257\273\036\343\255@\363\325i.=\352\244\267\036\365VK\237z\201\356=\352\006\270\311\353Q\275\316;\324\rs\223U\247\234Vm\305\307Z\316\226|\223\317\025VY\361\236j\214\327X\315g_\\\374\247\232\347n\247\344\363Y\362\314MWy\210\357L3\202:\324m.j\215\3179\300\254\351_\034UY^\251N\325BSUd\'5\021&\233ASH\024\232z\307S$u:GS$u:G\355S,U*.*\334F\255F\233\272U\230\343\253(\230\251T\000jQ\216)\333i\3503W\255\233\024\255\336\243\"\220s\221\232\255p0:\324m!hqT\231\371\3053}!jc\034\324\016\334\324E\251\273\250\337F\3727\321\276\230\362c\275\010\371\257\271\246\233\025VK\212\253-\317\275T\222\343\336\252\311q\357U\336\343\336\241i\362i\217\'\025\037\233\264d\365\252\227\027<\032\314\232\343,j\204\323\340\236j\204\367=y\254\331\356\371<\326m\345\356V\262\345r\334\325I2MD\321\026\035j\264\244\306qQ\0318\252\363I\305gNy5RCUe\346\251\310*\273\256M7\313\366\243\313\245\021f\203\r9c\251\222:\260\221\324\311\035X\215*P\224\340\2252&j\355\262b\256\242\324\352\224\355\234\324\251\036i\3423\232z\241\315O\030 \324\204\363Q1\342\241y1Mr$R*\260FBG85Zx\312\234\212\255\273\006\202\324\302\325\024\215\232\205\2154\2657u\033\250\337LyqL\r\223R\006\305}\273,\371\006\250Kq\357U$\270\367\252\262\\{\325i\'\252\322\\\343\275Bn\300\357@\275P1\232\206{\260\007Z\315\270\276\000u\254\331\365\000;\325)/7\202sT..sY\322\310I\353U&9\004\3257j\201\333\232a\220\212\251r\333\305R\336rEW\270\223\025A\344$\324\016\325ZV\315Wa\232h\213&\237\345b\230c\366\241V\236\024\032r\3063S\244B\245X\300\251Q\005N\221\324\313\035H\221\325\210\342\036\225i\023\025f4\351V\025i\342<\324\212\273j@)\350\276\2652\2574\307\004\023Q\270\310\252\322qP\357\301\247n\312\363Q1\004\340\216*\215\314%\016GJ\253\277\007\006\202\325\023\032\214\365\250\311\246\226\246\227\246\031*=\305\21586)\341\363_iM?\025By\370\252R\334{\325W\270\367\252\362\\c\275T\222|\325w\271\307z\254o>l\223U\256u\036\0175\225=\361l\363U\036rGZ\200\\\2058\315A<\336\225JI\371\353P<\233\263\315Vv\250]\261Q3\201\232\2533\346\253uz\202\3421T\235\006N*\007\216\253\310\230\250\nP\026\235C-4-(Zz\214T\311R\255H\202\247AS\240\251\324U\210\261V\220\002*h\306j\300^)\353\305=FMH\213\315J\023&\244\362\310\346\211\006j\027^*\006\213&\253\311ns\305Fc+\326\232\313\236\265\013\r\303\006\263nc*\331\305B\033p\246\261\250\330\323\030\324,\365\023J)\233\363N\rF\354\322\206\257\261\345\270\353\315P\232\177z\2434\365RK\212\253%\305W\222\347\031\346\252Ms\220y\252\022\335\020:\325)n\t\3175U\346\367\252\362\334\205\035j\214\227\1777Zx\230:u\346\251\314\334\324\r6\332\214\315\232\216I2*\27395\033\234\212\254\371\352*\274\222\347\255Vv\250Y\252\027\346\242)\232]\231\243e)\024\314\nP*E\\\212\221\"\307\322\255Gn\010\353O\362\266\324\261\255L\243\006\245\003\245K\027\275Y\214\325\210\333\006\255!\334*U^)W\255L\265:\032\224\215\302\232R\243d\250\212b\241s\315@\340\032\205\3075\013\257\347Uf@\343\232\315\221|\267>\225\0336j65\014\216\024\036j\253\310Z\231\234\323\203`Rn\315.\352P\325\365\304\267\036\365Jk\214\367\252R\317\357U$\237\336\252\311=T\226\177z\2455\307^j\224\263\373\325In*\234\267X\357T\346\271\316y\252o?4\253xW\214\323\314\273\205C!5\026}\351\t\250\035\260i\205\263P\271\347\212\251*\345\216*\026\030\250_\025\013sL\301\035iI\244\334)3\232]\231\245\010jT\210\372\325\245@G\"\236\240\257J\262\024\262\362(\021\324\212\264\361R)\346\247\214\325\2045f&\305ZS\362\322\205\247\250\253(\270\\\232\267\010V\217\"\225\200\250]A\315C\"\361T\245^j\026\\TL*\031*\273\016\274U\013\264\301\315g\263`\342\242\222\\UVb\3074\322qL\'\024\233\251CR\3474\345\257\252e\270\252r\317\357T\245\237\336\252I=U\226z\251,\365Ji\352\224\327\036\365F[\217z\251$\376\365ZI\252\273\311Q\371\234\324\2119\025 \227p\246n\346\232\317Q3f\242c\203L\'\275G\216\t\252\223\032\200\232ajc\034\324l:\322`\232z/5!%E3\314\346\245Ij\302J\017z\235Xu\251\222b\275zT\273\263\310\351O\0074\341\203\332\236\242\245S\212\231[\0254o\315\\\211\263VB\340R\257\336\025nb\014k\212\226\321\200\\S\344\305Ws\203P;dUy9\250\236\253\311\305B\374\325y2:U9\237\177\007\255g\334&2j\223\214\346\241c\3151\232\230Z\233\234\321\234R\206\251\025\253\377\331"
+byte_png: "\211PNG\r\n\032\n\000\000\000\rIHDR\000\000\002\000\000\000\002\000\010\000\000\000\000\321\023\213&\000\000\001NIDATx^\355\3351\016\200 \024DA\362\275\377\225\211\375VFE!\314\224\357\006l\002\264\006\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\277\251\014\223\350\031\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\200\313\216\014\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\300\020=\003\260\222\312\000\000\000\000\000\300\352L\277\000\000\000\000\000\000\000\260-\227>\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000`^\276\023\000\000\000`+\016\302\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\357\351\031\000\000\000\000\266g1\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\340\013\336\307\007\000\000\000\270\2512\000\000\000\0000\206!\006\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000`-\225\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000x\352\004b\"\006\010O\232\021\276\000\000\000\000IEND\256B`\202"
diff --git a/core/res/geoid_height_map_assets/tile-7.textpb b/core/res/geoid_height_map_assets/tile-7.textpb
index d00efe8..9667e64 100644
--- a/core/res/geoid_height_map_assets/tile-7.textpb
+++ b/core/res/geoid_height_map_assets/tile-7.textpb
@@ -1,3 +1,3 @@
 tile_key: "7"
-byte_jpeg: "\377\330\377\340\000\020JFIF\000\001\002\000\000\001\000\001\000\000\377\333\000C\000\004\003\003\003\003\002\004\003\003\003\004\004\004\004\005\t\006\005\005\005\005\013\010\010\007\t\r\014\016\016\r\014\r\r\017\020\025\022\017\020\024\020\r\r\022\031\022\024\026\026\027\030\027\016\022\032\034\032\027\033\025\027\027\027\377\300\000\013\010\002\000\002\000\001\001\021\000\377\304\000\037\000\000\001\005\001\001\001\001\001\001\000\000\000\000\000\000\000\000\001\002\003\004\005\006\007\010\t\n\013\377\304\000\265\020\000\002\001\003\003\002\004\003\005\005\004\004\000\000\001}\001\002\003\000\004\021\005\022!1A\006\023Qa\007\"q\0242\201\221\241\010#B\261\301\025R\321\360$3br\202\t\n\026\027\030\031\032%&\'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz\203\204\205\206\207\210\211\212\222\223\224\225\226\227\230\231\232\242\243\244\245\246\247\250\251\252\262\263\264\265\266\267\270\271\272\302\303\304\305\306\307\310\311\312\322\323\324\325\326\327\330\331\332\341\342\343\344\345\346\347\350\351\352\361\362\363\364\365\366\367\370\371\372\377\332\000\010\001\001\000\000?\000\367\325\3014\371\"R\231\350j\233.\036\244A\305?\024\273i\301iq\322\237\263&\223i\364\247\000A\247\201\232xRMH\252qR\252\324\253R\255J\265*\324\253S\245J\277xT\303>\264\342\271\003\214\323\343#\247z\260\242\245\024\360i\300\323\301\240\324M\301\315Z\267\225Yv\265H\313\316\005T\224\020qK\0023?z\261s\022,@\216\265\234s\232LPi\247\024\302\005D\3521P\2203PI\212\251 \252\262-V\221j\254\203\002\252J*\253\212\254\331\252\362-T\231x\254\371\220U\031V\251\310\2475\023-B\302\253:\344\324E*\027J\204\307PH\203\025\357\215\021\316E1\303l\301\250\n\372\323\324S\300\247\001N\013N\013J\026\234\027\212v\316)\352\224\360\265 Zx\024\365\025 \251V\244Z\231jT5*\324\313\232\260\200w\250\201\006rW\245ZS\305H\r8\032x4\360ii\214)\261\261W\253\350r\271\250\235C\311\315]\265\214q\201F\241\016\330\201\025\223\267\232M\274\322\025\250\331qQ\034\324MQ0\252\356*\273\212\257 \025NA\317\025Y\306j\254\252MUu\252\316*\274\202\251\312*\214\300sY\362\216j\263\212\256\302\241e\315B\313Q\025\250\230\n\201\326\240u\342\276\200\003\326\241\230\002x\252\373rsJ\020\323\366\032pCJ\0058\nx\024\360\271\247\005\247\205\247\005\247\005\247\205\247\201O\002\244QR\n\225M=H\365\251<\330\323\031aR\255\304{~\\\223@\363enX\201\350*\314h\024T\300\323\301\346\236)\340\323\3058t\245#\"\242a\206\315[\200\3459\241\201\r\221Wme b\245\277\005\255\301\035+\030\214\032J\010\315F\313Q2\324L\265\013\200\005V\222\252\310j\263\325wZ\256\353\212\252\340\232\254\350j\263\245U\224`U)GZ\317\230rj\234\213U\034sQ\025\250\314d\366\250^3\351Q4F\240t\305WqU\334W\2767\003\"\252\3111\r\203J\256\255\300\353S*qK\201\232\\sF)\300R\342\236\007\024\360=\251\340S\200\247b\234\001\247\014\366\247\000i\342\2363N\024\244\344c5\022.\331\366\036A\365\2558\342P\271\310\253\010GJ\220\032p4\3654\360i\340\323\301\251\005<R\024\315 \334\207\212\231\030\267j\263\016U\207\025v\\Ih@\355\332\262^.zS\nSv\323Yj&Z\205\306\007\025VJ\255 \252\262\n\256\303\232\215\326\253\310\265\003 \364\250^>*\244\250\000\2523-P\230\001\232\316\227\255S\220Uw\034\324Ey\2461\307\002\242<\324NqUd9\252\262\014\325y\026\275\335\345UZ\314\272\270_^k5\365/&\\\356\255\013}b9\024|\302\247k\325<\206\024\364\274\004\365\247\033\300\rK\035\310aS\254\253\364\247\254\253\237\274*u\301\024\375\246\227\276)A\247\003O\024\341\326\234)\302\226\242\225\312\014\324\006\360\t\327\'\232\330\266\270\363\024dU\241R\203\221N\024\361R\nx\251\005H)\353O\003\212F\034T\226\303$\214T\340a\263\332\247\21418\035\352\t\227ksU\317Zi\024\302*\'\007\265V|\367\252\322\016j\273\212\255\"\232\256\302\242~\225]\352\026j\201\315U\220\325\031\210\031\254\331\316j\204\243\232\252\353P\024\346\230\311P\264u\013\214\n\251)\364\252\315\222j&Z\201\326\275vk\261\264\363X\267wyc\315e\314^F\342\243\215.c9V5i\'\272\003\251\251\222\356\345G9\253Q\352\017\374`\326\276\237\177\004\214\003\234\032\350\022+Y\"\0048\006\253\315\004jr\257M\212]\235^\254\255\3169\316j\302H\255\315?\000\364\247`\322\342\234)\343\2558S\202\223Q\317\036R\271\3717\256\242\003\036\365\321Y\311\205\025\253\033\202\265(8\251\027\223\221O\002\244\006\236\r<\021R\003R-H)B\356<T\221\241G\006\247n\306\246\204\372\322\\\306]w\001T\212\220i6\212aZ\211\326\253\274u]\323\332\253\272\325Y\024\324\014\225]\322\253:\032\252\343\006\253\271\342\252\312\334V|\3079\2522\373UGSU\335y\250\312\324L*\273\234\n\247+f\2538\315DV\230V\241\221p+\266{\302\313\200j\253\006\221\263S\307\0161\232\262\221\003\306*U\205s\202)\376B\372Q\366d=E\002\324)\312\361Vc\226\3421\2649\253\021\3159a\271\262*\311\212F\\\206\305Vyg\204\363\234\n\267g|\314\303\232\331\212`\313\234\325\205n:\323\301\247\214zT\200\017Jp_jv*\031\234*\034\326\034\314\262\337\215\275\253^\334\020\202\257C!S\315^G\004u\251T\342\234\032\236\032\236\032\236\032\244V\251\225\251\341\252\304c\212\234/\0241\3711L\206C\346\214\326\201\001\243\342\250\314\2705\\\344\032Jkb\240\223\025]\260{\212\201\322\253\274uY\327\007\245@\311\315C$\177-P\2310MS\221j\214\335\352\214\240\232\247\"\324\014\265\003\245B\313\212\253)\364\252rd\324\014\265\023-D\313Q\225\250$\357]zB\005H\261\200zT\303\000\234S\325\260jP\3319\251\003S\267T\212sR\000*\302\000G\246*\310f\362\301\035\272\3222\254\211Y\263F\320\276\350\370\253VZ\211\334\025\215m\305p\254\274\032\262\262\217Z\225$\025:\2605(9\245$\001\363\034VV\247v\261\304Bw\254\315=K\314]\273\232\350\241U\333\214\324\352>n*\322\016\001\251\203qRg\2758\032p4\360jUj\2205K\037/W\342l\214T\300qQI\322\252\031\032)w\036\225\245\005\302I\027\0075\014\304\347\232\256O4\307\220(\250\231\362*\264\231=\352\273d\032p9L\032\215\205@\351\223P\262\n\257 \025Bt\2522%R\225=\252\224\251T\3359\250\0351U\335j\274\213\305S\221\016MWt\250\031j\026Z\205\205F\343\013\305T\220z\327l1\212\t\2405\033\271\247\254\230\251\004\224\355\365\"I\212\235d\253\013.@\036\2252JGzr\271\r\212I\000u\254\371-\312>\345\253V\267m\037\312\306\257\255\360\340f\254%\341\007\255[\212\364g\223V\016\242\2128\305S\271\324x\'uc\3114\267sc<V\265\234F5\034V\254l@\253\021\270\'\232\267\033\034`\366\2513\315<\032p4\360j@i\340\324\201\252h[&\257E\367\205[\003\212k\256k>\355\016\334\212m\263\262\307\221\324u\025\241\023y\311\367j)\241\220\002v\342\263\344\334\257\315\000\344sQ\271\031\250\033\257\025\023\023Q\2279\346\232\317\307\025\013\023P=U\225sT\344J\247,}x\2522\307\355U$J\253 \002\252\272\324\016\231\252\322&*\263\256j\273\255@\353Q\371f\253\315\264qT\2449\351]\216\352B\364\335\376\364\273\3517\363\326\236$\347\031\251\003\232z\311R\254\225b9x\251\204\235\352\306\362@#\222G4\365\177Z~\320\303\2450\333+v\244{b\2540i\271\225s\355H%\237=\rYF\231\327\245<Z\263\237\235\252\335\275\252\241\031\253\340\005\350i\352\376\365j0N\t8\253\260\347\025)<\212p5\"\236i\340\217Zxjz\270\365\247\347\212\226\006\303c5\241\021\031\025u\0334\375\271\025\004\261\344U\031$[@\305\206A\252\366\232\260K\235\270\340\232\350\"\270\216\342.\203\232\247wl\270$V[|\247\025\013\036\265\t84\036j\027Z\256\340\212i9\025\023sPH1Ud\252\262\000j\224\340\n\241/5Q\327\232\256\352*\007\025\003\256j\263\245Wt\315B\321s\322\241\230\205\\V\\\247,j\273\n\353K{\323\031\3523\'=h\363)w\322\356\367\251\026S\334\323\374\301\236*Uz\231d#\275XIr\270\251\343\224\250\353S$\244\266qVc\220\221Sg\"\244\213\030$\214\201I\265\013\020\007\024\341\n\372U\210\320/\030\305J\027\326\234\247\232\223w\024\233\271\342\245\216Gf\003&\265!\225\322?\231\177\032\224J\244\344\236\264\365n\375\251|\320;\323\204\231\357\212\221Y[\370\252@\213\331\310\245\303\257G\006\245\206FY\006\354`\326\234D\214\021\322\256\306\325aNE8\214\326V\261\thN\005`G\003\211\001\036\265\322\332e-\320\223V\334\253\306y\346\261\347]\254j\231<\324Ny\241O\313H\340\325y\001\305CQ\265B\347#\232\253 \252\262\n\243=Q\220UY\005Wu5\021N9\250\231*\t\020Uv\0305ZW\030\306k:\341\3075\225$\247\314<\324-7\035+\253-Lg\342\242f\346\220=/\231O\022f\234\036\244\r\306sR,\225:\276jd|\032\262\217\232\236966j\300\221wqS\253\361SC>\323\214qR\226L\345{\325\210\266\354\334O\"\207\224\0312\016i\333\370\245\337\315(zpl\323\343r\254\rh\255\323<!1\323\2759I\315L\034\201\212P\3709\247\357\247\253\212\225$>\265(|\323\362}kB\326l\240\004\326\224R\002\243\025a^\246F5\235\252\334\241\002 A5\237\n\000FGz\331P\242\025\003\245&y\340\361T/\007$\326y\353P\275*\0361J\325^SP\036\225\023\032\257!\250\031\252\t\000\252\222\2405FD\353UY9\351Q\262\014t\252\322)\002\252\273`UYe\000\034\232\316\270\272\003\214\326t\267LI\252SL\315T\2379\250^\272\306j\214\275FZ\233\276\215\364\241\352E\222\244\016E=^\246I*x\345\303sVc\220g\255XV\315N\2161\201\326\247I*P\374\346\254,\233\227\030\344T\210\375\273\324\245\243\\ps\336\236Y\n\r\275i\241\215<5<5J\204f\264\240h\304G=jx\345]\273v\365\357HH\316(\310\247\003R.jE5\"\2675*\266{\324\360Hc|\036\365\251\024\300\r\302\247[\245\0377j\255s\254$jU3\322\263\340\221\256%.\3479\255\r\277\'\025v\335\213\303\203\332\202p\325Z\353;+9\2175\033S\001\301\245,*\t\016MF\304c\025\013\342\253HqU\335\252\007j\201\310\305U\223\0075U\360\rA#\200j\234\322u\254\313\213\205N3\223YS\312\357\236p*\234\200\325W\025]\305@\342\253\270\256\221\236\242f\246\027\246\227\244\337J\036\236\255\315L\257O\017R\254\203o\275J\222\014`\365\251\243\222\255\244\274U\230\245(Cf\247\363\2030*1S\tr\243\216\225<r.\317z\221\\\203\221R|\3167\366\245W\355O\017OW\315H\246\245V\253\021\310sV\321\216*e9l\324\244/\033M\000T\252=*@3N\000\346\244\000\212\2327\033H#\'\265J\262\270\340\362)Y\344*|\266!\217j\242\320\334H\307w\353E\264\317o7\227 \305m\303.\365\253Q\002\2719\305)j\206\341\263\t\315g\340\236i\215Q\021\315!\340u\250\034\324\016\370\250\214\235\215C#dU\031e\332\330\250\232e#\223\212\201\347L\3435ZI\224w\252sN\240psT%\270l\236*\214\323H\335\361Td\004\234\232\255 \252\316*\263\212\256\342\253\276*\263\326\343=FZ\243-L/@zxjP\3305*=J\032\236\032\236\257\315XG\251\322J\264\222d\016j\3126\027\255O\034\312\001\004g4\364~j\302\276EH%`0\017\02524~I$\374\336\224\320\354G\034\212z=N\257\232\231\030\032\261\031\031\025~-\214\204\226\346\234\016\rH\246\246F\030\247\203\212\225MH\0174\372\221jT4\375\2719\034\032\221\034\243a\300#\351R\313i\004\311\275@\3156\331\014M\260\363\216\225t7\2754\2775RG2\311\264t\315\0050\265\003\255B\303\024\3228\250e\373\265U\352\273\203\236j\t\t\344\003T\244\353\223Ud \232\254@-\311\305W\231\030w\252RUY\rUpOj\253%WqU\334UY*\264\225Y\305WqZ\214\364\302\324\302\325\031j\003S\303S\203T\212j`\324\273\251\352\3252=L\217V\242z\264\030\201\311\251\243q\221\3179\253A\324\215\270\344R\254\234\324\301\262)rj\304\022\005V\311\355\322\235\021R\307q\251\343x\311\347\"\246R\240\360sV\021\252\3129\035*\302\022\3250\343\212\225\010\035\351\373\226\236\033\322\244Y*@\365*\265H\257V#`i\316@\024\353y\227qBz\324\341Fs\336\235\273\034S\033t\234/\342i\025\002P\354\000\252\256\331\'\025\023\017Z\211\216\005B\355\220j\273\363P?CU^\252\3123T\344\030\252\262f\2539>\265]\262\016qU&\31318\250\031\366\202\000\035*\233\325g\252\3626F1U$\252\317\326\253=Wz\276\315Q\226\2463Te\251\312\324\362F)U\371\251\225\252M\324\233\371\247\254\225*\2775:=XG=\252\322\3121\315M\033\215\303\'\0258\223\022gvj_0\023\221\305L\217R\206\315=X\253f\245V\311\311\251A\307\025<mV\021\352\324m\310\253\276daF\336\264\340\376\364\340\304\367\247\206>\265\"\276)\342Jz\275H\262{\324\253%XI)\354\344\212\2127\304\325t\316W\006\234f\004dT\213.!\372\323\004\231\357MbMF\300\001P\261\250\037$qQ\230\230\236\265\023\243\003\216\325V\\\347\025Q\363U\344\351U$\252\317\357U\330\016\265ZNx\002\252\310\010\353U$\034\032\251!\252\262\032\253!\252\357U\234\325g\252\357VY\2522\324\302\324\302\324\241\251\333\351U\271\251D\224\361%858\032\225[\025:\275O\034\225hH\030\016*\304R/\000\212\225~\376\007\"\247\306\334f\247F\342\245C\270\3435(\334\006H\340w\247\253T\241\301\307\255N\273\210\315J\256A\346\254\307\'\025ad\007\275J\257\3163S+{\323\374\314S\204\231\247\007\247\254\224\365\226\247I*\304rU\200\340\256*\031\t\007p\2530\310\255\016\032\246E\017\031\001\272\014\212lr\0026\267j\224\306G(i\271b9\342\230\330\305B\355P\266{\032\217\220:\324lX\036MA$\203?tUY1\234\342\240`\233y\353T\337\000\236*\244\234\236\225\003\223\214\n\256\303\234\325i\201j\245,|U)S\025R@y\252\256*\264\225]\305Wz\254\365#5FZ\230Z\233\2323F\352P\364\3573\336\236\262T\201\352T|\324\271\251Q\215XCVU\370\002\254F\334d\036j\314R\355<\216jP\304\375\354\342\246F\305H\255\315XIH\300=;\324\303i\034R\240\014\330\315YI\n\214\003\370T\236fXdT\312\346\246I1R\254\203\255L\263f\245\016\017zP\324\341%8IOV\357S\243U\204z\260\262qR\002\030S\014\215\t\340dU\210\356\001\371\223\203\334R\312\215\031\022vj\2369\tA\3159\217sP;\222j&$\324D\220qL\'\236hb\n\344\n\252\340T\016\265Y\326\252\310\265VE\252\356\265Y\352\264\225RQT\345\025NQ\326\251\310*\263\212\256\342\253\310*\263\212\215\232\230Z\232Z\233\272\227u!jn\3527\323\325\352ej\225\032\247\017R#\325\224z\260\222b\247G\346\254\240\'\007=j\310\220\340!\355R\241\347\232\235B\263`\034}jN\000\3109\251\020\343\004\364\251c\223k\344T\302M\317\222?*\223~_\203OW\303u\251\225\315X\215\201^MH\254)\352\376\365 zpjP\3075\"\261\365\251\221\361\336\247I*\302?\275L\222`\324\334H9\244\020\341\276S\214S\247\231\374\225\213\25754G\010\005L[\345\250\310\3435\021`F\000\315\001w)\'\202*\t\025\227\250\250w\340\324NFj\007\342\240z\255 \252\262UY*\264\225]\305V\220\n\247*\361T\344\025NE9\252\256\247\255WqU\334Uw\034\32564\302i\245\251\205\2517\321\272\220\265\000\323\225\271\251\225\252ej\225Z\245V\251\221\361V\021\352\314mVc\223\025b=\316r*\3021\035jej\2207\241\253\t 1\355<S\343\004\364\346\244\r\203N\014*Ej\231^\245W\251U\352P\365\"\265<5.\352z\275J\255\357\212\235\034b\247G\346\246W\2530\311\201\223S\253qP<\231\270\031\355Vc\220\032\235\270N)\214\333\223oJ\214.8\245\357\301\243\206\371Z\252\\\302c9\035\rU<\324.j\0075ZF\252\262\032\252\344\325g\250\0335]\371\252\362.j\253\2475RT\346\252H\270\025VAU\234Ug\025\236MF\306\230M34\231\245\317\024\204\363@4\340qR+T\252\3252\265J\255S+T\350\325b7\342\255F\331\346\254\306\3079\007\025`1*9\251U\2601\326\246F\031\03156T\036\016jh\330\203\221R\222Y\263\214f\234\230\r\317\"\227?5H\032\244W\0252\275J\257R\253S\367R\206\247\253sR\253w5*\265L\217Vcl\324\352\330\220\n\266\207#\025Z\351\037\031\217\255V\216\352x\333\016\207\212\275\036\240\2546\234\203SB\354\316I\351R\203\315.h\341\271\035hp%\214\251\353Y\322FU\210\"\253\270\036\225Y\326\252\312\225Y\322\253H\265Y\324\347\245@\374\034\032\254\343\234\324M\310\252\262\216\265RJ\247.MUu\252\322-Vq\305d\226\246\023Q\223Q\356\367\245\315(4QJ)\300\324\252jUj\231Z\245V\251\320\346\254Fj\324lG\025r\006\031\346\247B\017z\2262;\323\267\020j\324j\206\035\333\271\364\247D\344?=*\324\215\362\014\021N\204\253\0341\353J\300\256y\244W\251Fz\324\252\330\025*\275J\257R\007\315<8\306)\301\252Enjej\221\032\254\243\325\210\316X\032\275\033t\251\202\203\324R\375\231I\316(\373\002g~\006j\312*\371x+\217|Uy\303Dp\006j\271\270 \341\201\247\3078\335\234\324\305\260\301\327\241\250\346\001\206ER\221*\263\240\252\322%Wx\2168\025VH\315Wa\216\242\253\312\252z\201T\345\\\032\256\353P\272dUY#\342\252\311\030\364\252\222 \305S\221j\214\301\206qX[\3154\311Q\2264\335\324\007\247\006\247\356\245\315(4\361O\025\"\232\2240\251\021\252\3025X\215\271\353V\243<U\204j\260\217S+T\252rqR\347i\3009\251\343 \216N)\341\311\372T\270*\241\273\032\221\037\236\275}i_n\357\222\236\013\005\301\351R\203\307\006\234\032\245Y8\247\211=\352@\365\"\275J\032\244V\251U\252dz\265\033\236\335j\3542g\212\273\031\253+\332\246^j@(dW\352\240\325Yl\321\262v\326M\305\254\321JY:zS\241\271 l\220b\247,1\301\315B\3705Y\305V\220T,H\340UI3\232\253&j\263\212\255\"\345j\263\257\025\t\025\014\203\255R\224U9{\3259\007Z\204D\013d\212\346\235#Y8l\212a\205\030\375\354Q\035\270c\214\212\212\341\022!\214\202j\274\1773\201S\315\037\227\214w\024\305bx\245$\212r\266j`i\342\237O\006\245SS\241\253\010j\314m\305XV\253\t\22229\251\221\271\251A\305H\255\232\263\033\003\324\324\350\343n\322;\324\310\352\t\004qI\237\234\340`S\267\374\331\251<\302\344f\224\032\221Z\237O\034\nz\265H\257\315J\262T\253\'\025\"\275L\257Vb\223\232\273\033\177\020\352+B\031\001\025q\rN\246\245SN\240\362*\t#\r\326\263o-\201BTr*\22420;[\250\251X\203\355P\275WqP8\252\322\n\253 \252\356\277/\270\252\255\301\346\253\270\344\325g\340\325yMT\227\232\251 \315W1\344\323]6\360+\210!\275i\244\260\356i\242G\\\340\365\250\233s\234\232tm\345\364\024\366\230\276\003\016\225$e<\300{w\253r\305\013G\274\020*\025\2156\360i\n\225\353OSO\310\245\006\245SS\306j\302\036*\304f\254.H\3105v&P\230\024\241\276j\225Z\244V\346\247F\346\247S\305H\037\r\234\324\306r@\030\024\343\206\210z\346\206R\207\203\232P\346\244W\247\207\247\371\234S\225\363R\251\342\236\032\244V\342\245G\251\225\252\304oW`|\361\232\275\003\020\370?\205h\306\325aZ\245V\247\203K\234\212kUy\260T\346\261\034\001x\333jC\322\243aP=B\302\253\310*\264\213P\225\311\305T\232<\023T\344\030\252\322\364\252\217\315VqP\262z\324eB\202j\234\254s\\q\0034\322\242\242*3HV\230V\215\264\240\021\322\2367\221\214\232zeMYb\257\017\'\221L_j~1K\355OZ\235\rYJ\235x\30752\203\334\325\230\316\016\005M\273&\236\rJ\244\324\350jt5 4\360j@\374b\235\274\205\306i\341\325\227\035\351\331B\270\031\315H\2411\202pip\017\3359\246\206 \324\251%L\032\236\255\357S#qS!\253\010j\324M\203Z\020\2718\307Z\320\211\362\005YV\251\225\252@\324\355\324\326<Uy\233\nMd/\31736)\347\245F\325\003\201P\260\036\265\023\343\025]\361P\036\032\242\22523Y\363&\t\252r-T\230\205\025M\245\001\251\254\340\362j\244\217\222Fj\254\307\025\3071 \323KSI\244\315%\024\240T\2129\247\225\364\244\035i\350y\251;f\216\364\361S%XS\201Vb\031\344\324\253\326\254FqR\003\322\245SR\251\251P\324\312\3250jpj~\352pl\323\201\247\251\247\344g\203N\016Tq\336\236\233Yy?7j\010(\3305\"\310jEo\232\247V\346\254!\253\010jtnj\375\273\343\006\264!l\n\264\215S+T\241\251\333\251\013U[\226\375\321\252\01003\353C\032\211\215D\306\240z\201\252\026\250\232\232yZ\2512\003\232\243*V]\337\312\246\262\032L\277\025\034\222\262\346\230\231#&\243\230W\"\3035\013)\034\323OJm(4\341\322\235\3058u\251\001\371i\271\346\245\000\005\036\264\341\315;\024\242\245N\265b<g&\255Fw(\305L\240\324\252jE52\364\251W\000sO\004v\251U\252P\334S\303\016\224\340\303<\364\247\340\377\000\t\006\224\026\035j@\331\247)\347\223\212~\354\232U?5M\221\320\362E4\0346*`@#\006\247Rv\346\246\215\371\253(\325:\265h[0+\357W\342n*\3225L\255R\007\245\337Az\255p\333\276Z\256H\025\033\032\211\215D\306\242j\205\272\324,*&\025\0218\250$\"\251JG5\225z\003Fq\324\326RC\206$\325k\200\014\230\024\364\030J\202q\\\203TmQ0\301\246\321O\006\235\324S\200\247\017\273H:\324\213\315H\235jJ\\qNZ\262\225f\037_z\237<\323\201\346\245SS)\251\001\342\236\rJ\246\244\007\'\024\376\206\216\246\2342;\323\203\266z\324\201\263O\r\357O\006\234\032\237\274\223\223O\334\t\342\244V\305M\033\022x54d\022y\253\010\336\365aZ\256[\276\ri\304\334U\224j\231^\245\034\216\274\322\027\342\230\322`{\324\014\347\251\352j2\325\0315\033\032a5\033T,*6\250\237\245V\223\326\251M&;\325)%\310\254\311\231\235\375\252\274\204\001\201T\235r\371\2511\204\252S\232\344\332\2425\031\246b\2234\240\324\212i\342\237\216)\005=2O\025 \340\324\213\315:\234\242\246CV\242\373\270\251A\346\244S\315H\247\007\025*\265<5H\246\245\006\236\247\030\247\347&\234\r;u8\032x4\354\324\212i\340\214R\203R)\342\244\r\305=\037\232\261\037&\254)\003\241\251\221\253B\324\256\316z\325\350\337\232\266\215R\243v\251\225\360\334\323\032Q\311\364\250w\345\267\032k74\302i\244\324mM=)\206\243aQ\221\232\211\306*\234\355\201Xw\263\034\234UA&\345\246>1\315Tq\223P\224\3074\215\367j\204\347\223\\\253\n\211\2523L4\322)GJr\232\221jL\214R\016\224\345851;\200\300\247\255;\255<\n\221z\342\254\241\251\224\324\203\255<\032z\232x\340\324\273\362j@i\341\251\340\323\301\342\227>\364\3655 4\354\323\324\323\263N\006\244\rO\335R)\035\215M\033\342\254F\377\000.*\324#.\0015u\006\016\001\351V#\227o\007\275^\215\270\251\343o\230S\236O\236\243$\236\275)3\305&I\245#4\322)\214\0050\364\246\355&\232\313\353Q5V\231\302\212\311\272\271\007 \032\307\235\3015\000\366\244+\353Q\262T\022t\250\034\374\265B\342\271\206\250XTG\2555\272RQN\247\255;\275-;<\n\261\000\334qO \251\247-H\242\236\275ju\351S%J\270\301\342\224T\203\255H)\340\001OSO\006\236\246\244\006\234)\303\255H\264\372p\300\247dR\346\236\032\234\032\236\255\315J\255V#j\271\013\373\326\204-\214\036\265e@.\030U\264j\231\032\234y\346\216qJ\026\227o\265\033i\n\323\n\212i\000Td\324N\302\252\3132\"\222Mb\337j\013\310\006\261&\273,x5\n\356\220\344\324\341p)\255Q9\342\252\312j\t\017\025F\342\271\206\250\232\241=i\207\255\'C\365\245\3174\3454\365\247\034R\255<T\3206\331*\334\201J\356\034S\000\251TR\201\315J\265:\032\224R\216\rH*U\353O\305/Jx\247\203\305H\275i\375\005(<\324\212i\343\245(\353N\310\2434\240\323\201\346\236\032\245F\253(j\324m\212\273o(\003\232\271\033\340\017z\270\215\300\251\203T\212\325 l\323\301\036\224\271\244\246\265FMD\316\005U\232\345\020ry\254\253\275P 85\207s\251\273\222\003V{4\262\266NhX\017z\235\020(\247\036\225\013\265@\357U\24495\013\364\252W\035\rsMP\260\250\217Ja\353M>\224\237Zx\353R\255\004\020sNZx\351R\3062\302\256\034\234\016\240R\262\355jr\364\247\201O\002\245PEL\2434\374q\212r\361R/Z\224\032)A\247\253f\246SN\316i\300S\207\024\3658\024\377\000\306\223\232PisJ\r8\032\221\032\254\243U\230\332\255#t\301\253\201\211\333\316M_\211\376Q\315N\255S)\251\226\244\002\235\201Lc\212\201\246\003\275T\226\355\001#p\2527\027\310\001\371\353\036\353P\31085\225!\232v\357\212\022\323\007$T\302\020;PP\na\030\250\235\270\252\356\325]\336\240s\305FNEU\270\037)\256i\205B\365\021\250\3154\322\216\224\240\323\267v\024\365c\322\227\004\032\221jd\353W\004\213\344\343\034\347\255\'\336n:T\252*@8\247\001R\257^j\302.O\2659\200\315\'\361T\202\236\246\235\216)\271\305875*\275H\255R\251\247f\2274\240\320\\\212\177`M\034\2122i\300\324\210jtj\265\033U\224nEZI\006r\0175j\336B\033\035\215_F\315XCS\241\251\205G,\351\022\222\314\005a\337k\221\306v\241\254\306\325%\224\360MW\226I\333\236y\252\315\034\316~f4\253j;\363R\210T\016\224\245@\250\310\002\242sU\335\261U\335\370\252\316\336\365]\233\232\211\333\212\210\266\005V\235\376CX\rP8\250M0\323i;Q\320\322\203O\006\244\\g\232\231zc\0252\240\3019\351O\031\253\366\361\006\204\237J@9\251\025sO\013R*\324\3506\214\320y\315 \247\212x\247\203\305!\353IOZ\221s\332\244V\251\001\245\3158\032\0174\375\304\256(^\264\273\273\032\\q\220i\351\232\2363\315[N\225*\2675idP\177\n\232\031\300q\223\326\264\342\220\021\326\255#\014T\236z \371\230\014T2\352\320\304\244n\025\201\177\252=\303\355\214\361T\022\006w\334\347$\325\264\205@\351S`\001\202\0055\243R\231^\275\352\0221\332\232[\025\0335B\317PH\365VF\252\3625U\221\352\002\324\306j\205\237\212\2513\326CTL*\026\025\031\246\232oJJQOZ\225jd\025a\027\212\220-[\266/\367\027\275?\313*\377\0005J\242\244\002\244E\035i\371\244\301\243\270\342\236:\324\213\203J}\251\264`\323\200\247\251\"\244\024\360i\324\240\323\201\315;4\240\322\343<\3203ORj\302c\031\025b6\342\245\315I\021\314\200z\324\267(\321/\007\236\264\221j\245Wk\360EX\376\332\n\274u\252\263\337\3176Ys\315W\002Y\016]\215N\221\201S.\005J\036\202\325\031r:To/&\242g\r\323\255@\356A\305B\322T.\325\004\215Udj\254\346\253\273S7z\324\022=T\231\253=\2526\250Z\243\"\233M=)\264\243\255=jU\251\343\253H3Sm\253\226k\222@\\\232s\347\314;\252E^)\340T\212)q\203J\000\240\014\344\n\007\002\236\264\277Jv\3363IJ:\323\301\247\212ZP{S\201\247\016\231\245\006\244\340\2504\006\300<\320\rH\246\244S\203S\207\002\245\017\3059d!\262*\353\312&\201r9Z\246\360+6qJ\220\252\365\025(P\006;R\360(\336\005\036e/\233\212<\332i~*6z\205\244\301\3105\021\227\223\236sQ\263)\034u\250\013T.rqU\334\325y\rVs\315D\315\315@\346\252J\325U\205B\325\023S\017Za\246\232oz\007Z\221jU\253\021\366\253q\212\235Fj\345\2332K\362\212t\247t\333\261R \342\244\002\235\333\203\326\202=z\212\024\022\t\024\244`\n\\aA\245Z\221\027\223\2321\212LQ\212p\353N\006\236\016h\3058u\247g\265(\353\305/\"\214\234\346\235\332\234\032\245V\251\001\247\253b\244W\253q8\362O5\037\233\363u\247y\231\024\365l\3655\033H\001\3057}4\311I\346Q\346Q\346S\014\225\0235D\315Q\261\246y\230\353\315D\374\234\3665\004\200\212\253!\252\354j\0268\250\035\270\252\222\032\211\372T\rQ50\323OZa\246\np\353OQR\245Y\216\255\305V\224U\273D\014\373{\232\236ks\020\311\024\304\346\245\024\243\000\344\366\244\357\222)\300\r\271S\370R\362W\036\224\270\342\234\006)\303\257\024\275\261E&)qN\002\224qN\036\224\017J\\\343\232z\236)i{R\322S\303S\303S\267\323\225\352E\230\201\2674\236g4\361/\275?\316\343\031\246\027\367\246\371\224\206OzC%&\372<\312B\364\306zaz\215\232\230MF\304\342\242/\306\337Z\202d+\315Un*\t\rWv\342\252\311Q\275B\325\023Tf\232zS\017\335\246\212z\212x\251TsV#\025r.\325i9\253\020\313\345?R*\371\304\366\244\253\022GPj\262\014\034\032\230R\0323\353J8\351N\0370\372S\205<u\247t<\320\0074b\227\024P:\323\250\247R\201\232^\364\240\323\205.(<Q\232P\324n\243q\243y\365\245\337\357@sK\346R\231\016:\322\t=\350/I\346Q\276\215\364\233\351\245\351\205\251\205\251\245\251\205\252&=\3523/ 7 Uiz\344t5Y\215W\222\253=F\346\241cQ\261\250\217ZC\322\230\3351INZ\221jT\253\021\325\270\373U\264\351R\021W\254\334*\037\\S1\363\232\220t\246\023I\236i\340\322\203\203R\002\017\265<u\25101\326\225\224\216{Sz\322\201\212v3I\214\032\\\023@\024\264\016)A\247\016\264\374R\022h\006\220\361M\335K\270\021\357M.G\024o\243}\001\350/K\2734\205\250\337F\352M\324\233\351w\232k7\024\302\364\322\324\233\251\204\323\031\252\0265\013?\0305\014\253\201\270t5Y\352\264\225\003\232\211\215DM0\322\023M4\224\341R\245J\265:u\253Q\325\270\315L:U\233Y\002?#4\367#\314$\n\\\323M4u\245\006\234\r<\032x5*\362)\343 u\243\003\034u\245\030\305;\036\224\233y\243\245/\247\024\243\030>\246\220\212AN\006\237\236)\t\355M\316)\t\'\245\030\342\220\361M\'\212nqHM&\352v~Z\003PM&\3527\323wsK\272\223u\033\351\245\251\245\251\205\251\013Tli\214j\027\351Qn\307\r\322\240\224\000r\275*\263\325F5\023\032\214\232a4\204\361L\315\002\236\2652\032\231}\252d\315Y\216\255GS\212\236\334fQS\3101!\3157<R\023L\315(4\271\247\203R\003R+qR\344\343\232Q\307Jp\03194\340\010\247\001\232B1IG\265!\244\245\006\226\220\235\304SI\346\200\324\241\251I\3150\212c\036j2\334\320\016i\305\276\\Rn\245\315&sHz\323\t\305&\3527\321\276\220\2654\2654\2654\2654\232\215\215F\306\241j\214\221\336\253\310*\213\032\211\25264\302i\244\323riA\247\251\251P\324\312jh\315[\214\325\244\251\207J\232)60\"\2479\221\2629\246\367\305\006\230i3J\032\234\246\245S\315H\016jU\3509\251\027\337\221R\002:b\234y\342\201\220y\245<\323OZC\301\240\363M\"\212L\321\232i84\233\217Bi\273\260i\333\361\322\220\275F\315\236\365\036y\245\317\275.\352L\363N\006\220\232n\352i4\302i7Q\272\223u\033\251\244\323I\244\317\024\323Q\267J\205\252\026\250\211\347\232\317cQ1\250\311\346\230i\244\322f\226\236\246\245S\305H\246\247CV\2435n3\322\247^\224\345\353\212\322\217\313K3\317\314j\256~j\\\346\232\324\302y\2434\360j@{\324\252F=\352U<T\240\364\305J9\247\001\3158\014\321\212LRc\332\220\375)\017Ja\244\367\244\'\212a<SKS7\322n\240\2650\232L\373\321\2327S\263\225\310\024\252\300\036i\031\275*2\324\205\251\245\251\245\251\245\250\337F\354\320Z\232M74f\230\325\023T-Q5e\223Lf\250\311\250\313sI\236h\240u\247\203R)\251T\324\350j\314f\255\306j\312\364\247\023\216j\365\216\331Q\225\215G*\354\224\257\245 #\024\3265\021\353H\r=[\232\225Z\244SS)\033G\255J\246\245S\305H\032\236\r.\356\306\234W\003\353L>\324\323M\246\232a\342\230\324\302i\204\320\341B\202\246\242\315\033\251\t\244\311\2434\231\347\25586)\\\343\2453p\307^i\205\251\245\251\245\251\013SwQ\272\223u.\352ijn\3527PMF\306\242j\205\215d\261\250\330\323\t\246\023I\232)GJx\247\212\225ML\206\254\306j\324f\255\241\342\234\307\212\237O\230\013\260\t\342\264nmZc\230\2278\364\2522#\304p\343\006\242\335\232a4\314\363OSR\203R\251\251T\324\312\325*\232\221M<\032\\\346\235\274\343\004\320H4\323M=)\264\323Q\234\232a\250\332\230M34\204\322\023Fi(\316)\245\251w\361L\'\232ijB}\351\205\251\244\321\272\214\322n\2434\023M-I\273\336\215\336\364\206\243cP\265b\261\250\311\246\023L&\200iA\247\216\264\365\247\216\225 5*\032\260\206\254\306\325j6\251\031\262*%\220\244\241\207j\3504\375b8am\340\037L\326m\355\351\271\270/\3335\\=!zM\324\3655*\232\225MJ\246\245SS)\251T\322\346\234\032\224\032\\\321\232i\246\232i#\031\250\311\250\311\346\230\325\033S\r74\233\251sK\333\212c\034\034SwRn\244\'<S\t\244\3154\232i4\231\367\245\315\031\2434\231\246\223M\315\033\250\317\024\3265\013\032\302f\250\313S\013SKsI\272\234\rH\246\245Zx4\360rjU\251T\324\350\325a$\300\251<\312i9\2401\035\351\300\323\267R\027\240752\265J\246\245SR\251\251U\252U5(jpjvE(4\264g\336\214\373\323[\332\230i\215Q\223L=)\215Q\223Q\223I\232PiwqH\307\217z\214\223\212ijaj3\336\232Z\220\232i4\231\024f\235\232\t\246\223\212i4\322i3\317Z7PNj6\256t\232\214\2650\265&h\006\234\rJ\246\245SR\003OZ\220\032\221MH\255R\253\323\304\224\360\364\241\251\301\250\335F\352p5*\032\225Z\246SR\251\251\024\324\252\325 jxjx94\372\\\361I\232L\2123Mj\210\222)\214}\251\204\367\246\023Q\261\250\233\2453u.x\245\007\232\225\223(\010\252\344\3434\306\343\361\246\023M\311\307\024\335\324n\242\212L\342\214\321\232\t\246\023HM74\233\250\335\357M&\271\247n*\"\324\233\250\335Fi\300\324\252\325*\232\220\032x5 4\360\324\365jxjxnj@\324\273\251\341\251sJ\r8\036jU5\"\232\231Z\246V\251\024\324\200\324\212j@i\312i\341\251\331\244\315&M\031\367\244&\243c\315FMDN\017\024\205\363\326\243c\305F\304\032\211\216(\031#\255(4\361!\306)\034|\271\250\030\361\212\214\2657y\035)\013qH\r;>\364\271\240\363GJi\244\315!\246\223L\'\232i4\233\251\013W0\355\223M\315&E&is\357J\rH\255S+qR\251\3434\3654\360i\340\323\303S\303S\203S\303S\203S\303S\203S\303S\301\342\236\rJ\246\244SS+T\252j@j@\324\375\324\360i\300\323\263\357FM\031\367\244\315!<Tlj&5\0214\322i\244\373\324lj6<sH\030\003\315/l\203@l\034\324\276p1m#\232\254\307\234TLj2\324\007\3004\003\306E8\036\306\215\324\273\251wR\023M\244=)\244\323I\246\032a4\233\253\227-\223M\335I\273\2323N\315(5\"\232\225NML\rH\r858585<585<5<585<5<5H\rH\rH\246\245SR)\251\025\252Ej\2205=[&\244\006\236\032\235\232\\\322\023M-F\352\215\215D\306\242cL&\232M0\232\215\2150\261\315J\214\n\340\367\2460a\317jh~)\214\325\0314\302i\273\251\341\206\336:\322\344\223K\223\334Q\232L\322\356\244\335A<S\r0\232Bx\246\036\264\322k\223-\3054\265(4\271\367\245\006\224\032\221Z\246\214\361\232\231M<\032p4\340iwS\203S\303S\303S\303S\303S\303S\324\344\324\240\323\301\251T\324\201\252@\325\"\232\2205H\032\236\246\244\rN\rO\r\305.\352\013SKSwSKTlj&5\0314\302i\205\251\205\251\231\245\007\217z\223v\341P\236\t\3050\232\214\2654\232i4\240\324\200\340\360i\373\263Hx\246\223M&\215\324n\244&\232M4\236i\244\323Mq\345\2517Q\276\234\032\224\032p5\"\234\232\235MH\032\236\032\234\032\234\032\215\324\241\251\341\251\341\251\341\251\341\252@\325*\236*Ujx5\"\265H\032\244V\247\206\251U\251\341\252@\325 jpjpj]\324n\244-I\272\232M0\232\215\252&\250\311\246\023L-L\3174\240\322\207\303sC\234\214\216\265\t<\3233\216\264\302sHzQ\236)CT\212\324\377\000\274\277\312\232})\204\323I\243u&h\3154\232i\244\315qE\2517S\201\247\006\247\003N\006\245C\212\224\032xj\220585.\3527R\206\247\206\247\206\247\206\247\206\251\025\262qS\003R+T\200\324\201\251\341\252Ej\221Z\244\rR+T\201\251\301\251\341\251\333\251wQ\272\220\265&\357zBi\271\246\232\215\215D\325\033Tf\232\017ZM\324\204\364\247\356\310\305D\307\006\230M7\214SsI\232\001\247\206\251U\251X\367\025\031\351L=i\2714\271\2434\206\233M\256\037u\031\247\203N\006\236\r8\036jPi\341\251\341\251\341\251\301\251wQ\272\234\032\234\032\234\032\236\032\244V\251P\367\251\203T\212\325 jxjxjxj\221Z\245\rR+T\201\251\301\251\341\251\333\250\335N\rAjij3M\315!5\031\311\250\330\324lj3M\355M\3474\016h&\232O\0353Q\036\231\037\2254\234\322f\214\361IK\232z\265<5!\246\232a\244\2434\244\346\220\364\246\032\3417R\203O\006\236\r8\032\220\032p4\360\324\340\325 jP\324\273\250\335N\335J\032\234\032\244V\251U\252el\n\2245<5<5H\032\234\032\236\032\245V\251U\252Ujxjv\352pjpjv\352\003R\356\244\335F\357zL\323I\247\2466\234\323\n\007REVpT\342\230\324\314\361L&\215\324\023\3050\232i=\361M>\242\233\324\322\023\317\024\231\2434\240\323\303S\201\310\305!4\323\322\222\2234\003KM5\300\003\3158\032x4\360x\247\003O\006\234\r;u85<5.\352]\324\006\247\006\247n\245\rR+T\310\334\346\246\rO\rO\017O\017O\rO\rR\006\251\025\252Tj\2245<5<5;u8585.\357z7Q\237z7Q\237z\017Jn\342(\022`\021\353C&\344\316EVpGZa\351Q\232a4n\240\234\323\017\024\334\343\232C\216\242\223\004\216)2i(\315(4\340\324\354\320Ni\246\222\212RsI^z\r<\032p<\323\301\247\203N\315(4\271\247\206\245\335K\272\227u(jpjpjpni\341\252tl\n\225Z\234\032\236\032\236\032\244\rR\006\247\253T\212\325*\265J\255O\rO\rN\rN\rN\rK\272\215\324\273\250\335F\357z]\324\204\323M |Sd;\215B\325\0314\3064\314\321\232\t\342\232h\315&qM4\334\321FisN\006\235\232J);\322\321^v\r?<S\201\247f\234\r8\032pj\001\247\006\245\rK\272\227u(jpjpjxjz79\251\225\252@\324\340\324\360\325\"\265H\255R\006\247\206\251\003T\212\325*\265<5H\032\224585<5.\3527R\356\2434\273\250\335F\352B\324\322i\t\342\243cQ\023L&\230M!4\271\240\372\323I\240r0i\017\024\323\3274\231\244\245\311\245\006\234\r\031\245\315%\024W\235\203\3158\032p4\340i\333\251\300\321\232]\324\273\251wqK\272\215\334\322\206\247\206\245\rO\rR\253T\212\325 jxjz\265<5J\255R+S\303T\212\325 j\225Z\236\032\236\032\234\032\236\032\234\032\234\032\215\324\273\250\315.\3527{\321\272\2234\204\322f\230MF\324\303M4\323I\232\\\322\032L\363J\334\322\000H\3152\203\322\233\223K\232Pi\331\245\006\214\321\232Z\377\331"
-byte_png: "\211PNG\r\n\032\n\000\000\000\rIHDR\000\000\002\000\000\000\002\000\010\000\000\000\000\321\023\213&\000\000\004RIDATx^\355\335as\2420\020\000P\207\376\377\237\\\346\346\254\236\225\023\205\020`\223}\357\333\341\264\232d\223\335\004\352].\000\000\000\320\216az\001\000\000\200\236\331\006\3466N/\000\000\335\222\367\001\000\222\371\232^ \007\225?\000\247\220\200\000\002\361\034\010\000\000\000l\347\320\363\265\321\301\003\220\210%\017\000\200\030T\246\341,}N\337\001S\237\214+\000\360Dq\000\374\257|\'oMiR\225a\253\362K\000\000\n\250C\222\023\000\313\275\332\352\351\277\354^E\005\275\032.\337\323K7Y\343 k\273\001\240y\2228@8s\373M\330\231\252\340\255\361\247\207\364\022\244\324\351\324wS\013 \214N3M\017>d\313\017//u^\000\234\367\316\274R)\240\272\247\237h\301\341\353\253\211\021\307\341\203\017t\301\332\321\240\263\222\357\375}\253\004\315\322\357J\343\243-\343\261)\2266\375p\\q\233u\033i\317s\000\360\317\352* n\232\343\267\325\003\013ley\004\232\021\277Np\346W\333\320\300\250\223\234\020=\234\342\025(`\351\200\246|\230\262\037^\256g\356\215\032-\000\303~l\367\3779F\330)@O\204\331\223|\335\221\257\305\000\311\314m\021y\341\264\316\252|\243\366\247\035\343i\315a\245\020#\245&\204\276\205Xh8^\345\n\003VQ\\\204`\375\007\256\246\213\301\364\337,\244\343\n\335;\356Z\035\350E\310e\260/ %\331.9\001\000m[_\275\254\377\211\\\364\317\341t\371\361\3649\027a\000\3752\273\201\217\234\202\003\320\021Y\r\322\263\014@c<\235\000G\030\343\375m\336 iW\325\352\367\007J\002\225T\350H\023\262-\317\213z\205\000\000:eu\007 \222\277yi\274\214\276J\260D\272N\233\253b\322uDgL\377\243\305\354\360\271\371\r\300\216\336.\276\236 o_\314\234\017k\335\"y\020\321\200\342\004\000\000\000\240\224\023V\000\010\307\215\017:\242\332\004\330\313\212\025Vm\321\243\025\001\360\244\325\257\230a\336\252\031^\0328\264\312\210\003\301]\277\337pU*;Z\350\017\267F\314\206\310S\000\244\0263=\003\320\001{-\332u-\2206TI\242\277I\033F\234\0164\372\345UV\033\200\014\332\314QT#\000\016\320H\'\337?\346\323\307\r_\017\036\334\271\007\277]\004\t\233\014\354/|va_\033\003@j\0028\234\245\227Q\024\000qY\240\222\373\035\000\202\001b27\001\310@\276\003\000\0008\311\306G\321\032c\373\t\000\000\3009\276\246\027\000\000\000\000X\"\327c\r\000\000\000\241y\026\033\000\000\232\340\356\n\000\313L\017{\366\316 {\377~\200r\323\025\021\000\000h\202R\036(e\375\000\000HK)H\337\276\247\027\266\231\2350\263/\000\000\000\307\363\210vr{\006@\370\335\337\236\215o\314\020~\260\000\330\217$\000@\"\366\201\233\364R5\364\322\016\000\250Fr\004\323\000Rq8@6\2451_\372s@\016*hh\211\031\013\220\217\265\377\215\336;\347\247}\275\267\022J9\360\002\310Ju\004\271\335\326\200uK\301\373\322q|\377r\24166t\2734}w\321{\025\330\213\331\017\000\273\220b\tmv\337*ry\" \000 \225\331\"\021\200\336\331\375U\022=\227\032h\000\000\200\276\335\367\245\321\367\247\034C\034\344\346\034\010\000\000(e?\271T\274\236\252\271\027,h]\315\267\007\3261\377\222\023\000T&\244\000\000\000\000\000:Up\037\030\270\270y\002\300Y\276\246\027`1\321\003\000\000\215Jy\220\357\004\366!e\000\000\000\000\000\355q\240\003@\021\247\3407\2113i\342\246\003\300\203\204\010\220\214\335pb\006?9\001\300\203h\310\352:\362\206?/c\017\300E:\000z7\270\357\005\000\000\000\000y8\r\004\200\\<\362\000\000\000\000\035s\350\017\000\000\000\000\000\000\000\000\000\000\000\375\030\374\241\000\000\000\000\260\220c\004\000\000\000\000\000\000\000\010n\364\337\010\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\017\177\000UW\201D\216\024\213\243\000\000\000\000IEND\256B`\202"
+byte_jpeg: "\377\330\377\340\000\020JFIF\000\001\002\000\000\001\000\001\000\000\377\333\000C\000\003\002\002\003\002\002\003\003\003\003\004\004\003\004\005\010\005\005\005\005\005\n\007\010\006\010\014\013\r\014\014\013\014\013\r\017\023\020\r\016\022\016\013\014\021\027\021\022\024\024\025\026\025\r\020\030\031\027\025\031\023\025\025\025\377\300\000\013\010\002\000\002\000\001\001\021\000\377\304\000\037\000\000\001\005\001\001\001\001\001\001\000\000\000\000\000\000\000\000\001\002\003\004\005\006\007\010\t\n\013\377\304\000\265\020\000\002\001\003\003\002\004\003\005\005\004\004\000\000\001}\001\002\003\000\004\021\005\022!1A\006\023Qa\007\"q\0242\201\221\241\010#B\261\301\025R\321\360$3br\202\t\n\026\027\030\031\032%&\'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz\203\204\205\206\207\210\211\212\222\223\224\225\226\227\230\231\232\242\243\244\245\246\247\250\251\252\262\263\264\265\266\267\270\271\272\302\303\304\305\306\307\310\311\312\322\323\324\325\326\327\330\331\332\341\342\343\344\345\346\347\350\351\352\361\362\363\364\365\366\367\370\371\372\377\332\000\010\001\001\000\000?\000\372\231pH\251$\267VL\367\254\371\020\207\251\243^*@\224\241)\301i\341i\3060y\244\333\216)\343 \324\2523\332\236\02752!52&*t\025:\n\231jt\251\322\254GV\024\362*u\'\326\244d\312\214\363O\207\003\203\326\255\306\265:\361\322\244\rOV\247\203J\335*\007$\034\325\3339\303\200\032\245t\303c\265S\270\0058\246[!w\305]\272\265T\207wz\311nM7o\265\030\2466\rFP\032\206H\306*\263 \315W\230\n\2432\325\031\226\251J\225NU\305P\234u\2522\216\265RJ\2512\325\013\204\310\254\233\230\205f\316\265Be9\252\356\225]\327\025Rd\311\252\355\025W\226*\254\320\325yb\3005\365#\302A\310\246\311\273\313 \325R\236\265\"-H\006)\301y\247\204\247\004\247\004\247\204\342\235\345\360=jD\216\244X\352P\265\"\255J\242\245QS \251\320T\350*h\315XNjt\346\255F\240\365\250\230\217\264|\275\252\344m\305N\032\236\r=MH\r:\243qL\211\366=i\304\373\2275\024\310$z\273cn\001\030Z\227U\266\333\000#\245`\024\346\232S\232B\225\023\246*\026\250\036\240u\252\262\214\346\252J\005T\225EP\234u\252R\214\325+\204\2522\245T\221qU&\025\2378\353Y\267 \020k*u\252R\255Uu\252\316\231\252\356\225\003%B\352*\264\251UeN+\352\245\\\216j\013\224\035\252\231L\267\035\251\313\035<!\247\210\310\247\005\247\201O\013R*f\236\251R*b\236\026\236\026\236\026\244U\251UjU\025*\324\351\305J\206\246\363\02602jd\273\214\016\033\'\332\201$\3236\001\332\265j\030\266\017z\262\207\212\225[&\236\246\244\006\244SO^\224\244dT\016\2705z\315\267.)\322\002\255W\364\371\3600EZ\325\001{P@\342\271\306\0304\334PFj\'J\201\322\241d\252\362.\001\252r\361T\2465RS\232\247*UI\027\0315Ja\315S\2262{U9b\252s.3Y\267\002\262\256FI\254\351\327\223Te\\\232\201\243\250Z\"OJ\257$\'=*\007\204\325i\"\307Z\255(\364\025NQ_S7\000\021T\346\271\303`\212\022E\177\255O\034y\024\355\200\032\\P\006i\301i\333qOQR(\251TS\200\247\201N\000\372S\327\351O\\\324\212jU\'\322\236\r\014\304\214\003P\000V`\247$\037Z\330\202\330*\203\305[\213\013\305N\246\236\rH\206\244V\251\025\252E5*\323\307\"\221\243\317jD-\021\342\254G)~\325n\334\225a\305i\311\373\333B\007\345XR\301\363\032\204\305\212M\230\246:\324\016\225\004\240\000j\224\325Ja\326\251L:\325G\034\324N\225Vh\352\243\304\rW\226\032\245<X\315f\\\'Z\314\271Lf\262nF\t\254\351\206j\234\213P\224\346\243r\027\245@\334\324\022\020\265Nc\232\2450&\251\312\247\232\372~I\225W\232\310\277\273^y\346\262$\326E\274\231\335Z\266^\"\216e\0370\253/\251)\3440\305:=H\023\311\247\235AA\353SCz\257VVe=\352E\225}EYL0\247\205\364\247\016\r8\034S\201\305H\r8\036i\353O\006\226\242\232S\030\315V\223P\013\"\022y\255\353\013\3012\000j\362\234sS+f\236\246\244^\325*\324\253R\255H\265*T\200f\232\353\305If\001b\r\\\003\r\355V!-\236:\032\202\352=\215\315Sn\264\302=\2526\025\004\240\325II\357T\345\034\325I\005S\231s\332\252\272\325y*\264\225ZG\002\253J\331\252S\221\315f\\\340f\262.\3339\002\262\247^\265FT\252\317\025D\361b\253\274U\014\211\264U\031\333\035*\223\344\324\016\234UiR\275\376\343P\\\036k\235\324u\034\261\031\254+\271\236c\305W\207\3550\266T\234U\370\365\013\240\270$\325\230\265[\205\352\r]\207[c\215\340\212\335\32258f`\030\340\327S\r\234\023\304\n\3103U\256\254\204G+%6\t\314g\226\253\251{\216I\310\2531\314\262sRc=)v\220)\300S\307J\220u\247\257ZxRj+\230\267%r\267fD\277U\'\214\327U\245\313\265\026\267a\2202\373U\204;jE\344\202*U\025*\234T\252\325\"\260\251\024\346\245J\231zS\266\356<S\342\214\306\340\325\266\003\031\025=\271\351\232[\330\214\211\220:VaB\r&\312\215\222\241\2213U%\212\252K\026*\244\211\355T\346Bj\244\221\232\253,g\232\251,dU)T\203U%<U)\332\262\256\2379\254\311\372\232\317\225\t5VD\346\241d\025\014\213\232\253)\3329\252\023\276j\224\213\232\256\311Q\262T\023G\2055\351Rj{\327\255g\312Zg\357S\303k\300\315]\216\331N\006*e\264\\\362*O\262\'\245\037`F\355J\272\177\226r\274\032\277oys\000\332\034\325\250\257\356\035\276c\220j\331\216W\\\251\252r]\317lp\331\300\253\372v\254]\205t6\367\"@9\253H\374T\212\303\275H\270\364\251UE=PzS\366\3243\260U9\256b\375\322k\325\333\311\025\271`\244 \255[y\212\032\323\212@\302\247F\301\247\207\247\207\251\003\324\212\365*5XF\251\003\325\250\007\002\255*qC\234&*8f>h\035\253X\200\361\361Y\2671\340\232\250N)3\232c\001U\245\002\252H\001\342\252\313\025T\222,\325Ic\301\252\262G\223U\345\207\212\313\271\217\031\254\371\226\263nA\346\263\'\031\252\023&*\244\211\232\255$u]\343\305S\234\3435\2371&\252:f\241t\250\035*\"\225Zq\332\273\310\355\252t\204)\351S\250\000\361\322\245F\301\251\325\303\034\324\252\324\360\300T\250sS\000\rY\205A\030\002\256\243\237(\021\333\255$\210\263\247AY\0270\265\253\356\217\212\275\246k$0V<\327Gox\035A\006\255\244\342\254G(5b7\006\247SN \001\311\305dk7\311o\t\333\3115\317i\200\317r]\273\232\353\255\021v\201\232\264\253\363qW\242\007h=*\302\277\025(n\375\251\312j@jEj\231\032\246V\251c%\230\n\324\201\301P1VB\361QM\322\2504\246\031\003\036\225\257gv\262\305\327\365\250.\230\347\232\246NM5\344T\025]\345\3348\252\263\263\020y\252O\220z\323\325\267\'5\013\212\255,y5]\342\025VU\0305\231w\037Z\313\232>\265\235q\027\265f\317\0363Y\362\305\315V\222,UIR\252\312\265\2374d\223T\344\213\031\252\317\035Wt\252\356\265\024\203\002\250\3142y\257G\\\001JH\024\007\243~*D\233\025*\315\232x\226\245\216lU\230\346\315Z\216|\256=*\314w\005;\361NY\260\304Q2\211V\262g\263h\337r\344b\256\330j-\016\003\032\327MPp3\326\254\307\251\020G5~\337S^2j\347\366\264h=\352\215\366\263\301;\253\234\274\276\226\376]\203\356\346\265\364\253s\022\251\"\267\341\223h\025r\031\0015z\031\0161Sg\245H\033\214v\247\253T\212jE5*\232\225^\254[>X\326\214\007\221\353Z*8\246H\271\254\275E\010S\212\216\302VD\310\352:\212\325\202Ar\274\255Cqn\343$)\254\251\313+r(V\310\250e\"\253I\327\212\205\230\217cQ4\307<\324l\371\351P;\021U\245\3475Fu\315g\317\025g\334E\326\263\'\207\255P\232*\2452\340\032\245\"\325Y#\353T\345\217\031\252r\246j\244\251U\244J\207\312\'\265V\271\001F+6f\257B\022`SZJo\231G\233G\233OY\360qS,\246\236\263T\351?\275[\206~*\300\237\276j\330\220\262)\030$\324\211&z\323\312\007\355Q=\222\267A\3156K&\214\256\017\024\201\345C\216\270\240^J\017\000\325\250\347\226U\350sO\373\034\223\0343`U\333-5c#8\255dA\030\030\251\322J\267\000/\203\222+J\33759n\224\365o\316\245S\310\364\251\003\017Z\221_\025*\270\247\347\"\246\265|1\025\253n\334\216kJ7\316*R\271\025V\342\r\302\263\244t\260,\314\001\006\252\331x\201\"\271\307\360\223]L\027q]\305\320g\265g\352\026\013\202Eb\3106\022*\273\266sU\231\260i\010\310\250eL\325I\001\024\302\331\025\013\363U&\030\252r\343\025Je\315g\\\240\025\225p2MP\2252j\254\211Ud\025VD\315T\2260*\244\261f\253<\007=*\t\361\032\221\336\261\256X\263\032\245 \256\360\2751\244\305Df\301\240MK\346R\371\207\255J\227\007\216j_4v\251\222\\\325\204\230\212\267\034\371\\U\230\')V\022\340\263f\255\303>F*\306\354\212\232\000\017,2\0055\243B\307\034\212r\332\257\245Z\206%LqS\204\365\251\025\260jP\364o\301\251\342\271v f\266m.\014i\226O\306\254\t\325\316I\305=[\234\366\365\247y\341OZz\317\273\241\251Q\203\177\025J\261\372Hi\303\314^\214\010\251\255\346e\220n\342\266 \'\000\366\255(_8\253\210\331\024\254\271\254\177\021[\227\2678\025\310Gl\342@Gj\354t\260\311l\205\215i\271\022\306\334\344\342\271\373\305\332\346\263\231\2715\004\206\204l\212I\001\252\262\202\001\252\325\024\225^S\221\315R\230zU)Ef\335\034\326d\303\223Te^j\244\250M@\321T/\035U\232!\326\252H\200\032\2553\200\010\351Y\027\222\216k\016\342|H}*\273\334\212\356\032LTo\'\025\003\2774\202Zp\232\236%\3159e\251U\3623R\307.*\322I\232\261\024\2705r93Va\233c\003W\026e\316A\253).EOms\261\260G\025a\212\023\225\357V\255\300e\311=)e\230o\0304\341/\024\242Jp\226\22495,Rm`k^-C|!6\364\357J\214I\253)1\003\024\242NsR\211F*D\220\n\2369\317\324T\353.{\323\267\037Z\325\323\356r\200\023[6\362\202\243\035j\334rU\210\344\317j\315\327\357\021b\331\237\230\326\034\021\0162:\232\350aEKu\307Jql\036\017\025\231\251/$\372\326;u\250e\244\210\323\232\252\334\036*\251\316*\031\017\025VSU]\275j\264\240U\013\210\301\315fM\027Z\245$y5\013\305\301\252\222\246\321\234U)\037\002\251O>3\223YWw\312\200\363Y\027\032\211$\326m\315\333>k2RI\317z\257!\342\273\247\222\242ij&zg\231\315/\231\232\004\270\357R\244\325*\310EL\222T\361\315Vb\237\346\031\351W\"\230g\255[\215\367U\210\344\037\215[\212n*e\223\234\325\270\347\336\240\001\310\251\242\230\203\214\324\244\242\200I;\273\212\224\272\030\301\007\232`\220\324\212\365\"\275M\033\002k^\310\307\345\234\3435n\031c\000\202\271&\202\300\032L\212r\265J\231\251\220\324\312\3652>{\325\233Y\314O\317J\333\267\270\000\002*\332_(9\355P]\370\212+e!I\316;v\254H\256\336\376r\354I\031\255A\036#\342\264l\234\311\026\323\332\225\233kUK\342L|\372\326C\236j\0319\250\324\3554\342\340\325Y\333&\242b\000\252\362UIN*\234\215U\235\252\264\244\032\245.\016j\214\200\003U\246p\265\237s6A\305d]\334\254c\2575\207wt\362\023\216\005fL\t\316MR\225j\254\213U$Z\253(\256\305\344\250\032J\215\244\250\314\224y\264\242L\324\213&\017Z\235$\315J$\305O\034\243o=jhf\0079\353V!\233\025~9\370\025n\t\212\020\325h\334\253\220Tc\326\247Y\362\243\326\255[\314\244\034\236{T\253.\016jR\315/\315\216\005=%\355R\t)\353&jTj\235\036\255C9\365\255\010\2448\025:6\342\017z\260\312\270\004\032EZ\231\027\320\324\240f\236\252sS\000@\253\020H6\220\303\351S\307r\351\307jy\270}\244\306\330>\225\225*\\O!\3349\242\312\351\354\346\331 \305tv\267\036b\014U\373|\253\026\316\0059\233\234\324\027/\230[5\220FMF\365\013\014\232C\220*\264\246\252\311&;\324\r78\252\362\266A\254\351\347\362\332\240k\205#\256*\254\267)\234n\252\223N\243\275g\334\\\252\202sYw\027\244\347\002\263.\257\035\272qY\223\345\216I\252R\255S\224U9ET\224UI@\252\222w\256\225\344\250\231\352&z\214\275 \2234\360\324\341&*x\345\251\325\351\352\365*I\203V\242\222\255G6*\344S\356\000f\256B\370\\\325\250gU\310a\220jH\345\347\212\266\222\344u\251\226\345\220`\036*xJ4e\231\271\246\211I\316:T\221\313VR\\\325\210\3335j\0222+R\334,\213\367\272S\301\332z\324\250j\304l*UlT\310\331\251T\363R\016jX\305O\035I\345\3569\034\032\226960\016\240\217Z\232\343L\206\3517\250\347\326\231e\021\267m\215\310\355Za\370\246\264\225J\346s#\354^\224\337\'\013U\244Nj\273\214S\0108\315A6\002\325\tj\254\240\346\253J\3142\001\254\351\316I,j\214\304\036\225M\300-\311\305U\271G\035zVt\265Jc\326\250\313T\245\252\222\n\247(\353T\346\252r\3259Fj\234\243\255n<\225\033=D\317Q3\320\036\244W\247\206\315J\215S\243\323\367\323\325\352\304r\325\210\345\311\253\260K\322\257,\204\016jx\244\004\216j\362\310\230\301\341\251\311.\rXY2)w\221\322\255Y\314\027vOn\224\370Hy\016N\005Y\211\343\'\222EXB\024\360\331\253Q=]\212R\243\212\265\023\027\253+\307\0254|\036MK\270S\325\375*d\226\245Y3S#\324\351%Y\211\263R\271\000S\254\356@}\205\2705dF7\023\236i\333\361L\221\232N\027\2551!\021\236z\322\273\000*\234\257\270\234T\0143\326\241g\306j\264\215\234\325I\016\357j\255.0sT\245\352j\215\302\206\315g\3141\232\245.j\234\254\335\315S~\271\"\251\\\235\314H\030\252\254\341\007\335\004\326|\334\346\251\313U&~1\212\2431\315R\227\212\251-T\226\265\035\352&z\215\244\250\231\351Q\352R\303\024$\234\325\230\336\245\337@\222\244Y\252T\222\255G%[\212Lt\253\2518*2MX\212O\230sV\274\342\262g9\251\314\312H+S\307&EN\257\232z\271V\253\t&\346\311\251T\355\374j\324Rt\253q\313\212\271\013\344\212\323G\215P`\363O\022{\323\204\204\3645\"\271\251RLT\213/\275J\262\324\3136*d\232\255E6*G\224\225\250#\220\211\205i\233\262\201M8\334\007\031\025,3\205\214\236\346\230&\334j9\030\265D\313\201P;b\252\310I\351P\230\\\232\206H\231N1T\256\t\034b\250JMT\224\365\315Q\233\275R\224\n\251\"\202MT\237\330U\031\201\035\252\214\335\rP\224\325)MR\224\3259j\234\246\252IU%\025q\336\242g\250\331\3526z\026J\177\233NY9\251\226lT\2135H$\31585M\034\230\2531\311V\242\232\256\254\301\224q\315Z\202U\340\021S\203\207\3009\025k\005@\315Y\205\370\251\343m\307\0250\310\352:w\251Q\352e\220\021\327\232\263\033\0223\212\235$\301\346\256C7\025m%\310\353S\244\335\263V\021\252A.:\323\204\331\247\254\265\"\315R\254\376\365b9\275\352\3343U\241 +PLJ\235\302\255\332L\262DCU\210Sz\225\007\334Sa\230\020U\217\"\246h\231yS\370SC1\034\361L~\235MW\221\273Ug\'\261\250\262\300\023\232\212Gu\'5Zi\0279\333\317z\2430\004\203\217\255UtB\t=j\204\240\006\'\025Bq\223\322\252\310p\016*\254\213\222I\252w#x\254\331\341 \032\316\23623T&\025NQT\345\025NA\232\253 \305S\226\245w\250\231\2522\364\302\324n\243}9d\247\211\251\353-L\262\324\321\311\232\237uM\033\325\250\233\245\\\216L\0001V\341l\200GQW \234\003\226\0258\224\2663\322\247\215\361\364\251\326Nj\334w\004\014\036\207\255L\241H\340\323\243\033\233\031\253\221K\345\014\003\305M\346\207#\212\260\222\360;\n\2369qV\026PH5e.=\352Q(\"\234\036\234\263b\236&\251\021\363\315Y\215\352\334Rb\255\244\334T\241\203\212\217\3156\307\246EZ\206\361xd\340\367\024\263\243&%\037t\325\270&,\200f\236\315\236j\264\262\363\305W\221\262*\002\304\032\214\236i_\014\265FU\034\325Y\022\252J\235j\224\311TfJ\251\"\325IES\232\250\316+:q\326\263\347\031\252\023-R\224UI\026\252J*\244\213Q3\324L\364\302\324\335\364\273\3054\265&\372<\337zzI\315N\262U\210\244\305XY3SE%[\212Z\267\024\270\2531K\203Wc\313\000s\326\256,\245Wa\352*h\217J\264\252\031\200\006\245\306\321\234\346\245\211\217\004\236*x\345\332\340\212\263\347\007|\221\217\245Jd\371\370\301\251VB\016\t\251\326SV\240p\303\223S+\014\324\213%J$\247\211)C\234\324\311!\365\253\021I\357Vc\224U\250\245\317z\263\034\2705c\211\206)\237f*\337#\021R\334]2Z\371g\222N*[V*\200U\255\377\000-BFr{T,\352\006\000\311\244X\374\300O\245V\225\n\223\221P\0316\347\322\241\220\214\325ix\252\262\032\2470\2523\n\247-R\232\252H*\234\312*\205\302pk:e\254\371\224\325)P\372UIET\221j\244\253T\031\2526jc>*2\364\236e\005\363H\317H\032\236\257\212\261\033\325\204z\231$\315N\257V#\223\025n)j\334Rf\256\3036\334U\250\231\244n*\334nGZ\260\217\315L\037\035\rZ\206Pc+\306jH\201\'\003\232\225_i\367\251\026L\232\221\037\232\260\222T\351/\275O\034\276\365:\311R\253\324\201\351\336g\275H\222T\251\'<U\270\344\000\n\261\034\2705e$\253\226\263\001\234\366\253)&r}j\264\362\356\231W\323\232\271\014\243\212\260\347\021\344SL\233\243\300\340\324\0016\361N\307<qFC\374\255To-\214\'#\356\325\026\346\240\224\343\212\253!\353U&|U\031\233\255R\225\272\3259MU|\325Yy\252\223&j\214\261\363Tn#\252\023F@5FU\252r\255T\230\016\325\222\306\243c\212\211\232\243&\232Z\234\017\024\322\324\003N\007\025*=N\222U\204z\260\215\322\247G\2531\2661W\"\223\212\271\013\346\256\303!\r\220pj\322\310Y9<\212\261\033\340T\361\2608\253\031\nx9\251\341r\255\221\332\247w\336\331\003\002\237\030\001\271<S\263\206\300\251U\361SG%N\222T\351-N\217R\t)C\363R+\363S$\231<\324\361\311Vc\222\255\305&j\312>\034\014\365\255\010\216\341U/\321\300\334\203-T\241\324\245\211\260\350x\255Hu\210\335v\223\203SA9\222C\351S\203\223K\322\214\007\344u\245p\'\215\220\365\305dM\001\215\210\"\252J\242\251\312\235j\224\361\325)\023\255T\226<f\251J\207=*\264\234pj\234\303\234\324\017\202*\234\342\250MT\'\3475BE\353U&J\245\"\326\031|\324L\325\0135F[\2327R\203\2321KJ\264\3655*5XF\251\321\252\304mVcl\325\270\232\256\301!^\225~\325\306\356j\334g$\216*hH\'\223O\363\n\232\273\004a\342\335\273\237Jt2\025lv\253\3628\362\324\212[b\035\260M9\324\2419\241e\251T\232\2367\305L\222\325\204\227\212\225d\315H$\030\247\253\342\245F\251\321\352h\336\256E.*\324o\270\212\323\205\372U\201\030n\264\206\301X\347\024\035\035Ko\300\253\260E\030\217\005p}qU\356\225\240\372\032\250oppF*H\256\201 \203V\031\371\016\275\372\3247 H2+:h\272\3259\"\025Jhx\353U$\204\3259\241>\225Q\324\001\312\325Y\343V\352+>x\366\237j\251\"\342\253\311\036ER\232\016\rQ\232\021Tf\210`\326|\313\324Vm\310+\234W0e\2464\325\023I\232az\004\224\365\222\244\r\305\033\251\300\323\307Z\225OJ\225\033\0252\267J\2327\346\255F\370\253q6M]\205\270\253qI\212\267\024\225a\036\246V\334j\300c\027\000\325\210\016\356\247\0257\232zv\251T2\250n\3254r\344\363\337\326\235.\325#i\317\255=\035\202\343\034T\312\330\003\006\236\257S\244\274T\253/\275H\262T\311%L\255S#\324\310\370\2531\311W!\223\246+J\332]\303\336\264aj\271\035XQ\221R*\372\200id\205%\306\345\2527\032bHI\013Xw\226S[\313\230\363\266\237k|G\311 \305Z.1U\245\301\252r\255S\225j\273\261Q\212\245>I5Fl\325)GZ\2512n\006\251H\274T\005j\264\313\326\263\347\025\2378\316k>e\353U~\317\275\362G\025\307\315\002#\360\300\255DmC\236\033\255$Ve\333\031\250\356\240X\007\'\232\247\031\334\330\355Vg\204\302\252s\234\323\025\363\305)$S\321\363V\025\270\247\255J\016)\352\330\251\3435f#V\243j\273\013\325\270\332\255Fr29\2531\275L\255\212\231\0375n\026\007\251\2531H\241J\221\370\325\230\244P\304\021\362\323I\001\316\321\305?\177 \342\246\363\314\230\036\224\241\261R\243\346\244\251\024\021R#\342\245Y9\253\t/\0252J\rL\262T\351-[\202n\225\245\013\364#\250\255[Y\203\014\326\204MVQ\252u4\372\017\"\253O\010|\344\n\310\324t\361\260\224\034\212\315\267\235\224\354n\242\246v\007\332\240\222\252J\265ZE\252\223-Q\225G5NE\033H\357T\344\371MS\224rj\244\237)\252\263\265g\317\315Q\230\023\232\246\361d\323^-\203\025\346\315\273\326\232]\307zb\\I\03185\014\316\322\234\223K\003\010\216H\315M%\321\224\000\335\251\321\204\336\247\267z\320\232\3229\"\334\244\n\254\260.8<\320P\245H\2075&sJ\246\247F\2531\032\267\031\253P\267J\266\231a\305h\3332\252\373\323\367\374\325*>jdl\032\263\033\325\244n*Q&\0109\253?j\005@\300\315;\206\213\266sC!\213\036\364\253-L\222S\304\325 \233\212\221$\315J\255\232\221^\247G\300\251\243\2235a\036\255C&1Z6\262\347\0035\247k!W\002\265\242|b\255\306\365:\275J\255K\273\"\230\306\252\334\200T\3277r\241/\016\rJFV\241\220b\253\311U\334UI\226\251\312\265Y\220\036*\215\324;I\252\023.*\224\343\212\243/5NQ\315Vh\362j\023\030\\\232\245p\374\361^vTS\031\001\250Y\0054\307L)I\262\234\001\025\"\311&0\t\305I\031d5wp\226\023\223\363\n\2058\351R\201\214f\227\245H\225f#W\"\253)\306*\312g\327\212\267\t\333\200\017^j\316\374\232\221[?Z\231\t\2531\034\325\250\332\246\0074\36552\311\201\212x\224\205\366\247\253\253\'\275H6l\352wT\221\252\340d\342\234T\037\272sM\022m5<sT\352\365\"=X\215\361V#l\325\250\233\245]\267\223\004V\255\274\273\200\307QZ\320M\2203\326\256\306\365:=L\257N\335H\315\305U\270o\224\327>\307\315\271f\307J\220\360*\'5ZA\236\365]\327\035\352\t\000\305U\224\n\250\303kT7\021\356\004\326]\314x&\263\246J\241q\204\006\250<\301MF\322+sT\247\227$\212\243p@\006\274\371\333\006\230^\230\306\233\272\220\363@\024\240T\2109\251Jw\024\203 \342\244\214\363Su\031\244\3075\"\325\210\215[\214\325\270\006\343\223V\023\203\212\265\t\251\203qS#T\350qS\306\325b7\251\303\361OW\251\003\323\303\346\236\246\236\246\245\317#\006\236\222\030\363RG\266@r~n\324\204\030\3175*KS#\363V\221\352\324MV\242j\265\023\343\025\247i.\334\032\326\266z\275\034\225a\036\246W\247\357\244/U.\237\367m\217J\310\215pI\365\245sP\271\250\034\325i\rV\220\325i9\250\037\236\264\303\2021Tnc\0075\231<X\315cj\000\252\265`I7\316Fj)n\031A\250b,\371&\243\270\351\\\004\213\221P2\225\246\023L\245\006\236\275)\300\017\306\236\274T\252r)\271\346\246U\302\203\353R/\"\227\030\247-M\021\305[\213\223\317J\273\013\356\\\n\260\212jx\316*d5:\216*x\300\035jP\300t\251\221\252\302?\024\365p)\341\3015&\010\344r)U\310\352*U\2234\365njM\371\245V\346\254n\310\303\036E m\255\212\235H\030\346\254#\022\271\2530\313\315[\211\352\324rb\265,\\0\301\255h\037\245\\\215\352\312=L\262`R\371\236\364\031*\245\334\231\033}j\231\300\250\235\252\0275\013\232\256\375j\274\234Uw\025\003\016\265\013\034\034Ui\210\254\351\310\346\261u0\0326\305s\313m\373\302MV\276Q\270\001N\2010\225\005\310\3005\347\356*&\250\034`\373S(\247\251\247\365\036\364\3408\251W\201M\251P\346\246\216\244\305.0)\361\325\270\252\355\261\344\232\267\234\032r\234\324\350\325:5L\255\221R)\251\220\324\312\335\251\375\017\275/Zz\226^\364\361+q\232\224>i\341\217\255H\246\236\036\245\363I\"\237\2701\342\245\215\361\326\254\302\344\236*x\216X\325\270\237\003\255Z\215\372V\205\234\233XV\314\017\300\253\261\275XI*u$\214\346\220\311\212c\315\264UW\220\261$\324,\365\0335B\355Q1\250\234\346\253\270\250XT/\322\252M\305g\\\315\266\263\246\270\0075\215w)\221\360:U9p\242\263f]\317R*\341*\215\321\353\\\023\324-Q79\250\310\30578\247)\251T\323\324\324\240dS@\353R\'^*U\033ML\274\323\251\312*\304F\257[\234-N\247\346\251T\363S)\332qS#T\213%L\215S#T\212\330\305K\273=\351\312\325 zPrjU4\360\325\"5H\030b\234\247\232\225\rJ\257\201R\307&\rY\204\356j\270\207\035\352\304oZ\226\030#$\363Zp\312*\374o\322\247G\253)&\0174\307\230e\275\005V2\356l\366\246;\344\324e\251\214j\'5\031\2465B\302\242e\315A\"\342\250\334\266\320k\234\325.\260N+8O\275}\352)1\216j\204\303$\342\253\264}\351\033\204\254\273\263\326\270g\025\013\324-\336\230i\204P:T\212jU50a\212h\357NC\202*\311!\224c\255=*N\264\365\025*u\253\221\034U\205l\324\253\351R\203R#T\203\202\rO\346g\034T\252\331\251\003\324\212\325 4\340\324\365j\231M;uI\031\2512i\312\325*\276*P\365\"\037z\261\014\273M[\212Q\202;\325\310\001fPkJ!\264\3435r\031\366\016kJ\0312\242\254\304\331\"\244\222o\233\332\241.I#\265&\354\nL\346\2023M+Q\272\212\210\361\232i\\\323\031=j\026\342\252\\8QX\227\367\203\220\rs\327\222\006\'\232\246\247\322\221\224\236\265\013\307U\346\342\2539\371k.\364\365\256)\352\273\212\201\272\323\033\245 9\242\234\006\005J\206\235\234\232Z\220\037\224U\233Q\271\3005+&\323N^jd\024\365\341\252\324g\212\261\035N\2309\247/<T\213\326\246Z\220\014w\247\253T\200\324\250x\251T\346\236\0059z\324\310jJr\361O\335N\r\212x~)\342J\225\037\232\231\037\232\265\013\326\205\264\274\203Z\266\357\310=j\342\252\273\202*\374mV#z\220\374\324\234\342\224-;g\265\033)\254\224\306\216\230\312\005F\307\025\004\217U\'\235P\022Ms\372\246\252\252\010\006\271\233\275Kq85M]\2465a#\332(~*\t\017\025FsU\245<Vm\347C\\[\325w\357U\333\2550\365\246\3644\271\346\234\246\245^i\304b\225j@*{f\331 5\243*\253\240aQ(\305L\213O\013\315L\234U\210\215N\264\341\326\245^jd\346\245\333\305(\030\251\026\244S\201R\247Z\224p)CsR\243T\252sJ\0174\354\322\346\224587=jUz\2327\253q5^\205\361\212\322\263\230\003\311\342\264 \227\201\357W\342\223 U\205z\235^\244\014\rH\270\247n\244\3155\252\0265\013\270\025R\342\355b\034\232\305\277\326\326%85\315_x\201\237 \036\265\2135\304\267\014z\323V\330\236MY\212-\225)\351U\344z\253$\225Rf\315V\224\361Y\367]\rq\222\n\201\307\006\253\267z\215\272\323OJN\334\323\227\265O\035+\002\016i\310sR\255K\022\345\205h6v\252\372S\236=\244S\323\245H\253R(\251\243\004b\254\240\310\025!\030\0304\345\342\246N\2652\232RsJ\016*El\325\210\310\247\356\3158\nx\310\251\021\261R\016E7&\234\r;4\240\363O\017R\306\365r\'\253\221=\\\215\272`\326\202\310J\250\3175\251o\'\3129\253h\365:\034\324\351\315N\242\237\216*7;j\273\316\001\353T\247\277U\'\232\315\273\325\025A;\305`j\032\300 \341\262k\237\271\270\232\351\310\031\3052=<\347-\311\253\th\027\265)\210\001La\212\212F\300\252r\275U\222J\253+T%\262*\235\330\371Mq\256*\274\274T\rQ0\2465\003\221N\007\024\360\373zu\247\253\340`\323\366\225>\306\245Njx\2705\242\222\'\222G\361R\026\336x9\025*-L\243\212z\214\324\3109\031\253Q.H\307J{\214\032N\342\245Z\221\rI\212nqNV\301\251\222J\231_525?4\240\340S\203R\371\204S\271 \0322E(jpn\225,g\232\265\033\325\330_5n7\306*\374Sr\010<\212\273i9\r\203\320\326\244o\234U\250\232\255Fj\302\323&\235b\004\261\002\271\375S\304\261[\202\003sXrx\215\346\'i\340\325+\213\331\337\221\236j\224\236|\247\223M[\022\334\2675:Z\252\366\247\030\200\250\330\001PHj\254\217\212\253$\234U)_\255T\221\362j\031_\212\200\276\005U\272\223\3445\311\270\252\322\212\201\206\005D\324\312N\324\231\301\247\003\315H\016jd=3SG\2001\216j\312E\3019\351R.kJ\306\334K\033\036\343\2326\341\216:\n\231W5\"\245L\253Vb\\\014\320\334\223H9\251\000\251\027\237\255H\017\024\326\244\247\241\315L\244\324\310\365(4\355\324\340iI\315<9\333\212\027\255;p\034\032P\0163\232\2222j\304M\315_\207\245N\215\315^\216E\\\023\351V-\356\202\262\346\266 \230\0209\253\361?\275L.\025z\260\030\250\345\327!\201NXf\271\215k\304F\340\225\210\326\020\201\356d\335!5z\033EP8\253!@\\\020)\255\002\230\362:\324\005v\365\2463\342\242w\250\035\352\254\262U)d\252\223I\212\2454\265X\311QH\374Uw\223\002\250\334\313\305`?z\256\353\232\201\305B\324\306\024\316\224\224\3454\364\251\322\254F3V\243\\\212\230%]\261vS\264\016\274T\306&W;\252d_J\224-M\032\016\265)4\230\244\356=)\353\327\212\225pM8\361\322\233F3NPjT85*\324\212\324\374\322\206\305<6i\300\361N\006\227\357P3\232\221X\325\250G\031\025r\'\342\246\rR\302\344\270\025b\3567\2013\236z\322\332\353\333\027k\360\302\256/\211Q\027\2575J\363]\226\343%3\212\243\346\3179\371\230\342\246\212\000*\314`-N\216(g\250\374\322\265\024\223\363\234T\022H\034q\326\252\313!RA\250\032j\257$\231\252\262\275R\231\252\234\255\326\252\310\370\250|\314\325y\244\2527\017Y2t\250^\253\270\250XS\010\3155\270\3152\224u\251\022\247\216\255E\332\256D*\300^\005_\323P\0311\214\236\325,\333\274\302\017Z\2225\342\245\013\212\225\026\234W\006\224\014\320\253\234\201H\277.jD84\357\247Zv\314\214\367\242\201\326\244SR\255-9Z\234\r<q\315(j\230a\226\200\304g\232\025\252E9\251\220\342\255+\201\203S\254\231\024\364\227k\002+E\356\005\315\262\203\367\226\263\246\265W9\357I\025\242\257QV\025\002\256\007Jp\001i\336f(\363}\351|\374Q\347\373\323Z^3P\274\225]\345\332r\rB\367\033\211&\240vS\337\232\256\317\326\253\310\331\342\252H}j\244\307\025JF\346\241f\252\362\265Q\270z\241 \252\357P=D\335i\207\212a\346\231\336\224T\211\326\247J\265\017QW\241\031\253h\271\025{Oc\024\300\201\223S\335\260y\262\0063N\210qR\205\366\251:\n\010\343\236\264*\226\316)H\302\217Z]\270L\323\226\244\2152y\247c\024\335\264m\247\016\265\"\232x9\245\247\n~{R\200)\303\"\202\304\232p\351\357OW\305L\217S+f\244G\307z\225$\315_\265q\345\2675\027\237\363S\374\340\302\236\217\236\rF\362\200H\3153\315\246\031\275\351<\352<\377\000z\014\371\357Q4\271\250\232L\324\016\325\013\265G\346\343\257J\206S\223\307J\2530+T\246l\325I\rWf\3075ZG\340\325\t\233\223PI\322\253I\326\240z\215\251\215Q\236j0y\247\016\265*\n\232:\267\017QW\340\025v5\253\326\t\272Lw\253W\026M\010,\325\034U8\247\0003\317J\t\311$\216)\312\274eO\341FI\\zS\261\306;S\225qO\035x\245\355@\030\240\214\322\205\247\001\371\323\207\006\236\r\003\216)s\216i\350x\346\237K\212ZNjElT\213%?\314\3059%\251\343\271+\306z\323L\334\365\251\026\343\025 \271\343\255F\322\373\323|\352i\232\232f\2442\321\347R\031i\215%D\322T,\365\0335B\354qQ\031x*{\325[\210\312\363\332\251=V\225\252\244\255\305R\230\344\3242\032\256\374\324\017Q1\3050\324g\200j1\326\244QR\250\251\243\025n\021\315hA\305^\214g\025j\326o!\301\255\\\375\256\331\212\271$v5F0C`\325\221\322\220\321\236)G\035)\353\363S\327\221O\024\374c\024c&\227m\033ih\035i\324\264\341\315(\031\245\3058\032r\323\300\315!\342\214\322\206\305\006JP\346\227\315\243\316\367\245\022\237Zw\236}iL\347\006\232&\240\313M\363h\363\2502Q\346\373\323\032J\211\244\246\031)\215&j6z\201\317z\215\247\316\003r\005R\270\353\221\322\251\310s\232\2515S\224\3242\032\201\215B\346\240c\3154\323\037\2454\014S\320T\2503SG\326\255\303W\341\355W\242\251\212\344V\226\226\342<\347\322\230\334\310}\352Q\322\230\306\223u9M<\034\032\225H<\216\r<u\251@\004u\2472\025\301\355M\'4\240b\235\2674\205piq\232P)h\034R\203O^\264\374\001A$P\016i\033\212n\352\003\202=\351\246B8\240I\232O2\224I\232\014\224\276fE!z\004\231\240\275&\374R\031h\363\r#I\201Q\031sL/HZ\243f\250\335\352\273\232\201\344\300 \212\255:aC\016\225NCT\346\025ZF\250\030\324,j\"ri\244\323\030\346\222\236\017J\2321S\240\2531U\350j\364&\254\003\305\\\260\221c\220\0223SNA\220\2200)\001\355H\335)\235\351A\247\206\315H\246\244\007\0252r:\324\200\2201\332\215\243\035y\247\000\r;o\245!J1\266\234@8\305*\343\222\177\ni\024\202\236\247\025 n)\031\251\205\266\322\026\315\000z\322\021\212c\036)\233\261H[\212M\370\247\006\310\241^\224\232n\374R\031)\276g4\273\363Az\014\224\306j\215\232\230_\336\232\315\357Q\273{\324L\325^Nj\r\370\340\364\252\367\010\001\310\351T\244\346\250\310j\0075\013\032\214\265!j\2174\003\315H\265b3\203S\250\364\253\021qW!\253\321\032\260\246\254\332\214\310>\265nu\333!\3150\036)\031\252=\324\252i\301\251\352\325*\266jdl\016\2658c\217\2558q\365\247(\334\300\366\247\200E8\r\324\2141IA\244n\224\332Pi\331\244f\335\212a<\236i\003\323\203\346\224\234\212c\n\215\233\265D\315\3174\003\232v\377\000\227\024\320\330\247n\244\316i\244\363Q\226\301\244\337\212<\312<\312B\364\322\365\031jizc5D\315Q9\252\362T\004\214\340\364\252\322\257>\325\232\346\253\2675\023\232\214\232ajniA\315=MO\031\305XF\253\02175z\023Wc\253\013\322\254\301/\226\300\325\251\030\314\300\203\222i\235\016(j\214\214Rn\301\245\rOV\251P\344\342\246S\232\235\016GZ\225O\345S.:S\310\310\307zA\22584\247\232a\0304\036\r\007\232a\024t\244\335Fi\214\3304\335\347\241\246\356\301\247\371\270\306\r!\226\241w\317z\210\266M86\005.\374\322\026\245V\241\2157}1\232\243-\212M\364\233\3517\320^\232MFZ\220\2651\252\'\252\356j\0075\0037cY.\331\250]\252\0269\250\330\323\t\244\315-=Njt52\032\263\021\346\257@\325v&\351V\220\323\327\255lZ*Ej\314H\334j\231o\234\322\223\232c\324D\363J\032\236\246\246S\336\246\214\344\023\336\247C\305N\2540\000\251\227\232~1\212x\033\250+\315&)\270\315#q\332\232zS\033\245%4\266\001\250\313qLg\356i\206N\264\233\351\013\323\013Sw{\322\356\244\337O\334\n\214u\241\034\003\315+\270\317\025\013=4\276i\205\351\205\351\013\322y\224n\315\005\361L-L\335K\272\243nj\t*\273\365\250\034qX\254\325\033\265D\315Q3\344\323\t\311\242\224u\247\251\305J\255S\241\25315\\\205\252\374-W#\351O\'\025\243\245\342}\310\307\2652\346?&]\264\325#\024\3275\013\036i\241\251\352\334\324\350\36525XB6\373\324\312jx\315J\255R\003\351N\r\353JW\0034\303\355L\'4\332a\357L\'\025\033\032\215\215D\3074\256\212\250\010<\324\005\250\335Mf\246\356\245\335I\273\232r\276)\322\034c\025\037\231\220y\250\331\351\205\351\245\351\245\351\233\350\337F\3727\323K\323w\221I\276\202\325\033\232\257%@\346\260]\252&j\211\232\243-\212n\354\232\\\346\225M=MJ\2652\034U\230\315[\211\252\364-\322\257D\334T\216x\251\264\253\200\227j\t\342\266u\013371\256OS\212\314\2267\203\357\014\032\204\311\232\215\232\231\273\232z5N\206\246F\251\321\252\302=N\215R\251\251\001\305;9\247\211N\334\032BA\036\364\306\024\303\322\233\322\230\3075\023s\232\215\252\'\342\242-M\3154\236i\t\244\335HM\031\246\226\245\363x\305F\315\3150\265!<u\250\313S\013Ro\245-I\276\215\331\244-M-I\276\215\364\3265\033\232\256\365\316;T,\325\0335F\306\200iA\247\255J\242\244Z\225jx\315Z\211\252\344/\322\257E%L\317\305WYLr\206\025\326h~ \212%>h\007\353Y\232\316\254\267\327\004\250\001{Vx\222\221\244\246\357\251\021\252tj\231\032\247F\251\321\252tj\235\032\235\272\234\036\234\032\227u\005\262)\255L&\230\304\020y\346\242\'\025\023\036j65\023\032\211\251\233\250\337F\354\322\365\034S\\\221Q\226\244\337H[<Td\323wSX\324e\250\335\357K\272\215\324\026\244\3151\2157q\244\337J[5\033\032\201\315s\014\365\023=F^\230_\232M\364\360\325\"\032\235\rH\r=O\"\247CV#5f7\305Z\212\\w\251\304\331\024\306l\322\007+\320\323\325\263O\3631Hd\244W\346\247F\253\010\32525N\215S\243T\350\3252\275<5;4\3458\245\245\335\212L\347\2755\215F\306\242z\215\215F\335*\'\250\230\340\324D\323sJ\032\237\277\212c\220G\275F\314H=*2\324\306z\013\023\317jil\323KqL&\223\"\200\324\355\324\023M\'\024\302\324\322\324\335\324\273\251\013f\242z\344\231\252\026~i\205\263L&\200i\352\3252\032\235\032\245V\251\020\346\246V\305J\255S#\324\313-J\262\324\202L\322\207\247\207\243}\033\363J\255S\306\325:5XF\251\321\252ej\235\036\245W\251\025\351\352\3315 9\245\315!8\243\"\214\212\215\252\026$S\030\212\210\237z\215\216j\'=j\026\357\353Q\357\2406)CT\315\0311\202*\2618&\242s\216{\032c7\024\335\307\007\024\315\374\321\272\202sII\232\001\243u\005\263Q\223M&\233\272\220\265\033\351\254\325\306\311&\005@^\232^\215\324n\247\253T\310\325:5J\032\245V\305J\255R+T\212\325(zz\275J\262S\204\224\360\364\355\324\340i\340\363R\241\251\221\252\304mS\243T\350\325*\265J\215R\253S\325\252P\364\273\275\350&\223&\214\323I\250\234\346\241v\250Y\260i\246L\365\250\334\344T.sP\261\305\"\344\322\206\301\251R\340\201\216\324\331\007\313\232\256\355\306*\026zg\231\264\361M.\010\367\244\rO\316)CPy\244\305#qI\232kS\t\250\330\323KSw\322\027\256.W\317\024\315\324\322E\033\250\335\357NV\251\221\252tz\231\033\214\324\252j@\325\"\265H\255R\007\247\253\324\212\364\360\324\360\364\365j\221Z\236\247\212\225Z\246SS#T\361\265N\215S+T\212\325(zz\265H\032\236\0334n\244\317\275&\352\013T.\325\0035B\315L-Lf\250\235\263P\263qH\257\264\363\322\224\237\342\006\200\365an\025\242*G5NF\346\253\273Tl\324\202Lf\200\334dS\203z\322\356\301\245\337N\335\232i4\312\t\250\313S\t\315F\306\230Z\223v+\211g\334i\245\251\246Nh\rN\rN\rR#T\350\334\342\254\253b\245V\30585<5H\036\236\257R\007\247\253\324\212\324\360\324\365z\2205L\255\305J\255R\251\251\221\252ej\231\036\246W\315H\255R+\344\324\301\251\352\325 jP\324\205\251\245\2517Tnj\007j\201\232\243-\212c5D\315Q\261\250\231\316jx\244\030\301\250\244\014\271=\251\253/\024\307\2235\0135F\315L\335R\006\0058<\322\357\315.\356y\024\023F\354R\356\244\337HO\025\033S\t\246\223\221L=i\204\327\010_\003\336\232\322{\320\r;w\275(jpj\221\033\025f\023\334\325\205j\2205<585;}9^\244W\251U\352Ezxz\221Z\244V\311\251\325\252Ej\231\032\246V\251U\252Tj\225Z\245W\251Q\252P\364\360\365 ~)C\320Z\232Z\232^\230\317\232\211\316j\0075\0135FZ\230Z\242g\250\313sNF\343\2575(\223z\342\240a\264\234~U\0235D\317L-M\'\002\205lT\252pG5.\375\324\323\3054\232n\352M\364\273\351\245\263L&\230M!j\215\272W\000^\233\276\224I\212P\371\247\006\247\206\251\020\344\342\254\243b\246W\251U\251\301\251\341\350\363)\312\364\365z\221d\251\026J\221^\245W\251\221\252uj\221Z\246F\251U\352Tz\225^\246G\251U\352Uz\221^\244\017N\017N\rF\372B\324\335\324\302\324\3065\013\324/Q1\250\231\2526l\032f\356h\r\214\323\204\233N\r\022\034\214\367\252\354s\365\250\313`\363\322\243\'4\207\245 <S\225\352T\222\245\373\312@\250\311\355LcL&\223}\033\251\013SI\2461\244&\274\340\275!zr\265<585H\033\002\246\214\342\247V\251\025\352Uzz\265.\3727\323\203\323\303\324\212\365\"\275J\257R\253\347\212\260\255\212\225Z\246V\251\025\352Uz\225^\245W\251\225\352Dj\231^\244W\247\207\247\207\245\337K\276\220\2657}4\2654\2651\215D\346\240sQ1\305D\306\243\007\223I\272\206$\342\236\037#\025\013\234\032\211\216i\234\032i4\2314\003\212z\265O\033\340\323\2449\347\275D\335*3\326\231\2327Q\272\220\232i4\322s^i\276\200\324\360\324\360jE4\365952\266*Ez\221^\245W\247\206\245\335F\352pzpzx\222\244W\251\221\252x\233<\325\205j\221^\246W\251\025\352Ez\225^\245G\251\225\352d~*P\364\365zxzxz]\364\340\364\026\246\226\244\335\3054\2654\265D\3475\023\032\211\216j\0264\317Zfy\240sJ[\024\306n9\344T,})\204\346\233\272\227<SsJ\033\025\"?\275J\036\232O\345M=j3\300\246\346\214\322\223\232i\351L=+\3147\373\323\225\263O\rR)\247\206\251T\342\236\032\244V\247\207\251U\351\333\351w\321\2774\340\364\340\364\365z\221^\247G\253(\330\0252\275H\257R+\324\252\364\365z\225^\245W\251\321\352ez\224=<5<=<=.\372P\364\355\364\335\364o\244-L-O\213\004\034\323\032! $v\252\222)S\212\205\316\0053\2650\234Rn\346\202x\250\230\323X\217Ja\365\246\3654\214px\244\315&iCT\212\365 l\212i4\323\322\233HN(\0074\264\303^T\0175\"\232z\232\221Z\244SO\rO\rO\337OV\247\207\247\007\245\363)C\323\203\323\203S\203\324\250\325b&\311\315XW\251\025\352Uz\220IR+\324\212\365*\275J\217S\306\3652\275J\257O\017O\017OW\247\007\247o\243}\033\2517R\356\367\244=)\241\312\322\244\333r=i\257\031\225sU$R\265\021\351Q\267Z\214\234Q\276\220\234\323\017\024\314\343\232C\323\"\233\214\212nM!4f\234\032\236\036\234\0334\023\232i4\332)I\310\244\257\'\rR)\247\206\251\024\323\303S\367S\203R\206\251\025\261N\017N\337F\372P\365 zpzz\275H\036\254\306\330\0252\275H\036\236\257R\253\324\252\365\"\275J\257R\253\324\310\370\251\325\352Uz\220=8=9^\244\017N\017F\3727\321\276\227u\033\251\t\246\023\326\205\220\251\347\2452f\335U\337\212\211\215D\346\243\335K\272\202\331\250\3114g\024\231\306i\2074\322h\240\034R\206\247\206\247n\240\234\322\023\212N\374R\321^J\r<7\024\3455 jxjpjpjP\324\360\364\241\351\333\363F\372P\364\360\364\360\365\"\275I\033d\325\204z\231d\247\211*Ez\221^\246W\251U\252Uz\221^\246W\251\321\352Ez\220=<=8=<=<=\033\351wQ\272\227\177\275\001\350\337HZ\232Z\230\307\212\211\315B\306\243cQ\223\212B\324\006\240\372\323I\241Nx\357M<SI\3157u&iriCS\303R\223Fi)sFk\310\303sO\006\236\032\236\255O\rN\rJ\032\224=.\372pz]\364\233\362i\301\351\341\351\352\371\251\003\342\246G\305L\257R\253\323\303\324\212\374\324\252\365*=L\217R\253\324\250\365*\275L\217R\253\324\201\351\352\364\360\324\360\324\340\364\241\251wQ\272\224=\033\351w\323KR\026\246\226\250\331\252&4\302x\24651\272R\003\212]\324\215\326\232OCN~G\024\3003\232a\353A\351M\315(4\340\330\247\356\240\0323F\352Z\377\331"
+byte_png: "\211PNG\r\n\032\n\000\000\000\rIHDR\000\000\002\000\000\000\002\000\010\000\000\000\000\321\023\213&\000\000\001\322IDATx^\355\335K\n\203@\014\000P\321\373\037Y\351\246]4\264\2102\352L\362\3362\224\ne\254I\234\3174\001\000\000\000\000\000\000\000tf\216\001\000\000\222\222\371\001\000\000\000\000\000\000\000\000\000\000\000\000\\m\211\001\000\000\000\000\000\000\000`Dk\014d\263\305\000\000\000\000\000\220\207\006 oN.\003\000\370\351\2664\351\266\013\001\000\0000\210\335\2278\273\037\000\000\000\000\252\3226\350T\363\251\001\315\277\020\000\000\200\356\251\372\001\032\323d\003\000\200\212T\002P\231&+\000MH)\241*w?\000%x\340\221\300\311a\254{\010\000P\305\311\204\021\000\000\240\023\372\331\234\362\0318\006\020\000\000\300\243\326\030\330\241\214\003\000\000\000\000\000\030\303\321\367@\000\000\000\000\000\000\000\000\3000,\373\006\000\000\000\000\200k9`\022\000\000\000\000\000\000\000\000\000 \021\0335\334\243\375\357lZ/\000\000@5*A\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\340b\266?\004\000\000\000\000\000\000\000\000\000\000\000H\314\342\021\000\000HN\322\017|\363\257\220\332\026\003\000\000\251,1\000\220\335\032\003\177\250\366\001\000\000\000\000\000\000\000\006c\302\007\000\000\300\2448\302\362x\000\000\000(D+\010\000\000\000\000\240\nS\303\000\000\000\000\000\000\000\000\000\000\000\000\000`8\263\025\202\000\000\000\224`\313t\000\000\030\223\\\036\000\000\000\000\000\016Xb\000\250\30421\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\206\341`\032\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\200\'\274\000>R\030\020\037\177\342\335\000\000\000\000IEND\256B`\202"
diff --git a/core/res/geoid_height_map_assets/tile-9.textpb b/core/res/geoid_height_map_assets/tile-9.textpb
index 5f23f1c..f556a35 100644
--- a/core/res/geoid_height_map_assets/tile-9.textpb
+++ b/core/res/geoid_height_map_assets/tile-9.textpb
@@ -1,3 +1,3 @@
 tile_key: "9"
-byte_jpeg: "\377\330\377\340\000\020JFIF\000\001\002\000\000\001\000\001\000\000\377\333\000C\000\004\003\003\003\003\002\004\003\003\003\004\004\004\004\005\t\006\005\005\005\005\013\010\010\007\t\r\014\016\016\r\014\r\r\017\020\025\022\017\020\024\020\r\r\022\031\022\024\026\026\027\030\027\016\022\032\034\032\027\033\025\027\027\027\377\300\000\013\010\002\000\002\000\001\001\021\000\377\304\000\037\000\000\001\005\001\001\001\001\001\001\000\000\000\000\000\000\000\000\001\002\003\004\005\006\007\010\t\n\013\377\304\000\265\020\000\002\001\003\003\002\004\003\005\005\004\004\000\000\001}\001\002\003\000\004\021\005\022!1A\006\023Qa\007\"q\0242\201\221\241\010#B\261\301\025R\321\360$3br\202\t\n\026\027\030\031\032%&\'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz\203\204\205\206\207\210\211\212\222\223\224\225\226\227\230\231\232\242\243\244\245\246\247\250\251\252\262\263\264\265\266\267\270\271\272\302\303\304\305\306\307\310\311\312\322\323\324\325\326\327\330\331\332\341\342\343\344\345\346\347\350\351\352\361\362\363\364\365\366\367\370\371\372\377\332\000\010\001\001\000\000?\000\363]\336\364\340\324\355\324\360\324\273\275\351wR\356\245\335F\352]\324\006\245\335K\272\224=<=<?5 z\220=<=H\036\236\032\236\032\244W\251U\252@\325\"\265H\032\244V\251\003S\303S\303S\303S\203R\346\2274\273\251s\357Fh\335F\352L\321\232i4\322i\244\323)\017Zi\244\242\220\364\244\247SC`\021M\240\364\246\321J:\322\346\235E\024\240\327\233Q\234w\247\003N\rN\335J\032\227u\033\250\335K\272\200\324\354\321\272\215\324\340\324\340\365\"\275H\036\244W\251\025\352@\364\365jxj\225^\245W\251U\252Ej\221Z\244V\251\003S\303S\303S\201\247\006\245\315\031\245\315.i3F\352L\321\232\t\246\232i\351IM=i\017ZJBi3\232(\244=i)\r%\024S\273QN\355J\005\037Z\363SI\232\001\247\356\357F\352]\324\241\250\315\033\250\rN\rK\272\215\324n\245\335N\rR\007\342\236\036\236\257R+\324\212\365\"\275H\032\244W\251\225\252dj\225Z\236\032\244V\251\003T\201\251\341\251\301\251\300\323\201\243>\364\271\245\335I\2323I\232Ph\315!4\204\322SqHz\322R\032J(\244=i)\r%\024S\251GZZ^\203\212\017\245y\241\246\236\264S\201\2434f\215\324n\243u\033\251CR\356\245\rK\272\215\324\241\251\341\251\301\252@\325\"\265H\257R\253T\212\325 j\231Z\246V\251\225\251\341\252Ej\2245<5<5<5;u85.isK\2323I\237z3K\232ZC\322\222\212\017Ja\244\2444\224\277\303F8\244\357M\2444\224R\212Zp\035\251qA4\225\346\307\2554\323M.h\311\240\322f\223u\033\2517R\206\245\335K\272\215\324n\247\006\247\006\247\006\251\025\252Ej\221Z\245W\251\025\252Uj\231Z\246V\251U\252P\325 j\221Z\236\032\236\032\236\032\236\r8\032vh\006\234\r.i3\232)\324Q\232(\242\232zRc\212Jozu\024\230\246\221IHG4b\224S\251GJ;RRw\2578\"\230zSOJJQ\326\202i\247\25534g\024\231\245\335J\032\227w\275&\356iwR\206\247\006\247\006\247\253T\212\325 j\221^\245V\251\225\252Uj\235\032\246V\251\025\252@\325 j\2205<5<5<585<5\000\363N\315.h\315(9\247\nZ(\242\212C\326\222\220\322w\243\024\276\364\224\336\364\204RR\342\226\214sN\2444\224\206\274\351\226\230E0\212m\024SI\357M&\233\232i4n\245\315\031\243u\033\251\301\251\301\251CS\303S\303T\201\252Ej\225Z\246V\251\225\252tj\231Z\244V\251\003T\201\252Ej\2205<585<\032x4\354\322\203N\315\024\345\247\212Z(\002\235\212LSH\315\004RRc\232Z\017Jm!\244\242\212Q\353KG\322\220\364\2444\332\340\030TL*2)\204RR`\322S\017Ze!\353M\311\315\031\2434f\214\323\201\367\247f\2245<\032pj\221Z\244V\251U\252ej\231Z\246F\251\325\252Uj\2205H\255OV\251\003S\301\247\203O\006\244\006\236\r(4\240\323\207Zz\323\207Zu(\024\264b\227\024\334sA\036\224\230\244\305\030\244\305!\351IHE\000R\342\212?\032;R\0220\005!\244\315qR[\202*\253\302W5\021^qLe\250\210\244\246\232a\024\303\326\232i\244\322d\321\232L\321\232\\\323\201\342\234\r8\032P\325 j\221Z\246V\251U\252ej\235ML\255R\253T\212\325 j\221MH\r<\032\220\032x5\"\232x4\352p\351NZ\220t\247\216\264\243\255:\224\nZ\\\032LR\021HE&(\305!\244\"\232E%\024PO4\203\024\204\320x\2444\225\312\260`9\025\004\200zUy\"\005r*\263\306\303\255BG\250\246\221L#\232i\250\3150\323i\247\212nM\0314QN\006\234\r8\032p4\340jU5*\232\231MJ\246\247SS)\251T\324\212jU4\360jPi\340\324\200\324\212jE5 \245\035i\342\236\265 \247\216\224\340)\300S\261K\212\\Q\203I\217jB)1HE!\024\323M\244=i(\2444\322qKHOJJ+\005\221[\255V\222\337\236*\253\306\313P\260\004c\364\250\0361U\331\010\250\310\307Za\025\031\024\302)\204S\017ZB)(\242\212p\247S\201\247\212\221MH\246\246SS!\251\324\324\312jE<T\200\324\252j@jE5 5 5\"\232\220\032\220\032x\247\016\224\361\326\245^\264\361O\035i\340S\200\245\002\227\024b\214R\021M\"\220\212B)\206\230z\322\032J)\246\203\322\233E&h\347\025\214\302\242\'\232c\242\272\362*\234\266\304t\025X\243)\344qP\314\233I\307J\201\224\032\205\227\035*2)\214*2)\204SH\244\305%\024\270\245\372S\251\324\361OZ\221jU\251\326\246J\231jU5 \251\024\324\200\324\212jAR\003R)\251A\247\212\220S\326\236*U\251\026\236\005H\0058\np\024`R\340Rb\220\212B)\244SOZ\215\251\246\222\233A\351Hz\323H\346\222\212N\364\265\222\313P\224\346\230\300\255D\314@\252\362\020{\n\254\352\030\020z\325g\214\201P\262\372\212\211\226\243a\3061Q\225\250\310\246\221HE&)1\315.)@\247\005\247b\234\005=EH\242\245Z\231je\251EH\265*\324\213R-H\265\"\324\213R-J:T\202\244Zz\324\200T\213R\250\251\000\251\000\342\234\0058\n\\{Q\2121M\"\232E!\025\031\024\306\246\236\224\332CIM\357E4\365\242\2121T\035*\026Z\205\327\212\256\353U\335\016*\0220zTl@\355Q\224F\351\201PI\001\307\025Y\343#\255B\331\007\221M\306E&\336i\205i6\321\266\227m(Z\\S\200\245\013O\002\244QR\250\251TT\253R\250\251\027\255J\242\244Z\221jE\251\026\244Z\225jU\247\255H\265 \025\"\212\225EJ\242\245QR\001N\002\235\212\\\032JB)\r6\232j6\246\036\264\312i\353Hi)\017ZL`\322b\214\032\000\245\252l8\250XT.\271\252\356\225]\3628\025\003\217j\201\226\241`GJO1\207\024\306\n\343\004sQ\024\003\2028\252\362DP\344t\246\025\244+M\331F\332]\264\273)vS\202S\202\323\202\323\302\324\201jU\025\"\212\225EH\242\245QR\001R\001R\001O\002\244QR\250\251\026\244QR(\251@\251TT\252*U\025\"\212\220\np\024\352(4\332CM=i\206\230\335*3M4\323I\332\233F)\010\244\242\214R\342\252\270\342\240aQ0\250\231I\250Z>y\025\013\307\336\253H\2305]\226\242d\246\025\357I\327\202)\254\274q\310\250Z y\025\031B)6Q\263\332\227e;e.\312P\264\340\264\340\264\340\265 Z\221V\244\013OQR\201R(\251\024T\200T\200T\200S\324T\252*E\025\"\212\221jU\025*\212\231EH\242\244QO\024\341N\002\227\024\332CM4\323\326\230z\323MFi\247\2456\233HE%\035\250\242\212P*\274\213P\024\346\230P\323\n\201\324\325i\016\032\2438\3175\004\221\345x\252\214\204\036\224\302\264\302\225\023%0\202\246\223h<\216\264\2058\344Tf<\036:Q\262\224%(Ojv\3126S\266R\204\247\004\251\002S\302\323\302\323\302\324\212*@*E\025 \024\360*@*@)\340T\200T\252*E\025*\212\225EJ\242\244Z\220S\307Ju:\212CM4\323M4\323Lja\353L=i\010\246\236\224\224QI\2121K\212*)x\340\212\211q\273\232\206C\211\010\252\316Npj6Nri\031A\025\001\0308\250d\217\034\342\242*)\214\225\021Nj6\2175\031B\017\024\014\3644\343\030#\"\243\tN\tJ\024\322\204\245\331K\266\224%<%<%8-<-<-8-<\n\221EH\005<\nx\024\360*@*E\025*\212\221EJ\242\245Z\221jE\247\216\224\372u8QM4\207\2554\365\246\236\264\224\303Q\232i\246\236\224\224\230\243\024c\024\224QED\322\007R\030sP\222\007j\211\260[4\306@Nj&C\217\245G\234q\212c&Nj7\\\212\200\246\r0\246i\0144\323\017\035*&\213\007\030\250\332:n\322)BR\354\245\013\212]\224\2418\245\tN\331N\tO\013\203\365\247l\245\tO\013N\013N\013R\001O\002\236\0058\nx\025 \025\"\212\220T\253R-H\265\"\324\203\265<S\351\300\346\212(\246\236\264\207\2554\212Ja\246\032a\351IHG\024\235\350\2444\224QN\003\025[\200\307\035\351\273AlPb\301\246\024\347\216\224\306Q\214UW\214\206\250\330m\342\243cQ0\365\246b\234\005;\003\024\206 \335*\'\203\035\252#\027\2653\313>\224\230\000\340\323\202\203N\362\351\302*p\217\332\235\262\224\'\265;e8-.\332P\264\340\264\340\264\340\264\360)\300S\300\247\001O\002\244Z\221jE\251\026\244SO\025 \247\212x\247\nZ)\t\244\244=i)\010\246\032a\353M=i\244RRRQF\005\030\242\212\244\033\006\245\005O=(g^\346\243\336\244pj69\357Q0$T.\024s\232\214\340\365\250\331\027\034\032\214\216}\250\307\245\0035\"\323\360\017QH\320\206\034\n\200\304A\351Q\275\276\376q\3150\333\274|\365\251\221r\242\244\021\322\371t\241)vR\354\245\tK\262\215\224\241i\301i\300R\201N\3058\np\024\341\322\244\025 \353O\006\236)\340\324\200\323\301\251\001\247\203K\236i\331\346\214\322QE!\351Hi\207\255Fi\017Jm\030\246\342\220\212J\\\0321F)k=\206\rF\362`\361Q\027$u\246\207\3055\2459\316h\017\221\326\243\221\270\353P\022I\240\222\0055[-\203R\025\343\212P8\247\001\212x\031\025*\255)\213=\251\026<\036\224\366\2002\036*\233Fb~\234\032\224(#4\340\224\276].\3126R\354\244\333K\262\215\264m\245\305.)qN\002\224S\3058t\247\212x\353O\006\234\r<\032\221M<\032\220\032r\236?\032vh\242\212P))\rFi\206\220\322Rb\223\034\323OZ)pi(\245\301\254c!=\351\254sQ\223\212\215\236\243-G\231\212\215\244\367\244\017\315H\030b\231\362\347\212z\236*E\024\360\005=W\232\231W\212\224.i\301)\373\016\336\005E<A\340\351\310\252\261)\350jp\224\355\224\273)6Rm\366\245\333I\266\215\264\233h\305\030\245\305.)i\302\234:R\203N\006\234\r8\032\221M=MH\246\244\006\236)iA\245\245\003\232Z1\3054\364\250\332\232E4\322b\214R\021\3154\212(\242\220R\3275\346\341\252@\374S\031\252\0264\302i\214\306\231\234\236\264\205\2104\375\370^\264\3459\025 \353O\014zS\325\216j\314g$\014U\200\270\251T\n\220.j@\274t\246\252+\266\323\336\252\317\007\2257N)\352\271\024\340\224\273)\nRl\243e&\332M\264\233i6\322b\227\024b\226\212QKN\245\035)\342\244Zz\324\202\244Zvi\302\234:\322\323\251@\243\034SH\250\310\246\232i\244\242\2029\246\221F(\305&9\240u\245\305r\016pjD|\212Rx\250\230\363L&\230\307\212\217<\322\266p\r4\261\305M\033qVW\2454\234R\244\2305e%\350A\346\256G( f\247\030\352\rK\037&\255\"qM1\205\223\212m\324[\323\2475Z!\306\rK\262\215\224\205i6\321\266\223m4\255!ZM\264\322(\307\265&\005.\005\024QN\245\024\341R\n\220T\202\244\024\242\234:\323\307Zp\024\340)\303\255!\246\232a\246\021M\244\305.)\017ZB)1I\212N\364\240S\200\2565\251\020\221O&\243\'\232ajc6h\002\236\006F*6\\R\306qV\026A\266\230_4\201\271\251\221\216j\344r|\2705e\034\025\034\325\210\237\006\264\340!\3059\223\347\316)\356\231\217\245Pd\3319\036\265 Z\\S\n\321\266\215\264\205i\245i\n\323v\323J\322b\223\024\230\244\242\212u(\247\016\225 \251\026\244Z\220t\245\247S\307Zp\351O\035)\324\204SM0\212a\246\036\264QK\216h\"\233\2121HW\346\024\340\271\342\214s\\Su\244\006\224\236*3\307z\211\237\234\nM\324\240\324\252E\004n\030\357M\010i\335\0050\232z\016j\312c\024\362\352\005=%\367\253QI\223\326\264\355f\332\331=*\340\271FoJ\270\245Y\005R\274\217l\200\323TqA\031\244\333F\3326\323J\323H\244+M\333M\"\233\212B)\244SOJJ)\303\245(\247\212x\251\027\255H)\364\341\322\234)\342\236\005<S\205!\246\221L\"\230E6\223\024\270\245\024\021F(\305!\034\322c\270\245\357\\.\352il\032n\342Z\243y2\325\031nh\007&\244\004\342\232\\\203S\306\304\256M?4\302s@\031\241\233h\246\375\240\216\364\206|\367\251RS\353V\341\224\216\365~)\310\3075z<\262\357^\325r\t\333\247\245\027\023\031\016})c!\226\244\333F\3326\320V\230V\232V\232E&\332k\n\214\212B)\244S\r!\024\224\341J:T\202\236)\340T\202\237N\024\360)\340T\200S\200\247v\240\216i\244S\r0\212a\024b\226\224\016(\307\024b\227\002\230E\000R\327\000N\r3\253R\261\010\270\356j\273\032e9z\324\340qQ\262\345\252t\030\\S\261\3057\2759i\262\0163U\331\0163M\000\346\254D\246\256\304*\364K\232\320\210\225L\016\365f\335s\232\260\025J\025#\232\2113\034\245\017N\325l\014\212]\264m\244+M+L+M+I\266\232\313Q\021M\"\232E0\212m\024S\200\247\212\220\nx\247\216\224\361\322\236)\342\244QO\002\236\005.8\242\220\212a\024\302)\244Rb\224t\245\003\2121F)p)\244Rc\212P+\316\331\3014\322\373z\016j&r\334\232ni\247\245I\037Z\234q@\\\265H\007\024\352a\0304\364\034P\343\345\250H\312\342\230\251\315XL\n\267\n\023\316*\374\013\315_U\033j\345\254`\214\216\265e\243\310\334\005A*\344\007\003\221S\304C(\251v\321\266\232V\232V\230E4\212B\264\326Z\211\226\230E0\212a\024\322)1K\212P)\353O\025 \247\212p\353O\025 \251\005H)\302\226\216\324\204SH\246\221L\"\232F){R\322\321\212\\SH\244\305\030\2575\335A\"\243c\3153\275:\244QR\255<u\251(\357L=jD\351D\237v\241\035i\300`f\234\234\266+j\3260\"\000\325\245A\232\260\252M\\\267;\005h\333\200\340\2361\216\225^h\202\310W\261\250\341\033\\\241\355V\200\342\202\264\322)\244TdSv\320E4\212\215\224\223\212cD\303\232\210\212a\024\302)1F)\300S\205<\n\221E<\np\247\212\221EH\264\361O\024\356\377\000J1\305&)1L#\232a\024\322(\242\224t\247\001F8\244\"\223\024b\274\261\237\232P\371\240\232Jp\251\224qN^*@i\324\016\264\207\255K\030\242Nj,sJG\0255\264e\244\007\025\263\020\302\212\264\2035:\n\262\202\256\333d=Ip\271\001\205T<L\033\326\256(\312\321\212B\264\302)\205i6\322\021L\"\230\313\232\\|\270\315Vd\332\306\230\313L\"\233\212\000\245\3058\nx\025\"\212x\024\340)\352*@)\340T\200S\200\357N\003\2574c4\224\207\2454\365\250\315%&8\244\035i\324\341\322\216\324Rb\214W\222\026\346\234\265%.)\300\324\311O\245\006\234Z\205<\323X\374\365<g\214\320NZ\233\216i\t\347\025\245g\026#\004\325\364\025f1V\220U\210\306H\253Q\360\334T\354\277-Tt\371O\265X\204\356\214T\233i\n\323J\323\n\323v\323H\246\021M\"\223\261\250\034e\3526\024\302\264\334Q\212P)\300S\200\247\201O\247\001O\002\244\002\244\002\236\0058\np\353@\242\232z\323\017Ji\024\323\326\220\364\244\3058\np\024\270\342\220\n0(\305y\005<\032\220\036)\371\245\035jE5 4\341Ct\244SA\345\252B\333c\246F\371z\237\265$k\231y\365\255x\016\024\n\266\230\2531\216\346\247\334\000\353R\307 \355Wm\376nj\331\031J\251\"\220\344v4\266\347k\2245so\024\205i\245i\205i\245i\205qQ\221L\"\223\025\023\016j2\264\302\264\233i6\321\212p\024\340)\340S\251\300S\300\251\005<\n\220\np\024\270\343\024\270\242\230z\323H\246\032i\244\305\0304\240S\251q\305(\024\270\243\025\343\200\022*@\264\356\224f\235\232z\265J\246\245\316\0055\233&\225G\024\270\245a\225\250\207\313%[S\225\247\201\206\006\257@zf\264#*\006I\247\031\273-9\035\210\2531\347\326\265\355\006\024f\256\214\036*9b\004t\252\3426\335\323\221V\242\'\030a\315HV\232V\220\2551\226\242e\250\312\323\n\323H\250\312\323J\323\n\323J\322m\244\333J\0058\np\024\240S\300\247\201O\002\244\002\236\005<\n\\s\232\\`\232B)\207\2554\212a\024\204Rb\2008\245\002\227\024\275\251\312)\330\244\"\274\201TR\221\203K\326\233\216h\3178\245S\315XJvE-=\007\024\023\3159y\034\3224y\344S\221\212\234\032\2308\305X\201\302\256z\232\260%c\337\212\261\020\317&\254\251\355V\340\371\234zV\315\277\"\255\247\255K\215\302\205\214n\351Ox\227``9\244Q\221AJa\\TL*2\264\302\264\302\264\322\264\322\224\302\224\302\264\322\264\322\264\233iv\322\355\245\305\000S\300\247\201R\001O\002\236\005<\016)qK\216M!\034S\010\246\221M\"\223\024\230\366\240\016:Q\217j1N\003\212z\216)qF+\306\303S\363\221L-\203NS\232\0104\364\034\363Sn\300\300\247\001\205\315\n2ja\200)\207\2559y5`\001\2120\t\351CE\214\021RB\244\260Z\266\303n\005M\033\361W#\037.\343Wm\227\200kR\026\302\325\244n*\3025L\2705c\311\337\016\341Q,ex4\245j\026^j2\264\302\265\031ZaL\366\243e!J\214\2450\2454\2554\2557e\033h\333F\332P\264\340\265 Zx\024\360)\340S\2004\354z\320G\315HE0\212B)1I\212M\264m\243o\265\033i@\247\201N\333I\212\361`i\331\244\352i\303\201N\r\232z\365\247\365js6N\005=N\00585\004\363J:\324\352\337.)\353\326\236O\313O\265\346Rj\324\270\305,g\232\275\t\310\305_\265\341@>\265}\rZ\214\361S\253\nz\310wU\353i\317\335\'\203\326\247t\347\212\203\222q\212aZaZiCQ\224\244\362\351\336_\2651\222\241p\005B\330\024\302E\'Z]\242\223m\033)6\322\204\247\005\247\205\247\205\247\205\251\002\322\205\364\243i#\212R>jk-&\336)\010\246\342\215\264m\244\333F\3326\320\027\232x\024\354Q\212\361\021KNQN<\320\001\315J\243\024\026\347\002\225GzR\334\320\036\244\006\234\0175*5L\255\315=\210\331\305:\324\341\271\251\345|\200=\352H\217\000z\325\330\010\365\255\010\0161W\243aV\021\275\352da\334\322\356\332\335j\304\022\374\343\025\257\031\335\032\372\324r\000\262t\353M`1\300\244\021\3654\322\234\323\nS0\001\245!\233\356\2551\341\227\031\305S\225\033v\t\241l^E\316N)\255\247\310\017\006\253\2742\304y\024\320\344u\030\251\025\201\251\002\203K\262\227e8%8%8%<-<\201\322\223\234`p)@#\245\033i\010\246\342\220\255\033i\002\321\266\202\264\233h\333J\027\232pZv(\305xfx\245\034\232\224\014\nUZ\221W\034\232By\241W-\223Nf\002\243,)7\324\213\'\2758J;\324\211 \251\204\243\024\365}\334\036\225b2\001\251$\004\374\302\244\211\276\\\372\n\265\003|\243\326\264\241\223\003\232\264\257\357Vc\220c\232\235\037=\351Y\260*\345\202\231\033>\225\261\031\306)%;\345\030\355K\212\017J\215\210\024\314\0265*Z\344g\255L\220m\344\212\222DF\204\340r+<\331\263\276\342\274U\330\255\306\314t\252\363A\"\261\302\325W\210\267\004T/`\031zU\031m\236\022H\351Drs\203V\224\006\024\361\035;\313\245\021\322\354\245\333F\337j)pi\301A\316i\245i\002\322\021I\266\205\030\315\000PV\233\266\215\264\241y\247\205\243\036\324m\257\010=qSF\265!\000\nM\300R\206$R\214c\232kI\201\201Q4\224\3170Ry\235\351\004\2715\"\275X\212E\3163S#\215\306\254\306T\325\205\03052\260\306\323I\235\210G\255Y\265$\256\356\302\264\021\306\320j\304o\315YW\367\025b98\247\227\315i\351\262\000\370=\353m\024\021\305B\331\216R\r;p\306i\217\'aBD_\223\322\255Ch\314\303\002\264\343\264\n\200\021\315Ha\211W\346\003\036\365\023-\257#\201\364\252sK\020;W\265T{\215\247\212\221eyq\351S\010\021\307A\232\032\317\013\362\363\355U&\260.\016V\263&\323\231X\220*$G\214\340\203V\243\000\212\224G\236\324\276]!JiZB\264\005\245\333J\026\202\274Rm\244+I\266\225\000\004\344v\246\343&\215\264\205h\013K\267\232v\3326\373Q\212\360|sR\247\002\225\263MP\t\311\247\026\002\243i=\352&z\215\216EFO\035i\255/\030\024\325\230w\355R%\302\223\367\252T\235\025\303n\251V\343\315\227j\034z\325\350\337h\312\267N\325q%\3713N\206m\357\217J\222\342@\241W\2715r\311\307\220\300\325\244|\212\231d#\245X\216R\306\255\243\361\326\236$\253v\356\341\301\025\320Z\334\345Fz\325\321\373\316\253\232\014#\030T4\211a+\267\3345\243\006\237\267\357U\301\022\3047\020\024\n\257=\337d\374\352\234\227\016\343\004\325Ww\003\203T\345\363\013g5\036H<\325\250\'+\323\025h^\355`1\232\260\223\211\010\303c\332\264Da\243\031\003\006\242k\005q\300\252\027:Y\031!k5\355^&\310\034S\343\301\340\324\245\006)\205)\205)\245)\002S\266\322\205\315)^)\233x\244\333F\336)\241pM\001)J\323J\321\212]\264\270\024`R\021\315xW\227\212xJd\207\260\246tZ\215\230\232\211\211\355Q\222{\232\206K\200\274\016j\277\234X\362i\373\201Z\211\262M\002\244Z\225\030\243nS\315_\202|\340\356\347\275[78m\275\252[\031G\332y=j\325\331\315\322`\366\253p>\325\030\357V\221\30052\311R\244\240\032\231n;f\255\302wsZ18\000f\264\255\'\033\205t\266\222\304c\007\214\325\325x\313\177\016Gz\237\355\020D>f\014}\005!\274\014\270\216<\037Z\2554\354\331\004\325B3\336\220\250\2462\034Uy\"\366\252\355\037\265 B*@\274g\034\324\261\261\004`V\265\254\347\0001\343\336\264\342!\276\3575iaW]\256*\255\316\224\245\013 \315`^X<,]G\025^6\r\305I\2674\322\224\302\224\004\243m.\314PS\212n\312B\264m\342\230S\232]\270\024\323\212a#4\322\302\215\324\271\317j9\364\240+\032\361\027\307ji\'\030\002\243e\307Z\212C\306*\006p\242\240i\217j\202II\030\315Tv\346\242/\203OI\261Ro\3174\241\251\341\300\247\t*X\344\333\322\256+\003\026I\346\232\223\264ro\007\241\255X$7\r\346\236\303\212\272\317\2624a\334T\261M\236\365a$4\343.;\322\305)i\200\256\246\322\301\236\307\316V\343\275\013\033\007\301\253\261\025\214r\016kJ\332\342V!P\034V\325\2742\025\014\355VG\331\3429s\223\351I\347+\003\265\200\366\246\023\270\365\243h\245\002\202\0054\240#\245F\320\217Jg\222=*E\200\021\322\224Z\363\220*e\215\200\003\025\251g\300\003\241\2558\210\316\017\036\365eA\0318\315T\272\263Y\321\206\3203\\\205\375\263Z\\\222\007\031\346\226&\016\271\024\362\231\246\224\244\013N\010)\n\374\324\024\342\231\266\232@\315.\0050\201\326\242w\002\240,\314\330QR-\264\215\353N\373!\034\232h\207\234b\246[s\212w\221\3074\206\"+\303\n\214t\2466\007j\202F5VV\300\346\251\273\0265\023\032\256\344\324\016j\023H\rH\257\212~\372P\364\340\365*\275M\034\254F\301\326\233,\256\256\020\2163]&\237\264\332\241\007\034T\227/\202\251\355\232|,p*\3628\002\230\362|\325r\3220@c\326\272+K\341\024\001\030\344\016\324\246\377\0002|\240\001Z6\227\001\300\336\240\257\251\255\3536\265\333\271H\000u\346\247\270\324\342U\331\021\374j\232\334\226|\223\232\267\034\200\201V\220\347\275?<b\224\032)A4\264\341\0304\364J\220\014\036*U\036\3252\020\033\322\264\354\323y\0319\255o\'\216\230\250\2361\212\347\365{\0375\013m\344W7\261\355\245\350qV\222Du\340\322\340Q\200)\254E7\"\232dP:\324-(\035*##\223\302\2327K\217\272j63\036\324\251m+\234\2605v\013P\274\260\253\001\025z\nk\014\366\250\304\\\364\251\004m\212C\021\244\362\275k\300\310\342\241aU\344\3435JL\261\346\253\277\025\013T/\305@\3435\021\024\303\326\212\\\232]\306\224=H\257RG6\311\001\315K4\233\302\267\275tZt\203\354\303\236@\247\313t\245\366\340\022;\324\221K\221V\004\244w\246\254\273\345\305i\303/\226\240\n\275\0233\212\273i\003K7\314p\243\251\255\026\225\021<\250\317\002\237\034\356\243\001\215XI\030\236M[\211\371\025z)1\336\256G-X\022f\227x\245\337NV\251\003\n\225y\251i\352\001\251\025y\247\205=j\325\275\301\205\3075\277it\223\305\264\375\352\225\2429\252\227\026\341\324\361\234\3277\177\247\215\347\013X\362XJ\247)\221H \273\003\246i\246\013\302x\006\225l\256\330\363\232\177\366m\316psO]\"Rr\304\325\210\264\264\030\3343W\027IR\233\202p)[L\n\333J\001Q6\234\213\316\321\371S>\316\027\200\277\2454\333>y\030\245\020\0009\024\2065\035\251\245\000\346\223\217Ji\351M&\276~j\205\315T\230\374\265M\252\273\365\250\215D\3435\013\n\211\226\230V\233\212LR\032\001\247\203JMJ\035<\276G\"\2654\373\274\305\214\364\247\264\331\227\361\255\013w\312\212\260\317\362\324Q\313\211\263\232\330\266m\300du\255\2100\000\253\242s\267j\360;\323\225\271\253\010\325a$\025j)*\344r\032\265\034\206\247\022\236\306\244Y}MH$\247\t\005J\257\236\365b6\367\251\363\357NV\346\247V\310\342\246S\236\264\021\315i\351\363,N2kx<rE\225 \232\205\2075Z[X\345\352?\032\256\366\010?\204\032\251%\240S\304t\202\025\003\230\261\370S\0322\256\n\256?\n\235c2/*)\342\324zR\033uNqI\346\004R\275\215V\226\343-\221\236=j?\264\215\270lTMq\010~\0056I\303\016\005B_\214\324\016\374\236\325\021\223\336\224\034\212By\305!\353^\000\302\240u\2523\037\233\332\252=@\303&\230G\025\021ZaZaZ\214\2450\2454\2554\2554\212\026\237\216*\265\314\306\030\213\003\212v\217t\314N[9\351[\001\211\223\232\323\201\360\242\2472dT;\366\276s[\226R\201n\246\265\255\345\3348\253\2215XV\251<\317J\2322MZ\215\3105r)F:\325\205\234\016*u\234\032x\226\237\347{\322\211Nz\324\361\313\357Vc\227\336\247Y\275\352T\2235b9*\3026je\031\245%\221\363\236\225j\rL\243\001\223Z\366\367\2512\214\216j\316\321\214\216\225\023f\232p{\ncD\030T\r\003\027\366\251\025\000\343\024\374\001U\256\'U\312\343\025\235#\026\031\016:\361T\245Iwd\034\346\252\315\270q\223Q\251\"\236%\"\225\246\312\324\014\365\021jx\223\024\355\331\244-^\n\3353Ufq\202\005P\227$\325vZ\214\2554\255DR\232R\243e\246\025\250\312\323\010\24651\2056\235\236+\037U\230\210\312\216\365w\303\221\022\273\332\267\177\345\271\253\2217\002\254\003\305C#`\346\266,\\\033e\255\210fU]\242\256E-YW\251\343*OZ\262\222\252\036\231\245\363\tl\216*T\225\263VQ\230\363S\253\221\326\247Yi\341\363\336\236\036\246G\253\013%L\262\373\324\3130\365\2531K\357W\242l\325\264e\365\244\224\344qU\034\025l\212\267e{\345\310\0015\324\303p\222[\202\016iN\322*&\034\322\003K\221M%G5\033L\247#\246=k6\363$d\036\247\212\241+\272G\203P\t\030\237\230\323\\\003M\362\370\315D\303\025\0215\033Te\250\r\305\002L\032V\220W\204J\304\3259\r@\3035\031Z\214\2554\2550\245=`R\205\230\343\025VE\0318\250\030TL*6\353Q50\236i\271\245=+\032\3762\367\001kwL\210Ad6\365\"\257\017\277V\2435a9\2474{\205]\266W\214\016N*\344r\225l\346\257\301>H\346\264\"\2235j&\001\276aVF\037\356\212\2352\007j^Cf\254\305p\024`\212w\234\033\245H\262T\202\\w\247\t\271\353R\245\300\035\352u\270\007\241\251\222l\367\251\222Bj\314R\343\275h\303?\313VR_z\235\033#\255G%W\223(7V\236\223\250\260;\031\270\255\244\272\004\343=jF\270@\247\346\250~\324\203\223Q\276\245\0108\315T{\347\2238<T_io_\306\240\226vv\311n\225\033H\010\301\250\010\311\342\244\0106\362pi\010\000u\252\357\311\250\036\2435\023S\0014\204\323KW\210IU\\d\323v\374\246\243+Q2\323\n\323qMl\342\240qP8\250\036\240cQ1\246\023@\034\323\210\371k*\344\377\000\244\202kr\300\027\267V=+@(\364\251\223\035*\302\005\251<\304\035MZ\212P\311\223\300\035*9n\202\374\240\363V\355&$\016kb\031p\0075n9\t\346\255\3039\3175ie\367\247\371\240\214Q\273\232\221Z\244\017\212w\231G\233\357I\347\034\365\251\343\230\372\325\270\2445z\'\310\253HE\\\205\305ZI9\253\t.;\3224\204\236\264\342\003\246)\210<\246\312\366\253\177n;q\336\217\2661\376*a\272l\365\2463\2269\247\t\0161O\335\305F\306\231\232]\370\034S|\336\324\323\'\025\03385\013\034\232a\353Lnj&\340\323I\246\023\315x\233TEsM\333\216\242\243+Q\224\250\312\323Xf\242aP?z\257%U\223\245@\325\031\353M\3059E8\214\214Ve\344\\\356\255\r&\340cc\270\000V\320*\307\000\203N\344v\247\006n\324\252\214NO\003\326\246\363\202\256\320zUB\314\363\347\336\266l\270Q\232\325\216N\225\245l\341\216*\341\n\007\024\202L\034f\246\215\363\336\245\007\216M<5;}!z\003\323\327\236\36526:\325\270\345\002\255\3057J\271\034\334U\230\346\253qK\236\365:\310H\247\357\251\243z{\236*#\301\251\027\030\240\225\024\007\024\360i\333\270\246\263S\013SKTL\3304\322\324\205\251\271\244&\230j&<\323\r0\212\361vZ@\000\344\323\031A\030\025\023.\rFEF\302\242j\205\315Wz\255%WqP\221L\"\233\266\234\005<&j\265\334Y\\b\262\310\226&\312\344U\273MRH\234\371\271=\253^\333UG<\237\316\257\013\264\362\367\000*\007\276f8\006\234\263\345}\352\305\272\356`kb\001\265j\332>\r^\266\233\007\255^\023\345z\323D\234\365\251\222_z\230K\357O\022\217Zw\231G\230)C\363S\304\331\357Rn\301\353R\306\365n\'\253i\'\275L\263c\275Z\206~y5u\'\036\265*\312*t\224z\324\236h#\004\322n\310\353B\312\001\301\2512\010\3153\200x\247\t1N\337F\352ajajc53u&M.i;PFEA \"\230\016x\242\274h\2551\226\230T\323\031p*\0229\250\231j\026\025\013\n\201\305V\220T\014\265\021ZaZM\264\345L\324\241qP\312\241\252\253\333\206\311\305W6\1777J\r\263#q\305_\267Y\004@\023RyM\2735b\030\361\326\257Dv0\2558\\\025\004U\2255<m\212\262\262\361R\254\2315\"\27752\311\3058K\317Zp\226\234$\247\0075f\027\365\247\031>j\236)*\334oS\254\246\244\023s\326\247\212l\2663WQ\2163\232\262\222q\315J&\301\353R\t\271\251\004\271\350iKg\275H\262`Q\346\346\220\2759^\235\276\220\2654\2654\232i4\264\036\224\200\372\320x\2460\310\250\010\303R\366\346\274\200\2550\2451\226\242qP\262\234\324n8\252\3169\250\230T\016\265]\326\240e\250\331i\233h\331R*\342\221\316\007\025\0263\326\230\303\002\224\247\312\033\035i\2142\300T\312q\306)\306JzIV\243l\212\275l\3308\255\004\"\246SS+\212xq\353R\253T\201\370\244\336sO\017\305=$$\325\224\347\223R\371\201W\002\221d\313U\204\223\025a%\251\304\207\024\345rzT\251!W\255(\256r\243\245X\027\000\216\324\033\201\332\244\216|\367\253)(\251D\264\343%(n\371\240\276(\022\343\275H%\006\227\177\2754\2754\267\275(oZx4\036\224\323\301\243vF)\204\342\230\307\2757<W\2242S\nTl\265\013%@\352j\'Z\201\222\241e\250Yj\273\255DR\243d\346\231\262\200\224\244Te\t\244\331\212\215\3078\241\316\024\n\215G9\251@\244\"\234\243\025b&\253\360\267J\276\207*\r<\312V\2016jd\2235i\033\212\223u\031\245\335R\306\340\036j\320|\257\024\306s\336\225$\301\251\304\2652KV\222\\\255=%\332\324\351\'\3475=\265\316F\t\253Bb\017Zx\2275f91\336\254,\336\365*\315\357O\363\351E\307\275\036w\275!\233\232z\313\307Z\220K\357G\233@\222\244V\251CqK\232F5\021l\032izajn\354W\2332TL\225\033%B\311P:T,\225\013%@\311P\262T,\225\021J\214\307\3154\2454\255&\332M\274\323Yj\273\257\315Q\260$\322\252\324\252\274R\021\315(\025\")\'\212\275\n\236\346\257\307\300\305+\014\323\007\006\254FEYG\342\244\017N\315.M9s\232\265\033`b\226B)\231\305=\036\247G\251\226B*u|\216\264\355\331\251\2418j\266\037\"\234\257\317Z\262\262\340T\253.i\342lw\245\363\362:\321\347c\275(\270\367\245\023d\365\251VOz\221e4\360\365*\265H\255\203S\006\342\234\032\202\334T.\3305\031l\324n\373j#/\275qm\035B\361\324,\225\003\245B\351P2T\014\225\013%B\351Q2Tl\225\021Jk\'\035)\205)\205qM\305#\n\201\327\232\217g4\273qN\246\236\264T\210v\266j\364L8\253\261\234\212V8\342\230y5*f\247CR\203R\003R\003O\004T\212p3Mi3\336\22075\"\232\231MJ\244\324\350I\251T\232\2326\305N\037\212r\261\006\247W\342\244W\342\234[\336\232d\"\220JM<==_\232\260\222T\212\30752\236ju<S\367s\232\225_\212R\374\365\240\311\362\342\242f\346\230[\025\004\222qU\313\232\347\331*\026Ny\025\014\221\200p\005@\361\324\016\225\003%B\321\373T,\236\325\013GQ4u\023G\355Q\230\351\214\224\302\225\023%0\2551\2075\033-3m!\024\322)\244P\0058T\261\271\025z\t\rYnW4\321\326\247S\306*T\0250Z\220\003N\013N\301\315?\234S6\363OQR(\251\227\245J*T8\251\201\245\0143S#\342\237\277\236*\304o\221R\003N\335\305F\314)7S\225\252Uj\235\030\346\254\3063\212\262\240b\236\033\265\014\306\225$\343\2558\311I\2774\271\356j)$\343\212\256\355P\226\254\306J\205\223\212\211\243\343\'\251\250\035*\273GQ4u\013GP\264u\013GQ4u\023\'5\021J\215\322\243d\250\331*2\224\302\225\031J\215\227\rQ\221M\"\220\255&\337jp\024\344\0305f6\305XI{\032\220\016x\251TT\353S)5(aN\337\3158\034\323\201\244\3174\365\305J\005<\034\032pqN\022S\274\33684y\20754r\232\260\215\223V\025\261S\007\310\240\260\365\246\236i\264\340H\251\003U\230[\326\257F8\310\251C\021N\0143\232q<TE\260\334\032pl\216\264\365`:\232I\034m\340\325f\222\241g\315FZ\243d\250Z<\346\242d\343\245@\351P\264u\013GP\264u\013GP\264~\325\023GP\264|\324m\035B\361\324l\225\023%FR\230R\230S\214\324N\2375DS\232\215\226\223m\033h\305*\212\225EL\213\232\271\nqS\354\305\003\212\220\032x&\234\rH)wPI\241\\\203R\211iL\224\236a\247\253\023R\256MH\026\247\215q\326\254.\005?~)\311!\317Zs= \226\245V\006\237\232p54m\203W\242\227\345\251\213\214u\246y\200\032sJJ\340SFOZqm\2439\250\214\347=h3\0221Q3\324E\3513VZ<\324o\0368\025\013%@\321\324M\035B\321\324/\035D\321\324-\037\265B\321\373T-\0375\023GQ2TL\225\023GQ\264t\302\225\031N*\'J\205\222\242t\244\331F\312\nR\005\251\025jx\305[\217\201Sg\212P\0058\n~8\247\np\246\220sJ\017jx\240\232Pi\352EH\246\246SS)\030\247\356\305*\313\332\235\274\232z\032\223vh\003\232\225EL\2314\3609\247\255N\256@\251C\223O\033{\232p#\326\234d\002\243i\001\035j\276\376iwR\026\342\243-\315\000\326\263%D\321\324M\035B\321\324M\035B\321\324M\037\265B\321\324-\035D\321\212\201\223\223P\262TM\037=*&\216\242d\250\312q\322\230R\242)Q\262T,\225\023\247\024\315\224\004\240\245&\314S\302T\252\270\251\224\323\267\032\025\310j\265\033\006\025&)B\322\362)\0175\031$\0327S\203\032r\232x5*\232\225ju\247\020M\0023N\n\300T\250)\371\247+U\204\306*Q\3075*\200\302\244\tN<\nT|f\202\3704\236n\017ZS0\"\231\277\336\233\273\232vx\244\317\024\323\326\214\327B\311\355Q\264u\013GQ4u\023GQ4u\013GP\264u\023\'\265Wu\307nj\026J\205\220b\241e\250]}j\026\025\031\025\033\nf\312i\216\242d\250^<\324e)6R\354\342\202\224\004\251\025i\341i\301i\nsR&T\325\305\303(4\360\264\2168\252\354\304\032a$\320\265 \025\"\212~\332\221\005XE\030\251\300\033h\31752T\233E\030\024\215\301\241:\324\352\330\251T\223V#\004\n\235M#u4\301Lv\300\250\203\344\323\267`Ro\243q\247\253\346\2274\032@k\377\331"
-byte_png: "\211PNG\r\n\032\n\000\000\000\rIHDR\000\000\002\000\000\000\002\000\010\000\000\000\000\321\023\213&\000\000\002\322IDATx^\355\335QR\2030\020\000\320\016\336\377\3102\216N\255\032\241\224\220\322d\367\275\317(\010\311fI \310\345\002\000\000\000\000\000\000@&SY\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\300\002_\203MN\000\000\000p\237\021\343\350\264 \000\000Pc.\013\000\000H\304h\020\000\000\000\000\000r\261\352<)\r\017,\223\035\000 ,+\303X$0\000\000\000\000\000\000\000r\260>\020\000\000\000\000\000\000\000\000^\304\342\035\326\211\016\000\000\000\000\000\000\200\010<\375\005\000\000\000\340\331\334\203\002\000\000\000\000\000\200T<\"\004\200\261\271\226\003\000\367\314e\001\000\000\020\2121?\000\000\000\000\000\244\343\361\000\000@^^%\003\000\000\000\000\000\000\200x\254\r\005\000\000\000\310\306\033\"\000\000\000\221t2\313\353\3440X\241}\000\000\000\000\000\000\000\000\000\000\000\342\261V\034\000\000\000\000\000\000\000F\343i?\000\000\000\260`.\013F\342~G\003\357e\001\000\220\315\320\003B\216\023\000\220\222\256\317\250\334\306\000\000\000\340!\026\023<\215\252\005\000\000\010fj2\323k\262\023\000\000\000j\231\226A\004\303\364\344a\016\024\270x\r\207:2=\300~r\'_zy\177\377z\034\225q9\367r\032\235\253\254\336\016\034i\340#\333\322J\321\n\323\251\301x\346\337\002V\235\224\215\257=^\307\037\310I\241\001@^\337\343\002\343\203\r\277\257\311\273+k\210\013\372\356\263\312e\2106<D\000\374\023\261J\"\236\023\300\013<\222N\343\217\035 \243Gz\377\2154\020\307O\303\357\010\201\035\277J.B\003\272\247\233\322\324\357\200\362\006\020/\"\257eV\266\276\211\352\231\312\332g0\237\r\250\313\000\000$4\374 p6\033\341\211a\374\274=\323N}+M\233\3371x+\013\342\250\257\2664\326\253h\375\'\304\246\345\001\000\030\325\306\344w\323\321\355\007\261u\223\000\000\000\200\230<\002JJ\303\247\264p\373g\241\010\200\030\\\354!\022=\232\372\201{\375\226\001%\251\214\317\214q\313\032S\340\227\001\000\222\010x\371\nxJp\202(\323\302(\347\001p\036\231\263\324\272FZ\357\257\261\303\203\347\303;\000\030\216\314\007\000\361t>s\343D\376\021BJR@j\223\000HM\322g\233\034\001\231\271N \n\022x\340\303\277\242 0C=\000\000\310\304\014\200\277L\370\001\000\000\000\000\000\000\202\260$\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000.\276\324\010\000\000\000\000\000\000\000\000\000\000iYL\014\000\000\000\320\265\017\265\301<:\355\356j\346\000\000\000\000IEND\256B`\202"
+byte_jpeg: "\377\330\377\340\000\020JFIF\000\001\002\000\000\001\000\001\000\000\377\333\000C\000\003\002\002\003\002\002\003\003\003\003\004\004\003\004\005\010\005\005\005\005\005\n\007\010\006\010\014\013\r\014\014\013\014\013\r\017\023\020\r\016\022\016\013\014\021\027\021\022\024\024\025\026\025\r\020\030\031\027\025\031\023\025\025\025\377\300\000\013\010\002\000\002\000\001\001\021\000\377\304\000\037\000\000\001\005\001\001\001\001\001\001\000\000\000\000\000\000\000\000\001\002\003\004\005\006\007\010\t\n\013\377\304\000\265\020\000\002\001\003\003\002\004\003\005\005\004\004\000\000\001}\001\002\003\000\004\021\005\022!1A\006\023Qa\007\"q\0242\201\221\241\010#B\261\301\025R\321\360$3br\202\t\n\026\027\030\031\032%&\'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz\203\204\205\206\207\210\211\212\222\223\224\225\226\227\230\231\232\242\243\244\245\246\247\250\251\252\262\263\264\265\266\267\270\271\272\302\303\304\305\306\307\310\311\312\322\323\324\325\326\327\330\331\332\341\342\343\344\345\346\347\350\351\352\361\362\363\364\365\366\367\370\371\372\377\332\000\010\001\001\000\000?\000\361\315\336\364\365z~\372z\277\024\340\364\340\364\241\351w\322\357\245\337@zv\3727\323\204\224\365\222\244\022r*e\222\245Y*U\222\245Y*E\222\244Y*U\222\246I*Uz\231\036\246W\251Q\352ezxz\221^\244\017N\017O\rJ\032\2245.}\350\335\357F\377\000z\013\322n\243u4\2651\2151\215FNi\255\326\232M6\212\t\342\233N\355M\017\264\232a\240\364\246QJ:\323\301\305:\212)A\257\036\240\034S\203S\325\251\341\351CS\267\322o\245\337F\372P\324\355\324\273\350\337N\022S\304\2252KR\254\265*\313R\254\265*\311R\254\231\251\026J\231$\251\322L\324\310\3652\275J\255S#\324\212\325\"\265H\032\236\032\236\032\235\221F\354S\203Q\272\223u\033\251\013P\032\202i\204\361M=)\264\323\326\230\335i)\t\305!9\242\214\323OZJF\351M\242\227\2458t\245\315(\030\024\345\031\243\251\257\035\'\002\232M\001\252M\371\245\337J\036\224=\033\350\337@zxz]\364o\245\335F\372p\222\246Y8\251\026J\221d\251\222J\231e\251\022J\231d\251VJ\235\036\254F\365:=J\257R\243\324\312\365\"\275H\255O\rN\rO\rK\272\2245.\357zB\324n\244&\2245\031\244\'4\322i)\244b\230\324\224\215I@\024u\246\265%#Sh\242\236:R\216\264\352wN\235i\017\002\274p\236i\207\255%=[=iA\305\033\2517\321\276\215\364\007\3058IK\346{\323\203\322\357\244\337J\036\244I*A%J\262T\253%L\222T\312\3652=J\257S\306\365f7\251\325\352Uz\225\036\246W\251U\352Ez\220=8=<5.\352]\336\364\355\324n\244\317\275\0314\240\322\320zSh\244#\"\230zSi\t\244\245\035(\003\212CL<\032F\246\321J\0074\352p\024\340(&\222\274u\272\323Z\232x\024\003\232\\\232Bi7Ro\243}&\352P\364\355\364o\243}(zpjxzxz\221^\246Y*U\222\247I*d\222\246G\251\321\352\314oS\243\324\312\365*\265L\217R\007\251U\352@\364\360\324\365jpjP\324\340\324\273\2513\2323\212u.M\031\242\212)\207\275&8\246\3434\3229\247QF9\246\021M\246\221\315\001i\300S\2058t\245\355M\2445\343\354)\215\322\232zSiA\346\202i\215L&\223v;\322n\245\rN\rK\276\215\334\321\276\234\036\234\032\236\036\236\217S+\324\252\3652IS\244\225:=N\217\305Y\215\352\302=L\255R\253\324\312\365*\265H\255R+\324\201\351\312\325 l\322\206\346\234\032\2274\003N\0074\340i\324QE\024\3229\244\246\221\212LsK\2121IM=i\244RR\201J\006)qN\351H}))\255^H\353\212\211\205FE6\212)\204\323\t\246\223M-I\273\336\2245.\3527Q\276\234\032\236\032\234\036\236\257R\253\324\213%L\217S\243\324\351%X\215\352\314oV\021\352dz\231^\245W\251Q\352Uz\221^\236\032\244\rR+S\303S\203R\203\232Zr\232\220\034S\250\240\014\322\355\243\024\3223HE%&9\366\245\240\364\246R54\363@\030\245\245\002\227\024w\244=))\204\346\274\256E\025\003\255D\313L+M\246\340\232CQ\265Fz\32250\223@jR\331\243w\002\223u9Z\237\272\234\255O\rOW\251U\352dz\235\036\247G\342\254F\365f7\253\010\365:=L\257R\253\324\250\365(z\221Z\244V\251\025\252Ej\22058\032pjp<\324\213O\035i\364\001\232u.(\3054\2574\021M\300\244\013F\3321M#4\332B)\000\315;\034Q\212\010=r(\316)\t\030\036\264\323I\221^q-\230#\212\245%\273)5\003G\212\215\323\025\023\014Si\247\255F\302\243=j6=i\244\323w\0323Fh\335@jxn)\301\251\341\251\312\365*\275L\215S\243T\361\265X\215\252\314mVQ\352dj\231Z\245V\251U\352ej\221Z\245V\251\024\324\252j@i\364\341\322\236\247\245J:S\326\236)\324\240f\235F\r\030\024\204R\025\246\355\243m!\024\3221M\"\233E\024\023\203H1\232BsHN(cM\256\035\324\201\310\252\262\250\252\263[\356\031\035j\234\2210\252\354\274\362)\205i\204sQ\265F\302\243a\326\243\"\232x\246\346\214\232JPqN\rN\rO\006\236\032\236\246\246F\251\321\252tj\261\033U\230\332\254#qS\243T\250\3252\265J\255S+T\252\325*\232\225Z\246SR)\247\016\r<\032\221ja\322\244Zx\024\360)\300f\227\024\355\264\230\244\333HW\212B1HE4\212i\024\303\3054\322QH\324\322qKMc\306):\321\\\274\221\007\342\251\317g\351Te\211\223<T\014\003\014UY`\353U^\">\225\013.\rF\313\232\215\205D\313Q\260\250\330sM\"\222\203E\024\365=)\364\340jE\251P\324\310jt5f3Vc5:\032\235\rJ\255S!\251T\324\310jU52\232\225\rL\246\245SR\003\232p\351R-L\225*\324\240S\300\3158\nx\024\273h\333I\266\220\212i\024\204SH\342\243n\224\303\326\232Fi))\255\315!\351\212L\322R\023@<W:\342\241c\212\216H\226A\315gOdW<qT\3326S\317\"\240\270\217gN\206\252\262f\240x\360x\250XTn\265\023\n\215\226\232E3m%\024\240f\234\005>\234*E\353R/j\231*x\352\304uf3S\255N\206\245SS!\251T\324\310jU5*\232\231\rL\246\245SR\255=jE\0252T\313R\250\251\000\342\236\005<-.\005\030\024m\246\221M\"\232E1\2526\2467Jm4\322\036\224\323HFM4\214QI\336\214b\260\336:\256\321\363Q:\225\250\235\310\315T\237\007\234\n\247*o\004\036\265JHJ\216\225]\227\326\241t\250X`\021\212\205\222\243e\246\025\246\225\244+\212LsK\266\234\026\234\253N\305=EH\202\245QS\240\253\021\325\204\251\326\246SS-J\2252v\251R\245J\231{T\311S-J\265*t\251\026\245QS \251\324T\252*U^*EZpZ\\q\322\227\024\204SH\3054\212a\025\033\n\211\273\323)\264\322))\247\255\006\232z\322Q@\031\254\271#\252\357\035A*\340UI\026\252I\031\301\252\3540j\'*3\307\025\003B\222t\252\363Z\221\234U9\" `\325g\371O\"\232@\"\232S\232c.\r4\245\033(\tN\013N\333\3058-8-H\253R\242\324\310\265:\n\260\202\246AS(\251\220T\312:T\251\332\245Z\225je\355S%L\242\246Z\225z\324\252*T\025:\n\235\026\246U\251TS\300\247\001K\203E!\024\322)\264\302*\'\250\230sL<\032i\353Mn\224\332C\326\233\202\0174c&\223\006\200)\325\236\353\305Wu\252\362&j\244\251Ud\312\325YG\265U\221j\273\251\035)\004\244S\034,\200\372\325s\020^\010\342\252\315o\345\234\216\225\031Zi\216\232c\243e(JQ\035.\316)\353\037\024\340\224\360\225\"\255L\251S\"\324\310*d\0252\212\231\005L\242\245QR\250\251TT\312*U\0252T\310*U\0252\212\2325\251\321jt\0252\212\225E<\np\030\245\244#4\332i\024\323\326\243=j7\025\023S\030SZ\232i\224\021\232B)1E\000f\224\n\247\"\340UGZ\205\305A\"\023U\336\017\230\344Uy \374\252\224\260\340\232\254\351P<U\021J:\360EF\351\201\323\"\240{p\334\212\205\243 \363I\345\321\345\322\210\351\336](\216\236#\245\021\323\304t\365J\225R\245D\251UjTZ\231V\246E\251\224T\252*U\025*\255J\242\246QR\250\251\224T\252*t\025:\n\235\005L\202\245QR\255<\np\024\270\246\32251\2150\365\246\036\265\033\n\211\251\207\221M\246\021\212B)(\355\232LP\006(\245\0035Zd\252\255\0375\023FOja\214\n\2511\332j\006\301<\325y\241\3108\351T\036<\032\210\307\232\215\242\250Z:\210\202\246\220\306\033\221\326\220\305\221\310\250Z\035\247\216\224\010\363J#\247\010\351\302:Q\035/\227N\021\323\326:\225c\251\026:\221R\245T\251\025jeZ\225EL\253R(\251TT\252*U\0252\212\225EL\213S\240\251\320T\312*e\025*\323\307J\222\234:QH\302\230\324\306\246\2651\2051\273\324ML=i\244SOJm\030\243\024\230\244\332i@\305-E>\027\202*\262\343\1775\014\355\266B*\234\254s\203P<d\234\236\224\326\2140\342\253\272\3558\252\323C\337\025\t\214To\035@\321\324O\0205\t\214\255\000\236\204S\214\001\227#\025\030\213\006\234#\245\t\201\322\224GN\362\351|\272p\216\236#\251\026:\221c\342\236\251R,u\"\245H\253R\252\324\252\265\"\255H\253R(\251\224T\250*d\0252\212\231\005L\202\246Z\231;T\213\322\244\035)\364\341\322\212BsLja\353Mn\264\225\033TL)\215M=)\235i6\320E\030\300\244\242\212*\'\234J\010a\317\255Ub\001\250e\303\034\324O\020cP\274d\214TY\301 \212\211\343\334sQ\310\234b\252\264x5\031\2174\326\267\357Lkn:T/\001\035\252\026\203\2769\246\204+J#\245\021\322\204\305;\313\247\010\3704\242:p\212\236\261\324\213\036\010\247\210\351\302:z\245<%<-H\253R*\324\252)\340T\212*U\025*\n\231EL\265*\324\311S/j\225{T\213R\016\224\340sJ\016(\'4SOZa\353MaIQ\265F\335j3\322\233HG\024\206\212C\322\233E\024\3401U\031B\277\006\243d\005\261A\203\007\332\230\361\014\234t\250\3320\005R\226\022\030\324L6\214\032\211\315@\343&\243\333J\242\236\024SL\001\252\t-q\332\241h=\251\236V;Rm\000\340\323\225\001\342\235\345sO\020\323\226\032\177\225N\021S\204T\361\035/\227N\tN\tO\tO\tR\005\247\205\247\201R(\251\024T\252*U\035*e\025*\366\251\026\246Z\225MH\rH\246\234\r:\212Bi\264\326\353IM#\024\306\035j6\246\021\203M\"\222\232GZJ)6\2126\322\321Y\242L\032\234\025l\034\363J\316\275\315D]H\340\324.s\221\336\241pH\252\322 \034\223\223P\260\007\322\243x\2062\r@W\007\332\215\270\351J3R \251\n\206\352)\257l\030\014\n\256\320\020zT3Zy\234\343\232\214\332\2748=j\304i\271EJ\"\247y>\324\242*p\212\224E\305(\216\227\313\245\362\351BS\202S\302\323\202\323\202\323\300\247\201OZ\225jU\353R)\251T\324\200\324\252jU5\"\232z\232~y\305;4\026\240\234\212J1\232B8\2445\023u\250\330S\010\342\233HFi\270\344\320Fi\264`\322\355\243m.+)\327i\250\344\233oJ\205\246\'\275F%\307zk\316s\326\205\227wz\212g\343\255Uf$\320X\201Q\254\233\233\006\245)\307\024\252\274T\212\270\251\024dT\250\224\343\006\352j\300\001\351R\275\240e\316+=\3410?N*e@Fi\342*p\212\217*\227\313\243\313\243\313\245\362\350\331K\262\227m(\036\224\340\264\240S\300\247\201R/Jx\251\024\324\212i\341\252Ej\225Z\245V\251\024\323\324\343>\246\237\221E\000\321J\006h\3074\323Q5F\303\232a\030\244\243m7\034\323H\305%.\r\004b\214Q\203X\006r\303\255F\3075\0218\357Q4\230\250\231\363I\347`To?\2750I\315J\256\010\250\310\031\310\251\021\216*U^jP\264\365Nj\304kS\252f\236\"\006\244\021\235\270\3075\r\315\272\311\007NEP\205\010;MY\021\323\304T\276]\036]\'\227G\227G\227I\262\223e\033h\333K\266\227\024\3401N\003\024\361\322\234\017\024\360i\301\251\340\363R!\251\224\324\252jU5 4\264\340sK@\0314\3721L=*&\246\021\232a\031\246\340\321\212\010\346\230E\000QE \034\322\327\037\347\340\324\242\\\216\265\033\275Wv\250\313{\324n\370\250\213\344\322\027\332jA&\006i\310\333\252Q\326\245Y01R$\204\232\267\021\311\002\255\252c\265L\213S*f\244T\3004\325\214;m\354j\235\325\247\331\345\004\016)\310\231\024\361\035;\313\2441\323|\272<\272\nSJR\024\244+I\267\332\215\264m\245\003\024\264\341KN\024\341O\006\245J\225MJ\2652\032~i\300\323\207Zu8t\247\001F0\r1\205F\302\243aLjJZi\034\212B)1F9\244\306I\244\035i\340W\003#`\324\221K\221Of\342\240f\346\243&\243sP\223\3159\362@4\302\347\0254\r\221W\023\221HN)c\227\006\256E>0A\346\264!\270\016\006z\325\221\201\3105<G\'\025r8\362)\215\010G\342\213\333\1776>\234\342\250\300\274`\365\0258\216\227\313\246\262SvQ\262\220\2454\2454\2454\255!ZM\264m\024`Q\212)i\303\2459i\313S/J\225jU\251\227\2458\034\032p<\323\307Zx\031\247\001\232x\034\212\rF\303\255F\324\306\024\302)6\321\214PG\"\232\313I\266\220\214Rw\245\002\234\005y\353\232lm\203R\226\250\235\271\250\313Tn\371\246\250\251@\310\"\241t#4\260\266*\342L6\323\032L\346\232\037\232\23679\255\010&\371pj\344r\345z\325\270%!\270\255\213V\022\n\222H\376`EH\361\356\217\221YrE\345O\354jP\271\024\245i\205i6Q\262\220\2454\2450\2457m5\226\233\266\220\217jB\264\224QN\034\212Q\326\236\265*\324\253S\255H:\032p\247\016\225\"\365\251\007Jx\351N\307\"\220\212ku\250\310\250\330S\017ZJ)J\362(+M+I\266\221\223\004S\202\372u\245\003\265y\313\034\323A\245f\300\353Q6ED\362\001\300\246o\315(5:\020he\334\017\2550Fi\300m\024\322i\321\216j\354`b\245\363\025GZ|S\373\325\350\'$\216k^\302\340\253\202kL]\2430\002\257!W\214V~\245\006\302\255Q\240\342\202\271\244\331I\262\227e4\2550\2554\2550\255#/\025\031ZB1L\"\220\364\246\321N\035)\303\265<t\251V\245Z\225jAN\035*E\025\"\324\200S\300\346\236)\010\246\221Q\260\250\330S\010\246\225\245\3058\n1I\2674\005\240\2574\230\307\"\227\255y\226\372i|TfB\307\024\311f\371\261P3\363B\266jP\307\024\326\224\251\251\341\223p\311\251wTls@\0314\346m\213L\027eF3C]\347\025$W&\257\333NA\353Z\226\367eqZ1\026\220o^\325\243ix\337w\322\237}rfP=)\260\260e\030\251\266Q\262\215\224\205i\205i\245i\205i\273)\256\265\021\024\3021M#\024\3021M\"\222\234\006)\313R(\251W\265H\242\245Z\222\236;T\212*E\025*\212z\212v(#\232i\025\033\n\215\205FFi1N\351J\006iq\221F\3320)\254)\240f\235\214W\225\261\346\230NM+\021\032\344\365\252\216j<\323\323\223V\024qQ\310\2775X\210m\\T\230\342\243\3178\247\240\346\222a\225\252n\204\214\323\0009\253P)\310\255\033u\306+N\3353Z\326\254cR\007z\267h\273\230\325\304\215H \365\250\"\006\t\212\236\235\252\362.E;e\033)\nS\nS\n\323\n\322\025\2462\324%qQ\221L\"\230E4\214RQO\002\244Z\221EJ\275\252E\251\007J\221jE\025*\212\225E=E;\034PG&\232Fi\214\265\033-FV\223\024\3401J\243\255.\336(\333\315\030\024\326\024\335\264\240W\223\274\200\232\214\310#\347\251\250d\224\277&\231\2734\303\322\244\210d\325\225\030\243n\346\251\202\340S\3526\030\247\3062)\322/\313U\230\002\244Tk\036MZ\210\005\253\326\352[\234V\245\252\364\255H\323\013\315hX\303\236GZ\272\360\344n\003\245V\270\217r\206\035EX\266;\320U\215\224\233i\n\323\n\324l\264\302\264\205)\214\265\013\255D\313L+Q\221L\"\233\266\224\014S\200\251\024T\213R\250\251\007Jx\251\026\245QS-J\242\236\264\3521\326\232E4\214\324l\264\302)\204b\234\007\024\016\224\240R\201K\212aZM\264m\257\036\334)\030\202*\'=\252<\363N\251#\025:\034\324\243\255K\232*6\344\324\260\364\247K\302\325Q\311\247\005\300\315>>XWA\247B\004C5\240\221\000x\025i\024\221Z\026G\313\255{E\022\344\366\252\3276\376\\\205{\032\202\331|\271\n\032\274\027\"\202\264\322\264\306Z\215\226\230V\220\2551\226\242t\250\236\007\035\252\022)\214\265\031\024\335\264m\247\001\232z\212\225EJ\242\244\002\234\005J\242\245QR(\251V\244\024\360:{Q\212M\264\322)\214\274\324l)\204QE(\024\3403JG\006\232Fi6\321\264\327\211<\2704\213&iKf\233O^qS\240\310\251\024`\324\252i\364\016\264\326\353SD:S\245\344Ur\2704\3420\265-\234E\344\034q]\035\262\355QWc\031\253Q\n\271\022\364\255\033\"VJ\236\3617\000\336\225\237!\304\252\325~1\225\024\342\264\322\224\306Z\215\226\231\266\220\2550\255F\311\221J\007\313\214\3259#\330\346\243e\250\212\323J\322\005\247\005\247\201R(\251PT\200f\234\005H\242\246QR(\251TS\300\247\201F):\322\021\221Lj\215\273\323)\010\244\247S\207J\\Q\212M\264\233Mx3>M>3R\322\205\247\255X\217\265IN\006\234[\024)\346\232\347\rVa\351C6Z\232W\232k\036\325\253\245\333\374\233\210\353Z\321\256*\334*j\364iV\342\031\305]\210maV\331r\274\325\tb\341\275\252\315\243n\214z\324\373i\n\324l\264\302\224\302\224\322\265\033-0\212h\035j\274\313\227\250\231j&ZaZ6\322\205\247\205\247\252\324\212*AO\002\244QR\250\251TT\200S\300\247\201\223I\353KM=j6\025\031\024\302)\010\342\220\np\031\247\201\232P8\244\002\227m\033k\300:\324\212qR\251\310\2513J:\324\250\3250jz\320\374\nj\036z\320\307-So\331\036j8\245\334\365g\250\246F\233\345\301\255\353B\025@\255\010\271\253\221\n\266\010QSA(&\264-\016\363\232\320\333\224\2523\251W>\206\2133\345\310T\326\200\\\322\024\246\024\2462S\nTl\230\250\231j6Zn\332\201\327-Q\262Te)\205)6P\026\236\026\236\026\236\005<\014S\324T\212*U\025*\212\221E<\nv0\r(\024b\243jc\na\024\302)\270\243\006\234\0058\014S\200\342\225Fiv\320V\276{PH\251UjA\305\033\251\340\323\321\363S\251\316*el\014\322;\356\244AO\333Nq\224\252\340l\220U\370\316V\236\253\206\006\264\355[\030\255Xq\214\223R\033\220\274->9\313{\325\270\t\365\342\267t\325\302\214\326\232\200x\250\247\267\310\351T\304GwNE^\201\211\030=jb\224\322\224\302\224\306\217\025\003\255DV\243e\246\025\250\231)\205*2\224\302\224\205)6S\202\323\202\323\302\322\201OQ\232\225EH\242\245QR(\251\000\305.?Jv\334\032B*6\024\306\024\302)\245i\273h\0034\240S\202\323\200\342\234\213N\300\240\255|\376\211\3058\215\264\270\3150\216h\335\316)\312pj\324g5&h\315I\020\357J\347\232z\234\365\246<;\206GZ|Rm\340\325\220\340\212\265k&2\304\363V\305\311=:U\2302\335j\354m\214\n\275l72\217z\350l\206kB>jm\241\305\"\300\013r*W\266P\233\207Zj.E+GQ\262\342\241qP\262Tl\225\033%0\2450\307Lh\3523\0354\307L)M\331J\022\224-;m(Zz\212\225EH\242\245QR(\251\000\245\013\232R\274\322\025\246\021\212\214\212iZiZM\264\005\342\200\276\324\270\247(\247\240\342\237\267\332\202\265\363\310z\220\035\302\230_i\245V\r\326\224\203N\210d\363V\203\005\034S\225x\311\241FMXP\025i\215\326\234\247\232\264\2106\212\n\002zP\320\020\001\025-\272\222\333}j\373.\300\242\254\301&\000\253\320\215\313\270\326\225\222\347\346\255\273V\332\242\257E\'\025j7\030\253\t\203V\305\271\222\022EWHJ\032sG\305A\"sQ2TM\035D\311Q\264t\202*C\027\265F\321\324M\0350\307L)I\345\322yt\241(\333\355@J\221R\244U\251\025jEZ\225V\236\006)q\232V^@\246\221M+L+M\333HV\223e\033(\333F\312P\265*\255;m&\332\371\315M?8\246\236M=F\336i\341\263ON\265/qOg\340\001R#m\247\207\244f\245S\315ZG\371i\352\t51?--\227\315=h\317\215\271\244\200\363Zv\315\270b\264\254\006\027\236\346\265\242j\273\013qV\243j\225f9\255\033+\254\034\036\206\254\313\026\017\037QU\317\'\030\250\331*2\225\033F}*&\216\233\345sN\020{S\036,T\016\200\n\201\261Q1\024\334R\354\243e\'\227I\345\322\210\351\341*EJ\220%H\251R\254t\355\277\235\033I\024\245~o\302\232\353M\331\3054\2557m\005h\331I\262\220\255\001)v\363R*\323\366\322m\257\233\026\235OAO&\220\003\232\235\006\005\014\370\351\326\225\0079\247\027\346\224IR\251\310\247\003\315M\023\325\204l\032\225\210\333Kb\333_5ry~Z\222\335\270\255\033R\003\036}\253V\325\261\212\323\205\352\334rU\210\237\236M;v\306\2536\363\374\303\025\277\001\017\022\236\365\034\310\025\307\024\307\003m0C\222OjkG\315F\321\3236\200y\245<\375\321\232\212H$<\355\2527\010\331\301\342\230\232t\223\014\203\3051\364\231\201\340\325i \226\023\3104\325\233\261\251Q\201\251\225sK\345P\"\247\210\251\353\035=c\251\026:\223h\003\031\3054t\342\234\240\251\342\215\234\232F^)\233i\nRl\240%\033h+M\331@J6sR\005\247m\243m|\317\273\002\224rje\004\nURjd\217\326\206ni\252\233\233=\252F`\006*\"\340S|\332\225f\305H\'\025$s\n\262\'\030\353R$\273\270\2530\341MO($dt\251m\333#\351W-$\3435\261m.\000\315^\216N\2075r\t\207\025f93\323\245=\344\300\253\232Z\231\236\2728N\334\016\302\222\351\274\307P(+\322\224\216*& TG.x\251\022\304\260\311\346\254\307i\267\031\025bHQ\2418\034\212\307\222\301\245|\355\340V\215\265\210\362\361\322\253\334\332\2721\302\325\t`\3638+U\344\322C\256@\254\331\354d\266bG\"\210f\347\007\255]A\270T\242\032w\225\212Q\0258E\212pLPS4\001\212P)\312\201\263M)M\333AZn\332\021pM\033sAJiZ\002P\023\232\220-.\337j6W\314-\327\0254I\232\234\250\002\223xZ\004\204\323\206\010\346\221\246\n0*\007\233\236\265\021\230g\255 \224f\223\355\031<T\251.j\324\022.pj\304n7\232\271\tSV\221px\253(\300\214\032@\336PoJ\263b\304\214\366\025\257\023\215\240\325\310e\311\353V\321\370\353V\341\227\003\255Jd\335Z\272$\201e\301=k\246\2120\303\216j\031\007\225)\004S\203\2023L\222`:Sc\204\314rzU\273{\022\354\000\031\255\253}8*\r\303\232\230\331F\027\346\034TMom\310\310\037\215R\271x\243\371W\004U\t.\374\263\221OK\246\237\000\016=ju\263I\006p2i\037M\332\271^}\252\215\316\227\346\203\362\326-\316\214\310\304\205\250c\215\3428\"\256\304\003U\201\016iD\030\2441\323JSJR\004\247\204\240GJS\212O.\232R\223e\021(\336wt\3057h\'\212]\224\322\224\004\245\331O\331F\3126\342\276_+\315M\027\002\234\3474\305\033\217\265<\220\243\002\230\322\343\275@\362T\014\304\346\243-\201\326\230\323\205\030\024\304\270\031\251\243\272R~\360\251\243\270UpwT\342\364K.\330\317=\353J\t\n\016\0338\255\010n2\2314\350.|\327\306y\025=\324\241#Q\236I\253\272L\203\313pj\374Rg\201Vc\233oJ\263\034\345\210\253\361I\201\326\245\023{\325\313I\335\034\021]f\237}\271F\356\265\242\n\317\367\2274\215l\2528\006\230\232l\222\267\nkV\317Ge\003w\025\247\035\240\204\002\000\000w5\025\336\240\020mN\276\265\2355\363\270\"\250\3113\214\234\326u\303\310\315\234\324E\333\275\\\264\271\331\216\005_\032\222\241\000\200j\324wbl\005o\300\326\242B\0360J\216j\t4\205\220\034\n\312\276\320J\344\205\254\231,\036\334\344\016*XpG\275Lc\030\246\030\252&\216\232c\244\021\323\266b\224&iJqM\331L)@\216\232\023\004\320\261\322\224\246\024\243m(Jv\321F\005!\025\363\031\207\024\365\2174\331x\030\025\032\374\253P\273\223P\273\036\325\021c\236j\t\256\226>:\232\250n\313\237jx|\255@\344\344\342\205\030\251S>\2654Nbp\312y\025\253mx_\007<\367\025|\336\355!jM:|\335\362x5\241\2527\357\"\301\253\266Rl\003\007\255^\212@\016j\302M\353S\305>\326\253Ix\007\031\253\226\357\346s\232\327\266p\2523Z\366\027#x\346\273\0355\342h\301\343>\365\246\202\'a\362\256E[Y\341\204e\312\375\0054\352Q\020|\244\371\252\255\305\343\260\3015\234\312X\365\246\224\305D\321g<Ui`\252\217\t&\232\250T\324\241r2GJ\236\027\332F\0075\273\247\335\235\241X\234V\314\005X\214sWR\331e\0048\353To|>\245K \310\256_Q\322^\331\213\250\342\252\304\341\270=jM\231\246\264u\031\216\201\035.\312_/\024\206>)\276_4\215\036)\002qQ\264y4\340\230\024\326\030\250\330\200i\245\205\033\351wf\223\'\322\227k\036\325\363l\240b\243-\306\000\250\235\017z\206V\300\305Vy\002\216j\263\334zUi\256\t\035j\204\317U\314\2705$w&\245\3633\315(l\324\253 \024\341-M\014\373\016{\326\204R\007\217,y\246\245\323C e=+n\336\344\3370s\321Ei\371\236\\(\300\365\353SAu\2209\253q\317O3\342\226+\222\322\201\232\354\264\255-\347\263\363T\344\016\265\"\304\352\3705\241lV!\223\232\331\262\324\037\205L\327Eg\024\322\000\314H\025tG\014|\312\347\351K\366\204l\354 \n\211\233q\353I\260\nP\271\245(*6\2105B\366\243\322\243\373(\364\251c\264\004t\247\013\002\016@\253\021\304\312\000\305l\351\247n3\326\267 a\273\236*\342\251\034\365\025CP\323\222\355Xm\003\"\270-^\301\264\373\202@\3434\226\354%\\\324\206<\323LT\202:p\210\nk\'\"\225\243\342\231\262\230\313\2126\214S\n\014\324R8QU\036R\307\013\315=-d\222\237\366\006\035i>\317\315O\035\241\307Jx\265\365\246\233r\005|\316\321\212\215\200^\325^g\252s>\321\223Y\322\310X\325w5ZF5VSU\230\322\006\305M\034\270\247\371\274\323\204\264\345\222\247Ij\3147\007\033GS\322\231qr\321\235\204u\256\257D\001\355P\251\346\256_I\265\021?\032-_ V\234.\000\246\31575sO\204I\2065\330\351:\240\266\267\362\331\210^\340T\217\253!\223(\270\255->\361g\341\324\021\353]F\227\035\267Ta\307^j\375\316\261\014\021\354\214\344\373Vg\366\213J\371,M]\202`\303\255]\210\347\275K\234\n\024\323\217\326\200i\335z\322\210\203T\221\305\212\230.\323S \007\265Y\210\205#\265li\350e g\212\336\026\270^\230\342\241\226\000\007\245r\376#\323>\320\204\205\344W\031\3455\224\270\376\032\277\024\211*\360y\240\2504\004\002\232\330\246\344\021\357Mi\024\016\265\003\316\253\236j\273\334\022x\006\232f\177\356\232\211\345\224\364\024\211m,\315\222\016+B\323O\003\005\205^\020\254t\331\006z\n\200[\344\364\251\226\026\003\245#@i<\203_-\025\342\240\220UYx\254\331\330\261>\225RN*\273\363U\344\342\252\3103P0\246\021\203FiC\032]\364\345\222\245I*Xn<\271\001\253\027S\tP7|\327Q\240\312>\314\006{U\253\213\324-\264\200H\247\301>G\025q.\n\367\246\033\215\362\343\275lZM\344 \2558%i\007\025z\312\331\356&\013\320w5\270dKX\374\2449>\264\370/$\214aX\214\325\250\356\031\210\311\253\326\362t\346\264\355\346\3069\255\030n*\322\315\221N\363E/\231\357NI9\251\203\003SGS\201\212z(52&\rH\020\365\253\266wf\331\201\315uZu\374w1`\237\233\247\326\246\222\334\222x\2527vbE9\034\327\037\254h\3409\300\256z]2h\3331\346\232\"\272Q\367sM1\3351\341\r\013ev\347\241\247\377\000e]\361\326\236\272\r\303\237\230\232\267o\240\017\342\353W\323\303\252\313\220\234\nsh*\247i\217\255B\372\032/\360\212g\330\202p\026\232m\034\366\3058Z\0009\315\r\002\212a\210\016qM\300\024\215\322\243\'5\362\243\325y\016*\224\347\203Y\322UIj\006\250$\031\252\356\265\013%D\313L\305\030\246\265\000\342\244V\247\023S#\251\210\344\234\326\326\213\250|\230\317J\236{\255\322u\3475\245e.TU\326\223\345\252\361\317\211\253~\306_0\014\212\337\264\001@\025\250\227^Z\355N\017sOG$\344\232\263\023\325\270\246\003\025z\t\272sZ\020\317Wa\230\325\245\234\201S$\371\251Vjz\314*d\223=\352\324-\357Vs\357OG\253H\331\025:6iYy\255m\036q\014\212I\342\272\264\221&\213*Fj\264\213T\256\264\370\356:\216j\224\232*\001\367A\252si\213\0318\216\232\226q\201\314u\033\300\021\301U\375*\322\303\347(\312\014\323\326\300g\240\240\330\252s\212Q\"\304\245GCUn/\001#\004\234T\002\361H;\207\025\004\2270+q\326\2315\312\0206\212\256d\310\342\253I\'5\003K\357B\266h-\316)\207\255|\256\353UeZ\316\272nqT%<UG\031\250\331x\250Yj&J\215\243\250\232:\214\307M)Q\262\323J\322\241\247\343\212\257uq\366x\313\003\310\246\370wQy%b[\255t>c<\2035\261g.\024U\2636EWi6\276k\243\322g\037gS[\326\227\001\272V\214\017\315[F\351R\211{\n\261\013\223Wa\223\004V\214\023\014u\253\221\335*\325\210\356\301\251V~z\323\305\307\275(\2719\353Va\271\367\253\261\\t\346\255%\317\275J\223d\365\253p\315V\342}\325a\006\352RZ&\004\036*\375\256\271\344\220\273\215n\331\352Q\335(\317\006\256m\004dt5\013\361Q\260\007\265F\366\341\207J\253%\253\026\3501SG\010A\323\232\227`\025V\356\345\023+\322\262\'\221\233$0\366\346\263nD\301\263\234\325+\206p1\272\240F#\251\251D\345i\317p\n\361Ud\227\320\324&Jr\315\212x\223u\005\270\257\227\034U+\211\000\004\n\313\237\223U$Z\205\222\243h\352\'\216\230c\250\232<TL\265\023/4\306\025\023\212\215\2052\236\033\212\305\327\256vB\300T\236\014\204\312\373\230q]s\361>*\375\273`\n\266\017\025\014\355\212\335\321\344\006\325k\242\264\235c\\w5~\t\363WR_z\261\021\004\362j\354S,G\221\232y\270\334\331Q\201R\307rj\344S3U\250\345#\255YI\375\352E\227&\244Y*x\245\305\\\216j\235\'\307z\263\035\300\253pO\236\365\245n\371\305hD\303\326\222v\317J\241(*\331\006\257i\232\237\225 \004\327ogv\223[+g4\255\206\350j\026\034\322\006\305\034R\034\016j&\270S\307\245d\352E\230\022\275+\"Y\0368\316EV[\206c\317\024\331@|\234\346\242\020\361\232\212D\305@\306\242sQ3R\006\241f\332i\3170\257\230n$\'\201\322\263\3465Q\306{TL\225\021Jc%Dc\315>;A $\234\001U\'\214\0068\351U\231j\007\025\023\365\250\030\363Q\261\31574\036\225\201\255!\222@+\240\360\335\260\264\264\334:\342\266\027;\301=j\344-V\343$\212{\303\274U\373\005x\225\177\273ZQ\\\025|\347\212\324\265\273\334G5\255\004\333\252\345\273\000\3375^\371_\356\3475<@\201\310\024\354\220\331\305\\\267\272T\034\324\246\3441\342\244I\252U\270\307zz\334\325\210\356\300\357VR\354\036\206\247K\234\367\253\021\314I\253\220O\267\034\326\265\255\320\332*\354w\031=j\304o\272\243\232\252I\230\306\352\331\360\366\264\312\376[7\313],w\300\236\265+] \004\356\252\346\365\007\\Trj\360\251\3015Fm\\\310HN\225X\3371=y\365\252\3677\217!\0377\002\253\3110e\347\223UYw\036*T\213+\311\305!M\243\257\025V^MU\223\212\211\272T/Q\206\301\244-L/_5\315\315R\225rj1\036A\250Yj\027J\214\2554\2551\211\003\025ZE\252\322\014UY*\263\265B\315Q\023H\006MI\217\226\2615\023\231\306k\240\321\263-\270?\302+dD\276\225<J\007\025n0=jp\350\275M]\267\2342\377\000\262)\223\337,@\214\363V\364\353\242\370\346\272\013Y\360\0075\241\024\345\271\253\326\367\\\325\344\270\367\251|\340GjO3\232\225\037\035\352e\227\024\357?\336\227\316\367\244\373Q\007\255X\206\350\325\373y\311\255+yCU\330\230V\205\264\200b\257G(\315[\216|\016\264\2179&\234@\2251QD\237gl\212\322][\010=iN\250\344}\352\215\265\006\317S\212\211\347.sJ\223\0200*@\374T.\325\036iD\201G\275!\270\'\212kM\305B\362\003U\335\262j3\326\242q\232\201\2704\306jc5|\335\'5\003&i\273q\326\241d\250\232:\211\243\2462\347\034TN\270\025VJ\251-S\224\325G\250XsM\333NU\247\221\362\326F\247\001\373\325\243\341\333\276\221\263\000\243\326\272U*\330\000\203N\311SO\0227\255*\253\271\357V\205\300\2116\203\322\250M3K?^3[\332Q \n\336\202\\b\265\354d\016@\255\035\252\243\212\004\333OZ\232\031s\336\254+z\232\221^\235\346\320f\367\240M\236\365\"\362z\324\3616\r_\206p\275\352\374\027=9\253\360\334U\330nj\365\275\306j\322JMI\346f\247\206J\225\317\031\250\017_j\2250E)\305\002A\322\236\016i\341\270\246\273\003Q\227\024\302\365\013\276\r0\2754\2654\2654\232\211\252\'5\023\n\215\201\305|\350\353MT\000\344\323\035F8\352j\006L\032\215\226\241\221j\006\025\004\246\252Hj\244\325NQU\331sQ\262\3236{S\325i\3413U5\0107!\030\254C\346[\266W5\241\247\353\357\024\237\275\311\000`V\375\236\275\034\307\004\376u\246\227\261\354,\024Uy\265bx\035=\250\216\3540\353\315X\265_1\301\256\202\315v\250\255\010\244\301\255;+\235\254+Un\262\274\232`\233\3465<W\030\3075en3\336\236\'\367\247\211\250\363iD\2305f\007\334z\324\245\360z\324\360\311\232\277\004\265z)\252\314w8\357Wm\256\371\034\326\214W@\367\251\326q\353Vc\234z\324\302p\303\031\246\226\316y\241&\npMK\27053\200x\247\211p)\336nh2qQ\227\250\331\352\'jf\372M\306\200i;PFEV\224\021Q\006\317\006\226\276xd\250\331*2\244Tn\230\025\003\016j\t\020\232\257 \252\322\014\325i\026\252J\265RE\250Y*2\224\233)\313\036jdLT71\206\025B[!&x\252m\247|\335(6o\013dqZ\266^`\213\004\232\225\241b\331\253v\321s\315i[\376\351\201\255\253iC(\"\256F\325n\t0j\352\\p9\346\245Y\263R\244\274\325\230\346\342\237\366\214S\305\317\2758NOzp\232\255\333K\315J\323|\325b\tsW\342\226\254\244\370\251\205\306;\325\230.\262@\315hE+c \361W\241\233\216je\270\332z\361S-\317J\224N\017zR\373\273\363R\3076\325\346\227\355\000\232C-9e\247\371\234R\027\315F\317L-M&\226\202qH\017\255\014qQ\270\334*\253.\032\224t\257\001h\3526\216\243h\361PH\265^D\346\243q\305S\225y\252\356\265^E\252\222\245Ut\250\236:\217e\'\227R\244t\262\020\007\025\\\215\335i\2166\212O+r\206\3052A\270\201\212\2363\264\001\212\227\315\036\224\370\346\346\256\302\373\205iY>\016+V20*\324m\212\235\034T\253 \035\352d\222\246Yp)\014\246\236%\342\244\216l\232\267\037\315\311\253\"E\215i\2136\346\253qK\266\255\307qV\226s\214\323\226b\306\246\216r\216+b\336\364\025\034U\265\273\004S\232\360v\251b\273\317z\267\024\343\326\247\023\347\024\3637\024\007\3179\2452b\205\237\025\"\316\r;\314\246\264\224\303%(\177Zx4\247\2450\360h\335\270b\230[\025\023\220i\233\253\302\332:\215\243\250\235*\274\221\325i\020\364\355PH\225ZH\352\273\245W\221*\254\251U\232:\211\343\246\030\375\251\004t\355\270\250\235\t\246\371x\250\245^)_\210\300\250\025rsV\025sH\313\315*\014U\270\037\006\265-_\245jD\331QR\265\306\316)E\331n\365<sg\034\325\330\233\216\2656\372B\324\340\36542\005<\325\345\223+\305F\362\232X\346\301\253Iq\232\261\024\365v)\362\270\315K\034\373Z\2375\326:U\213+\334\361W\226\350\251\353R\375\243v9\2530M\216j\352\\c\275L\227>\365/\332\3061\232Qw\357K\366\234\3654\323s\351OK\217z\231n=\3503\347\275\002l\324\210\371\251\225\360)\373\270\246\271\250\031\360i\036L\212\204\2774\322\370\353^:\361T/\025B\361Uy#\252\262\307U\336:\256\361\325y#\252\362GU\244\2135\003EP\264\\\323LX\246\230\361M)Hc\246<|UYS\232\211\301<P\211S\242\361C/4\252\265$jKqZV\252x\315j\303\302\212s\214\324c\203V\242\"\256\305&\005L\262S\367R\207\247)\253\260>\0074\371Xb\241\r\212\2269j\314r\325\230\347\305XIw\016\265&\375\3255\261\332\325\240\262dS\322S\232\271\035\306\005L\227\031\357R-\316;\323\376\324\017z\005\326;\322\213\302;\323\205\326OZ\231\'\367\251\026\340\324\213!525L\217\203V\025\370\247\207\240\277\025\004\217\203P\263\346\242\222]\203\232\204\334f\274\335\241\250$\213\025Y\343\252\362G\305V\222*\254\361\325i#\250\036*\257$u]\342\250^,\n\205\242\246\264u\021\216\230\311\212f\332FPEV\2259\250LY4\242<S\300\3050\214\232*X\216\326\310\255;w\034V\214-\221Ov\305D\307&\246\2175f2EN\254je5*\232\221H\251\221\273\322<\331\3434\300\3475*\032\261\031\251\321\215X\211\211\253\010\325</\203V\326^)\313!\006\254\244\274T\311%<\2754\315\266\223\355\006\234&\317z\225$\346\254\307-L\262sV\021\216EZF\342\237\276\254G/\024\246Oz_8`\325w\223&\243g\305W\232^*\233Jk\224x\261U\236<\236\225^h@\307\035j\274\220\325Yb\252\317\025V\222*\202H\252\273\303P<=x\250d\212\2410\324o\027\025\031\213\025\013\307Q\224\250\335y\250^:\217e!ZiZa\024\2305\"\324\320\312T\326\225\254\306\256\277\314\240\323\027\255Y\214\214T\361\214\324\352\231\251\225H\247\205\247\001\315J3\212\214\241\315=V\246E\253\021\212\231jx\233\025aNi\312\374\325\210\244\305Hd\346\255E&EL\r;w\035j6|\323w\342\234\262U\204\222\254F\370>\325r!\273\025r5\310\251\025\361\305+>\005,s{\323\314\276\364\206\\\320\016y\250\345\224c\002\251\311&sU\331\361X\262EU\336.*\007\207+\223\370UY\"\252\262CU\336\032\201\341\252\357\rWxj\007\206\240\222*\205\242\250d\212\243h\370\250\036*\210\307Q\264U\023GQ:`\324l\265\033-4\255&\312xZtk\315\\\205\261W#\237\261\251@\311\251\243SVS\212\261\033U\205aN\363\005804\365lP[\232zsS\250\251\001\002\236$\003\275=e\305?\355\024\236y\315X\212\3435n7\334j\334n\026\247Y3N.\000\250\333\236\224\314\232z\222*Uz\267o&x5\245\010\300\315XW\"\236\030\036i\344\344T,\333\032\234\037wz\221\010\035h\226A\267\212\245$\325]\345\315D\322T\017\035Wxwg\025\013\305\307N\225VH\263U\336\032\256\360\325w\206\240xj\274\220\324\017\rV\222\036zTM\rA$U\023\305\305@\361T-\027\024\303\025D\320\324\022\307\315@\321\340\324n\224\335\224l\243m9EL\202\254F\231\253\366\321dU\237+\002\234\274T\252\334T\201\215<\034\324\252iK\343\275.\343BJA\251\326~)L\371\246\231\211\251#\220\223S\256MH\020\232\263\004x\253i\205\251|\334\016\264\370\3469\353OyH\357H.*dp\324\360i\352jx\233\004V\235\274\370Z\263\274c\2553\316\000\323\332\343\345\342\243V-\311\247\357\330:\324-tsA\271\310\353P\311&j\006\223\232n\352\266\361f\241xq\305Wx\252\273\305U\336\032\201\341\252\362CU\336\032\201\341\252\357\rWxy\250^\036\265]\342\250^*\201\342\250\232*\214\305Q4\\T\022\305\223P<U\004\221\361M\362\350\362\351\014t\212\2252%X\210sZ\020\036\005X\335\221J\027<\323\325j@1NQR\016)\257\222iU\217Jr\212q4\252i\352A\251\220\212\235\010\253(\303\025 }\264\344\270\031\247\371\273\251\361\276\rJ\0334\001\223S\240\251\343\313T\240\034\323\320\342\255G)QS\254\245\252P\007sNR\001\353O2\205\025\033\312\010<\325C\'\314i|\312k?\025\01374\241\253q\342\250^*\201\342\252\317\rB\360\373Uw\206\240\222\032\256\360\373T\017\017Z\201\340\252\257\027&\240x\252\007\212\240x\263P\274U\013G\305F\321qP<~\325\023E\232\202H\252\274\261qQ\371t\010\350\362\251<\252z\307SF\230\253(\330\2517\361B\312U\252\344L\034T\333x\245U\245\344Py\250\230\2254y\230\247\007\315=MH\247\025*\032\260\206\254%HA\"\232\"5*\253\001SF\010\251A\3059^\255E\202*t\030\346\247\214\006\025 \213\006\237\214\ntR`\322\264\270=i>\321\212q\270\014*#7\2750\276M?w\024\233\275\3526\353@8\256\261\342\250^*\201\341\250\036\032\201\341\344\324\017\rWxj\007\202\253\311\025V\225\000\252\317\025@\361Uw\217\025^D\252\356\270\250Yj&\025\037\225\232cCP<\\\364\250%\207\"\2411b\223\313\245\021\322yt\010\352UJ\221R\244\021\322\030\371\251a\312\032\276\230u\025*\245#\256\005Uw*j6rh^\265*\214\324\250\265&\312\2265\253Q \253H\200\n\\\363S\3063R\354\030\245\010\0055\270\242>\265i\033\02529<U\250\201\002\255)\241\372\232\210\034\032d\217\201P\tw\034S\367`S|\317z]\344S\326L\323\267R\023\232h5\377\331"
+byte_png: "\211PNG\r\n\032\n\000\000\000\rIHDR\000\000\002\000\000\000\002\000\010\000\000\000\000\321\023\213&\000\000\001\213IDATx^\355\335\313\n\2040\014\005P\321\377\377\344\021q1\013C\231\301\0073Mz\316\362.\004\241\332&\021\234&\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\200!\3151\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0008m\215\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\333\034\003\000\000\000\000\000\262Yb\000\347\230\026\000\000@\022\016\357\000\000\320\2455\006\351\274\357@\321\001\000\360o>\003\202\316)\233\000\250\"\177S\023:\366\212\001\000Y\335?3\035;\t\367\257\007\017\260\020\001\340;\003!\000h\260A\322h*4\"`\010\236~\000\000\000\000\200\252\214\005\001\000\000\000\240\006_{b\r@\035\3467\000\037yM&\342\017\014p\201\342nX68\000\000\200\003e\022\000\000\000\300(\366N\220n\020\000\000\000\000\000\000@u&\303\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\300\317m\204\275\016\017\263vs\375\000\000\000\000IEND\256B`\202"
diff --git a/core/res/geoid_height_map_assets/tile-b.textpb b/core/res/geoid_height_map_assets/tile-b.textpb
index 83d160b..b9b5bfc 100644
--- a/core/res/geoid_height_map_assets/tile-b.textpb
+++ b/core/res/geoid_height_map_assets/tile-b.textpb
@@ -1,3 +1,3 @@
 tile_key: "b"
-byte_jpeg: "\377\330\377\340\000\020JFIF\000\001\002\000\000\001\000\001\000\000\377\333\000C\000\004\003\003\003\003\002\004\003\003\003\004\004\004\004\005\t\006\005\005\005\005\013\010\010\007\t\r\014\016\016\r\014\r\r\017\020\025\022\017\020\024\020\r\r\022\031\022\024\026\026\027\030\027\016\022\032\034\032\027\033\025\027\027\027\377\300\000\013\010\002\000\002\000\001\001\021\000\377\304\000\037\000\000\001\005\001\001\001\001\001\001\000\000\000\000\000\000\000\000\001\002\003\004\005\006\007\010\t\n\013\377\304\000\265\020\000\002\001\003\003\002\004\003\005\005\004\004\000\000\001}\001\002\003\000\004\021\005\022!1A\006\023Qa\007\"q\0242\201\221\241\010#B\261\301\025R\321\360$3br\202\t\n\026\027\030\031\032%&\'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz\203\204\205\206\207\210\211\212\222\223\224\225\226\227\230\231\232\242\243\244\245\246\247\250\251\252\262\263\264\265\266\267\270\271\272\302\303\304\305\306\307\310\311\312\322\323\324\325\326\327\330\331\332\341\342\343\344\345\346\347\350\351\352\361\362\363\364\365\366\367\370\371\372\377\332\000\010\001\001\000\000?\000fy\245\006\202sE\024R\346\224\0323\357J\r=Z\236\032\237\272\215\324\340\324n\243v(\335\223O\337\205\300\250\313\323K\323w\321\276\224?\2758=8I\357O\022\373\324\202S\353O\023{\323\274\363\353@\234\372\323\204\376\364\3617\024\34158M\357N\363\250\363\275\351<\336x5<R\347\251\253\005\262)\204\215\270\254\273\3051I\221\320\324K!\"\224\2755\236\243/M\337\315)z7\322\027\244\337H^\205bM[\213\205\247\023M\335C>\007Z\201\256\000\357Q5\310\365\250\232\346\242k\234\036\264\326\273\000T/z\000\252\315xI\353W(\245\315&h\242\2274\240\321Fy\247\003O\rK\272\2245;u.\352Bis\201\3154\2654\2650\265&\3527Q\276\224=/\231N\022{\322\371\336\364y\336\364\3417\2758K\317Z\221X\232\224\023N\016iw\232w\231F\3727\324\261\315\203\326\254\254\331\034\032\014\240u5Z\361\326H\376\225EO\034S\213\361L/L-L\335\315)z7{\322o\244\335Aj\226.Nj\342\364\306i\030\250\352j\027\231W\275S\232\353<\003U\332R{\324fJas\353Q4\234\324M\'\275@\357P\274\230\255\343\322\212L\321\223Fi3\315.isFM\024\271\247\003J\032\2245(j]\324\273\271\241\245\312\201Q\227\246\026\244\335I\272\233\276\215\364\027\244\363(\363=\350\363=\351|\317zp\222\236\262sV\243\220c\232\233\314\024\236o4y\207\326\227}\033\350\337J$\346\245Y\215=\245\312\373\325Ig \021Q\243\344f\234_\212\211\237\007\2554\2757}\033\351wqM\335NV\024\027\311\342\254Dp*_4\001\301\252\323\\\340\340\034\325\'\230\261\316j2\3714\322i\t\305F\315P\273TE\252\'j\205\216k\244\244&\222\212L\322d\322\346\2234\271\243\"\234\017\024f\2274\271\245\335J\032\215\3704\302\324\322\364\302\324\233\251\013\322\026\246\357\244/I\276\220\275\'\231I\346sR\251$g4\355\3705*\334c\275J.\001\357N\363s\336\224K\317Z\220J=i\336e\033\370\244\337O\022S\314\270Z\257+\023\021\"\233\031\371E+5D\315L\337F\356h\335K\272\233\273\232P\324o\346\246\023`To9\307\006\253\226\'\2754\322\023M&\230Z\243f\250]\252\"\325\0235D\306\272|\322Rf\222\212L\321\232J2isFisK\2323K\272\215\334R\026\246\226\250\331\251\245\2517SK\322\027\246\227\246\227\244\337H^\230d\244\363=\352E\237\003\255)\237=\351<\337zp\233\035\351\353p}jD\234\223\326\247Y}\352A/\275<IK\276\234\032\226G\302\342\221[r0\246n\300\3054\275F\317L-I\272\2245.\343@98\245\346\216i\030\361L\315&}\3513M-\3050\265F\315Q\263T.j\"\325\031j\214\232\352h\244\343\232JL\361IE!\353IE&i\300\322\346\214\373\322\216\005&ri\013Tl\325\031jilSwf\220\2650\2754\2750\275\033\351\206Ja\222\232d\243\315\367\243\315\367\247\t}\351D\264\242_z\221&\301\353VRl\212\231d\367\251\004\224\361%8KD\222\360\006ic\224\003J\347\370\205DZ\230Z\233\272\227u\000\323\306M=p)K\014TL\376\224\204\323I\244\315%4\232\214\232\215\232\242cQ9\250\230\361Q\223L&\272\312)\264Sh4\231\244&\233\237z3I\232Ph\317\275.}\350,i\001\3434\205\252&j\214\232c78\024g\002\230\315Q\226\246\027\246\027\246\231=\351\206Ja\223\336\232d\244\363)<\312Q-8KJ%\367\247\t}\352\304S\201\336\254\254\336\365*\312=i\376p\305\002Nz\3224\271jz\311\357R\244\204\241\007\261\2463\214\323I\315\031\245\006\224\037Z~\3768\244\336h\337\232L\322f\220\232N\264\204\323\t\250\230\324lj2j&5\033\032\214\232\214\232\353\350\244\"\222\233E!\353M4\3123\306)3\315\031\2434f\202h\'\024\302j2j6l\n`9\346\220\265F\315Q\227\250\331\3522\364\302\364\302\364\302\364\303%4\311I\346P$\367\247\t)\302J_7\336\224M\216\365*\\\220z\325\244\234\036\365:\313\232x\223\276i<\301\277\255J\222\017Z\225e\000\020)7\321\2734\240\363N\315\000\363N\335I\232p\342\202i3F3HO\024\302j65\033\032\215\215F\306\243cQ\223Q\223L5\330\212C\326\212i\353Hz\322R\036\264\323M=i\246\222\212L\320\247\234\321\236i\t\250\330\324d\323\030\347\212i5\0335F\315Q3TL\325\031j\215\236\243/L/Q\231)\276e!z<\312<\312_6\227\315\245\022\323\226Oz\235&\307z\265\035\307\024\363?\241\247,\271\347\275L\262\032\263\013|\214\177\n7\032z\26585.ri\300\342\22794\341\307Z\\\320M \365\245&\230MFMF\306\230MF\306\242&\230j3L&\243c]\225:\220\212i\244\244\"\232i\017Ja\246\236\264\334\320\0174\215\305\000\341sM\0353\353HM0\232\215\215G\357McQ3TL\325\0235D\315P\263\324L\365\031\177z\215\237\336\243/M/Hd\246\371\224y\224\276g\275/\231K\346{\323\204\225*\311S$\206\246W\311\2531\232\235MN\222`l\251\003sO\006\235\234\323\301\245\316jE\030\353N\315!4\224\271\244&\230M0\232\214\232\214\232\215\2150\323\r0\324mQ\232\354\351GJZB)1M\"\220\212a\246\265Fz\323i\t\246\261\342\227\370@\240\323\rF\306\243\'4\322j&j\211\215D\315P\263T,\325\013\265D\315Q3\324e\251\205\251\245\251\205\2517Ro\367\244\337\357J\036\234\036\236\255R\243T\350\325a\033\232\265\033qVQ\266\215\304\360) b\316[\326\255)\251\001\247\203N\0075*\3603N\315\031\244\317\255.\3523M&\232M0\232\214\232a\250\3154\324f\230\325\033Tf\273JQ\322\226\212LRb\232E4\212cTf\230zSi\214y\305H=i\033\245D\306\242nM4\232\211\215D\306\242f\250Y\252\026j\201\332\241f\367\250\231\252\"\324\302i\205\251\245\251\205\251\273\251\013\032M\306\227u8\032\225ML\206\247J\235\rXF\307SR\202\362q\310Z\264\230U\300\251\225\252E8\247\203\232\221H\024\360\324\273\2517Q\272\215\324\271\244&\232M4\232a\246\032a\246\032a\246\032\214\323\rv\230\245\245\305)\031\244#\212JLsM\"\243aQ\260\250\330S\r1F^\245\2461\250\230\324,\334\324l\325\0235D\315P\263T,\325\0135@\315Q3TLsQ\223\212\215\2150\232\214\2654\2654\265&\3523J\030S\301\364\251\221X\373U\210\323\025eFjd\025b<\016\242\247V\025 l\364\251\224\342\236\032\234\036\236\036\234\036\203%(jP\324\240\323\263Fi\244\346\232M4\323\017Ji\246\236\264\302)\204Tf\230\325\332R\342\226\212(\307\024\334R0\250\310\250\330Tl*6\024\2120sJMF\306\241v\252\354\3315\0335B\315Q3T,\365\013=B\315P\263TL\325\031j\215\232\243f\250\313S\013SKSKQ\237zQ\311\344\323\327\006\246R\242\245W\0252\275L\217S\243\324\352\325 \177z\225X\001O\363)\302Ozx\222\236\036\227}8585<\032p4\354\321\221A4\334\346\220\323M4\323\010\246\232a\025\031\246\032\355h\240u\247b\220\2121\305%!\024\302*2*6\025\023\016\324\323\301\2461\250\230\324\0225@\306\241f\250Y\252\026z\205\236\241g\250Y\352\026\222\241i*&\222\230^\2432S\013\323K\322n\244\334)\014\200P$\356i\342^i\352\374\365\251\225\352ez\235\036\247Y*U\227\260\251\026@;\323\374\352z\311\357O\022T\202Jxzz\265H\032\236\rH\r8\032p4\271\244\'4\264\230\244\"\232E4\212i\025\033TdS\010\256\327\024b\226\212(\"\212i\034\323XTdTdTdsQ5D\306\241sU\230\344\223P\273Uvj\201\336\241g\250Y\352\006z\205\344\250\031\352\026z\211\244\250\332Ja\222\230d\246\031=\351\246`\007&\231\347\026\351J$\247\007\367\247\253T\252\306\246F\251\325\252E\222\245Y\017\255J\262b\236%\367\247\211=\352E\222\244W\367\251C\373\324\212\325*\265J\255R\251\247\203R\003N\006\224S\200\315(\024b\202)\244S\010\246\221Q\221Q\221L\"\273J)qKF)\010\243\034RS\010\2460\250\310\250\237\241\252\347\245D\306\253\310x\252\354p*\273\265Wv\250\035\252\006j\205\332\253\273\361U\331\371\250\031\363Q3\324,\374\323\013\324M\'\275Fd\250\236b;\324[\3119\251\021\373\342\234\030\023O\rR\251\346\245V\367\251Q\327<\324\202^\302\244W\251U\233\031\3058HI\300\247\356\"\236\262\034\324\253)\251\203\234S\326C\232\260\217\221S+T\352\325*\232\225jAO\002\236\005<\np\024\270\366\244\"\232V\232EFV\230V\230E0\212\354@\245\242\212(\2434\332C\326\2434\306\025ZS\203\212\205\215@\346\253\310{Uw<Ui\rUv\252\356\325\013\265B\315\305Vv\342\253;T\014\365\013=B_\232c=D\315P\264\225\03357w\275=X\221R)5*\324\200\323\203sOROJ\224d\016jh\330c$\324\206\\w\247$\242\247\022\206\340\212p\035\326\244_z\235\010\25103R\243U\2245:T\353S-J\242\244\002\244\002\236\005;\024\270\243\024\322\264\322\264\302\264\302\264\302\265\031Z\353\250\242\212)\017JJL\322\023L4\3065RC\227\250^\240sU\244<\325y\033\212\253!\252\256j\273\236j\027j\205\333\214Ui\032\252\273Uwj\201\232\242/\315F\315Q\263\032\211\216i\233\275h\034\236*d\030\034\323\307Z\221zT\310\204\365\247\355\013\316)\276q\007\002\244\014XS\267\221F\362MO\020&\255\"\234\325\264\217\212\223h\306\010\247,|\361RmaNN\265i*\314ua\005N\242\246QR(\251\000\247\201N\013N\305\033i\n\323J\323J\323\n\324l\265\031Z\352h\242\212L\322\023HM&i\244\323I\250\330\325G?1\250\234\325g5ZS\315V\220\325g\252\362Ug\250\034\325w5^F\252\316j\273\232\256\346\241cL&\243f\250\231\2513\232p\3009\251\224\202)\341j\302\021\266\247\217\024\367\\\257\025\\\307\206\311\247\006\n)7\344\324\2503V\341\034\326\2141\344t\253!@\247\005\315=W\006\246T\004`\323\014{Z\247\214qV\022\254\307V\020T\352\265*\255H\026\236\026\234\026\236\026\227m!ZiJiZaZ\214\245FV\272ZB))\r%4\322\023\212JBi\204\324.\330\025Y\217\314j&5^CUe\252\356*\006\250\034UwZ\254\342\253H*\254\202\253=V\220\325v5\023\032\214\232a\006\243\"\215\246\234\001\251PqS\'5 \03052\234T\341\306\332\202W\035\252\014\222i\352*\324\\\325\310\260\rhE \013R\006\313U\270\307\313\315)\340\324\261\221\234T\255\036W4\210\2705:\216j\314b\255\"\324\352\265*\255H\026\244\013O\013O\tK\266\220\245!JiJaJ\215\222\243)[\324SOZCHzSi\r!\246\032a5\004\207\212\257!\371\252\0265\003\232\201\372Uw\250\030T,*\027\025^E\342\252\310\265RAUd\025U\326\240u\250Yy\246\025\246\225\244\t\223R\210p:R\371B\227`\350*E\\S\366\342\235\217\226\243.@\246\362\306\234\027\024\341\326\256@\274U\214\034\361V\241V5r4\307Z\262\033\003\002\236\212X\325\250\3419\253\033>LS6f\245D\253\010\274\325\250\305XE\251\225j@\265\"\245H\022\234\026\227e\033i\245)\245)\205)\214\265\033%l\342\220\365\246\232i\351IM\244=i\206\232\324\306\252\362Ui{TMP\265B\365\003t\250XT\rQ5@\342\252\310\265ZE\252\262\'5]\2435\023\302qP<-\351L\021\036\342\221\2414\337,\251\247\200qJ\026\224/5*\2558\246i|\274\361I\344R\030\202\324m\201NE\311\253\260\251\025q#\006\256\304\200\n\234\017J\231\"-W!\213\030\310\253\212\203\024\241y\247\375\237\214\212z\305\212xL\032\261\032\325\244J\235R\244T\251U)\341)\333)vRl\244\331HR\230R\243d\250\312V\241\024\334SH\246\322\021M=i\247\2554\323\032\243j\201\352\274\203\"\240j\211\252\027\250Z\241j\205\205D\302\240\220a\261U\335r*\273!\317JF\200\025\346\242hT\014\001P\274\031\355PI\t\003\245Wd\301\246\355\366\2441\322l\245\tJ\023\232\221V\244\013N\000R7\025^F\250\261\226\2531 \253H@\253\021\266M\\\214\234U\250\206H\255\030Pb\254*\363\305N\252H\245\010sV\241\036\264\366L\014\342\232\027&\254F\225i\022\246T\251U*@\265 JpJ]\224\233)6R\024\246\024\250\331*2\225|\214\322\021\212a\024\3029\244\"\233M\"\232zTl*6\250\034d\032\205\207\312j\006\034T,*&\025\013\n\205\226\242e\250XUy*0\205\207JC\0368\305F\311M\362\263L1\214\324\022\240\305Rh\362i\2060)\204Rl\247\004\245\tO\tN\333@^i\031x\252\322G\3151S\232\263\032\032\262\2203U\310\255\310\251\266\355\253V\300\223Z\221.\000\253H\271\253\010\265(\2175*\307\212~\323\212EL\265YD\305YE\251\325*EZ\220-<-<%\033(\331HR\220\2450\245F\311Q\262U\254sMaM\"\232E4\212f9\246\221L\"\232EF\302\241aU\334u\025\013\016*&\025\013\n\215\226\242e\342\240qP\260\250|\262\355\212\231cU^\225^A\223Q\371t\2458\250$\\\032\255(\310\252\254\274\324.\r0!\245\331K\266\234\022\237\262\224&i\306>:T.\0105\023.i\026\"Z\256E\017\265]\215@\034\212\260\244c\212\031rj\325\252\340\326\244``U\244P*d\0315i\023\212\220\n\230E\2713B\305\216\265*\246MN\211\212\230-J\253R*T\241)\301(\333F\312M\224\322\264\322\224\306J\211\222\244\"\220\364\246\032B)\270\246\221\3154\212a\024\302*6\250Z\240q\315@\302\242aQ0\250\330T-P\260\250\231sBFG4\327\004\234\n\217\313\311\240\246\005F\302\253\310*\264\211U\3319\250\212Rm\244\331\355N\021\323\266S\3262{T\253\007\265<\3041U\244\207\236\225\030\207\236\2252@\007j\235c\003\265J\"8\251\021\016jm\207\035*X\201\006\257\304\330\025ad\346\256C\223\212\275\022\2265a`=qV#\213\003\004PS\234b\225W\0252\212\225\0275:\245H\026\244\013N\333\355K\262\223e\033)\245)\nTl\225\023%\004qL\"\230E\024\332a\024\204SO\025\021\250\332\241aP\270\250\\TL*&\025\023\n\205\205D\313H\221nz\225\243\003 Ur\234\322m\2468\250Yj\007J\201\326\240d\250\314t\337+\332\227\312\247\010\371\251\226\337=\252d\203\007\245I\345\200*6^i\276V{S\01484\345\213\332\245HI=*\342[dt\251\222\320\223\322\246\373\031\364\245[2;T\202\022;T\261Bw\016+N\010\016\005i[B3\315h\010\227oJ_+\322\221\255\311\\\212\211\243\301\351OU\251\321juZ\221R\244\t\3058!=i\333}\2516Rl\244)M+Le\250\231*\034qM\"\230E6\232i\264\323M&\230j6\025\023\n\205\207\025\013\n\211\205D\302\242aP\262\323\031i\321.)\354\244\324-\035FV\242q\212\204\324N*\022\231\250\332:\217e!JQ\021=\252X\340\346\256\307\010\003\245\014\200\032c\n\204\2474\365N)\032<\232\226(3\332\255$\000v\253\221D1\322\256G\010\035\252u\205Oj\224Z\202:R}\217\332\245\216\317\236\225r86\216\225:\r\247\212\262\233\215N\243\0254k\220j\t#\347\212ENjeJ\235R\245T\247\205\247\005\245\333F\312M\224\205i\205j2\264\306Z\251\212i\024\322)\204SH\246\032i\250\233\351M\243\025\033\200\rB\302\241e\250\231j&Z\211\226\242e\250\233\212\2265\371A\365\251vqQ\272UvNj\027J\213\313\250\236:\217\313\244h\275\252?+\236\224\341\007=*U\200b\245X\200\355R\005\300\246:\324L*=\2715:E\232\231m\362zT\361\301\216\325e-\363\332\254G\001\035\252q\031\307J\232(\3115z8\370\351S\010A=*\304v\343\322\234\360\340p)b\267,\335*\362Z\355^EF\351\206\305M\022\374\265\033\246\r5W\232\231\022\254*\324\241)\301)v\322\355\243m\005i\245i\205i\205j6Z\240E7\024\204S\010\246\021L\"\232V\230\313L\305!\025\033\016*&\025\033\n\214\255F\311\362\346\241e\250\235}\005B`bjq\031\030\247\201Mu\342\2532\363Q:\361P\225\346\220\307\232i\217\024\206:o\225\317Jx\213\002\224&)\341i\016*7\250H\311\245D\346\256E\037\265\\\216\034\366\251\322\016zU\310\240\343\245N \366\247\213\177j\2328\000\355V\226>*x\342\315[H\260:S\274\235\307\245Z\202\330\001\234T\262(\013\212\244\351\226\251\025p\224\205i\2339\251Q*\302\245J\027\212pZ]\264\273h\333HV\232V\232V\243+Q\225\254\322(\3054\212a\024\302)\204Sq\355H\313Q\020sI\216*2*&\025\031ZaJa\217vqP\262SDY8\250\335v\266*`\277&M3o4:\374\265]\223\232a\2174\323\0057\313\305F\353\212\210\212r\250\247\034b\231\212\017\025\021&\214f\234#\315J\220\363\322\255\305\017N*\354q{U\310\240\317j\273\035\277\035*u\203\332\244\020q\322\225a\301\251\322/j\2368\361VU8\251#\217\236\225qW\013QH\271\252\355\035.\314\n\002Q\345\324\212\230\251UjP\264\355\264\273iv\321\266\220\2554\2550\2550\255FV\262qF)\010\246\021L\"\243\"\223\006\220\216*\"9\244#\212a\034\324L\275j2)\244S\031j2\264\335\274\323\014E\244\251\031p\270\246\005\346\224\257\025\003\245F\027\236\224\255\214T\014y\250^\242\3074\034\201H\001cR\210\270\246:\324$`\323\220d\325\250\342\317j\265\034\036\325i!\307j\263\034^\325z\010}\253B8\206:T\342/jp\217\332\236\"\030\351OX\371\251\204u\"%XH\275\252P\274SYj=\224\323\035\036].\316)\3018\251\025x\251\002\323\266\322\355\245\333K\266\232V\232V\232V\243e\250\331k\037\024\204SH\246\221M\"\230V\230E!\025\033\016i1L+Le\250\212\323H\244+L\333M+\315*\'\314N)\254\23757g4\2458\250Y9\250\33103Ud$\032\211\272T\014y\244\035iH\251#\0035+\260\013U]\362j2\244\232\236\030\211=+B(\270\351W#AV\022<\232\271\014#\214\212\275\024C\216*\342GV\222!\216\225\034\253\266\232\204\032\231W\232\235W\212\2268\376j\266\261\374\264\214\224\322\224\233)\241)\002sN\021\363\212_.\225W\025*\250\305.\332v\332]\264m\244+M+L+Q\262\324l\265\211\216i1I\212n)\010\246\025\250\310\244\3054\2554\2554\212\214\255FV\220\245!Jn\312n\316jA\036\027\2450\307I\345\320c\343\245W\2210j\007\373\265RE\346\253\270\250\212\346\223n)v\223NDjq\211\332\220[7qR-\267\265Y\216\034v\253q\307S\204\"\247\204sZ\021\216*\324Ur1V\025\260*)\262\325\002\202\032\256\3042\005YD\253\021\2475eG\0242\212\214\255\005i\212\275iU2jU\213&\245\020g\2651\241\332i\241i\301{\032xZ]\224m\244+M+L+Q\262\324L\265\204G4\204Rb\220\212i\024\322\264\302\264\322\264\205i\245i\205i\205i\2739\243g4\206:iJn\316je\217*8\246\264~\324\303\035&\312\215\341\310\315Q\2322\265M\305@\353\315F\313\201Qc-V\0220EN\221\214\325\225\211q\322\203\032\216\324\004\036\224\355\270\251b<\325\325\2140\247\254EM[\210g\025z$\253\013\201R\001O\330\010\250\2360\017\025$\\\032\270\207\212\235\030f\254\003\305\031\311\245\013\232d\230\007\003\255\"\247\024\364R\rYD\350juN8\244x\301\031\252\357\036\326\351H\027\'\024\340\0108\306i\341r3K\266\220\2550\255F\313Q\262\324L\265\201\267\2326\322\025\246\342\223m!ZiZiOJiJiZiZ\214\255\033)Dt\246>)\236_4\357\'\'\245J\"\343\030\246\264U\033G\201Ql\313S\231\000J\315\271\003&\263\344Z\254\303\232M\231\024\337(\206\351R\250\300\251QI5aT\342\227a4\340\270\245\333\232T\\5i[\256@\253~W\035*H\342 \364\253j0)\3435*\323\306iJ\023@\\\032\231I\305L\204\346\255\253|\264`\223R*\220\264\320\231l\232\225S\212~\312\231\007\0252\212~\316*9#\310\250<\262\r9W\007\353Rl\347\353K\262\232V\243+Q\225\250\331j&Z\347\361I\212B)1F\332n\332\n\323J\323J\323J\323\n\322l\245\tN\021\322\371t\323\025L\221a9\035i\302:kDOj\211\341\366\246yX\250g\000-d\3162\306\251\310\265\001\217&\234\261\322\262qQ\343\006\246L\n\260\244S\270\246\023\223OPML\221\222G\025\245m\021\002\257\254|T\252\200T\201i\301y\251R<\325\210\341\317j{F\024Tb<\232\225!>\225am\217\245L\260\221\332\245Xy\351S,9RMDS\006\236\242\244\331OE\251\321j]\237-4\245G\345rx\246\224\305I\260l\006\202\224\306Z\214\255F\313Q2\324,\265\317\201\232B\264\205i1F(\333HE&\332iZaZM\224l\247\010\371\247\004\247yt\253\026Z\246\020\322\3714\276P\250\244@*\234\244\016\225Br[5FH\3175Y\342>\224\317+\332\232W\006\220\256EG\263\232\221b5\"\304jC\031\3059!$\363V\222\337\212\261\034 \032\273\032\200*\302\324\203\232\225W5*\307\315Y\216>*\302\256\005#\246i\360\301\232\264\260\200zU\270\241\005zS\314 \036\224\205\000\246\223\306\321L\330M8&)\340S\224T\361\212\230\201\214SvR\204\310\243\312\366\2451b/\306\230V\230V\243e\250\231j\026Z\211\205s\252\275iv\323J\323\033\212i4d\322a\275)\t\"\2200&\234\0274\276]8%8G\3058GN\021\324\251\027\031\305L\261q\322\231 \333U\332J\255#\223U]KT\r\0175\023C\355U\236\036zTf/Z\257,X5\032\246E\036Q\317J\221W\035EL\212\t\351S\210\301\024\005\njtaS\'&\247U52\n\235\0275j4\342\246U\251\320T\200T\201s\332\247\215j\312\246j\334I\307JVZ\215\227\212\257\267.H\251\024qK\266\225V\237\264\324\211\305H94\375\274S\221j@\234S\214\177.*\273\246\030\212\214\255F\313P\262\324L*\026Z\347\302\361AZ\215\2054D\315\332\245Kbz\212\220[\250\2450\247LTF\321I\3105Zks\033dR\'\241\253\010\234T\236^{R\210\215<GN\021sS\254T\362\201ES\230d\325VJ\257(\010\t\252\236o4\241\201\353C(\"\253\274c4\303\026{T\023A\362\236*\252\246\033\025a`\005zP`\364\024,$\036\225(R\005!Bi\311\031\315Z\2123\351V\2250*U^j\314kV\221x\251\225*u\216\245\021\324\211\035XH\252\302G\315[\2158\241\327\232\211\327\212\256\024\006\247m\346\227\024\345\024\360\264\273jH\327-S\025\002\225EM\032\2268\251\0310*\t\020\036{\325vZ\211\226\241e\250\231j\026\025\317Q\214\322\254\034\345\252p\021F\000\245\332\314x\034R\025\n\271&\243$Sr\000\353H@\220`\324F\327\234\212t@\347\004r*\312\245H\251K\345\343\245\"\237\336\343\035*\322/\025\034\302\251\272\022j\tp\242\263\346\313f\251\224 \321\234R\027\"\241y\r\021\315\316*\313F$L\372\325Co\206\351R\004 R\252\344\324\342\000GJcC\216\324,\\\364\251\343\204zU\225\210\001N\331\315J\221f\254\307\025[H\270\251\0250j\312&EL\022\235\214T\321\325\204\034\325\310\300\333L\221y\250\231~^j\271O\232\235\266\227m9E<\nq\034S\342\031\351O\307<\323\200\251cm\255R\261\315F\302\253\272\374\330\250XT,\265\013\n\205\205s\313\037\343S\307\037\255H\261g\236\324\335\2007L\322\273\235\270\252\356\334sP\263\034\322\000Z\246\217\n*P\271\346\232B\357\351\310\251\220df\244\000S\261\305G\n\346s\305]U\371j\031W5ZE\n\244\326l\331,j\273&j\t\022\253\262Tl\274T.\231\250\260T\325\225\224\225\305:3\275\360j\317\223\225\246\010\366\265\\\211AZy\200\036\324\013oj\220A\216\325 \212\225a\251\322<U\210\323\236\225m#\371i\010\301\251\342 \212\233\214Sr7U\250\224\021R}\323S\305\'\025)\301\246>1P\0203@Z\\R\355\366\245\031\247{T\361&\324\244?z\226\214\343\232\23662\014c\245\014y\250\235rs\212\205\327\232\205\226\241qP0\254D\217\332\246\330\000\245\347mFN:T26j\273\234\232\217\034\324\212\006i\314q\315<I\362\214S\224f\247E\251\202\322\225\371j;~%\"\256\250\342\241\230\020\t\254\351\\\223U\235sP\262\324.\225\003%D\351P\262Te3@LS\327\206\315hBw-\022\2469\3056\027;\260kR\024\014\271\251\274\260\005\036Vz\np\200\372S\304\007\322\245X*UUS\315L$P\265ZY\006x\245\212S\232\263\346\344S7\374\325n)HZ\223~O5b>\231\2517\340Rn;j>\364\365\034S\200\346\234\026\224(\247\205\251\024\361Mj^\324\224\344fS\305XD\3343\353H\361\372T/\037\025ZE\252\356*\026\025\226\020\n\033\000Tl\334\323\010\030\252\362\036qP56\236\240\322\271\302\323P\374\265j!\221VPT\230\312\323\271\306;RE\030\363\267U\203\362\256j\031\016\344>\265FH\216s\212\210\3061Q<u\013\245B\310*\007J\256\313\3157e\033(\331V-\316\033\025y\243\336\225_\311*\371\305[\206]\243\0258\233&\254\302\340\365\253>d`Q\346\307CN\270\342\253<\304\236)\201\234\236\264\361\0337Z\231\"\305N\0234\361\016MN\252\000\305<\001\236\265*6:T\301\262)\254\307\245\000T\213\322\234)\340S\361K\212\\Q\212A\311\305(\251\000\253\020\237\227\024\366\002\240q\201T\344\034\232\256\342\240qYg\326\243cP\261\250\331\316:\324\005\263Q\223\223OU\024\360\274S$\031\024@\001\340\325\304]\274\032\235*A\332\226\234\230\r\223Ng\312\221Q\036\225\023\255B\351P\262\324\016\206\241e\346\243e\250\032>j2\224\233h\333NQ\264\361W\240\223\200\rX\362\325\2057\311\247,52\251\003\212\033\177\255 \017\357O\010\306\236\261z\323\200Pi\301\261N\023\021R\307?8\"\247-\221\225\245\334M=sS\2408\251E?niB\323\200\251\024S\302\323\200\247\001K\217j6\322\025\346\225E=\006\346\305I\215\217\305H\033\"\242\223\221T\344\250\036\240z\310v\250]\207\255@\357P\226\3150\323@\346\245^\006i\301\201\246\311\323\002\240G)6\ri!\014\231\315H\254i\341\263N\3158\036)\001\000\340\367\251\004G\251\246I\036:Uv\025\023-B\313P\262\373T,*6Z\214\2557m&\332]\264\36485a%5/\232@\353J\'\247\211\351\353.i\342Oj\220?\035(\363N*=\304\232]\324\240\346\245QR\2432\237j\262\244\036\2252\n\260\202\245U\251\000\245\002\234\026\236\242\236\005<\nxZ6\321M\"\227\034P\207k\323\231\262\331\240H\0055\334Ui\030Uv\250\230V\023\2775\0035@\3074\322qM\243\275H:R\343\034\323O&\253\316\010\031\025%\265\321\306\322j\354r\203S\206\356i\300\203O\024\216\017\336\035E>+\257\340\224s\353R;\'\250\252\304d\323\035y\250Yj\026Z\205\226\242+L+L#\024\230\315\033h\003\232x\315<\014\365\247\005\346\234\026\244Q\212\225A\305H\277v\224\016(\333\315;fi\301*EZ\225W\"\244U \361Vc\351VR\247Q\305H\0058-<-<%8%=V\236\026\235\260R\024\024\322\224\230\342\233\201\236ha\305D\331\025\021j\215\216j6\250\315s,\365\0335GHM%&i\301\251\341\205!<\324\023\034\203U\341\037\275\255$\371qVQ\263R\017j\220\034S\263Q\355\033\263O\330\016\017B)\301N3Mt\004\006\025\023%B\311\355P:\373TL\276\325\031Z\215\226\233\266\214Q\212x\024\365\024\360\rH\250i\341)\341jE\025(A\212B\230\024\241i\341i\341jU\025\"\255J\203\025a*\302T\252*P)\340T\201i\301)\330\305L\";s\212B\234\321\267\212a\024\322\264\302\264\326\025\023T.8\250\215F\324\303\\\2514\302i\224\204\323K\201L2R\253\322\357\245\017\223L\220\361P!\333%]Y\tQVb~*un)\340\361N\rN\034\323\207Jz\212v\334\323\031=\252\026OJ\201\320\372T,\225\013-FV\233\266\223m\030\247\001O\002\236\243\232\260\200T\233(\333\216\364\345\025\"\212x\\\366\243e8-H\026\236\242\245U\251Ujd\025:\212\225\005N\242\244QR\252\324\252\224\2730\300\342\237\271\215!\004v\243\024\3229\340S\n\323J\323\031j\026Z\201\305BEF\325\033W$M4\232Bp*\007\224\016\225\t\2234\322\364\202LS\274\321\353J\262\363\326\234_\"\243|\343\212[I7K\261\217\322\265Tm\025\"\277cR\203OZ\220S\326\244\024\361H\325Ji\325\033\024\315\340\214\220y\244*\032\242t\364\025\tC\232aCM\332iBR\342\200)\353R\253\021R\253f\236)\352*eZ\220-8-(A\332\234\006:\323\302\324\252*@*D\353S(\251\220sV\020T\312\265*\245L\253\212p_\233\245+(+\221MbJ\340\323qHE&)\244Tl\265\023-Wu\250\030T,*3\\\205!\300\025^G\347\002\252\2719\353Q4\235\251\206CI\276\220\261\354i\310\374\363S\253\347\212\224`\255@\312VM\313V\241\273l\205sZ1\374\303\"\246^\005H\255\332\246\025\"\363R->\232\325\223{\362\236\007z\226\333\230\206j\177,\036\224\306\214\342\241h\315Fc\246\224\036\224\233)\n\321\266\227\024\341\305H\265*\232\225qS%J1J:\323\200\247S\200\364\251\026\245Z\221EL\242\246J\235\005Z\215j\302\'\025&\332\224\304\004Y\250\266\361Q\221M\243\006\212i\024\322*&Z\256\353U\335j\006Z\205\2075\310\036\265\034\215\205\252N\374\223U\235\262j#\326\232M3u\033\251\340\324\250\376\265b3\236\364\375\271\355L(T\346\246\216\351\343\030\006\264l\356\322S\206\340\326\232$L3\300\240\371j\247\221\305\n\300\3645(aK\277\212\202i\302\016\274\326l\322\033\211B\257AW!]\250\005N\016)H\343\232c-DS\332\230S\332\230V\220\255&\3326\320\0058\nx\251\024\324\252\3252\265<\032x4\341O\035*A\315<T\313S%N\202\247J\263\031\2531\232\235F\356\22418\301\355Q\236\225\031\353IE&3O\362\211Bj\022*6\250\034T\016*\273\255Wq\\i5Vw\343\025E\337&\242&\230MFZ\230M jpj\225MX\211\271\253\310AZk\340\232a\217540\225;\201\253\3134\201p)\256e+\303\032dW3\3020y\025:jK\234?\025$\232\244\013\031!\3015\234\3273]I\204\004\002z\326\205\265\276\305\347\223V\300\300\245\351\332\224\026\244,\331\351I\237QF\001\351M)\355I\345\322yt\236U/\227I\263\024\270\366\245\000\323\306E8\032\225Z\244^\2652\212\225EH\027\322\236\026\244U\346\245Z\235ML\246\254!\253\010\325:\271\035\r\005\263Q\263S\013sKHi\321\215\315\212\270A\362\260\007j\242\343\004\324L*\027\025]\305@\365]\305p\362\260U&\263\246|\265VcL&\230Ni\206\230i)GZ\225*\304mVR^1\232p\223&\245C\223V\025\206*x\306\357\245M\201\322\232\321\n\255-\250s\322\243\217OR\3315\247\005\262 \030\025gn\321K\364\244\003\232u.)B\217Jp\214g\245;\313\036\224\206!\212o\226\007jM\224\233)\nq\322\232R\223n(\002\234\026\244U\251\320T\310\2652\257\245L\253R\004\315;\313 S\325j@\010\251\026\246F\251\321\352P\324\355\331\2444\303J\0175 \031\024\203(\371\025?\3322\274\365\252\316rMFzTn*\273\212\256\342\253\270\257=\236N*\203\266MDMFM%4\365\246\032LS\200\247\202\005H\215\315J\032\234\244\203VcoZ\260\204n\007\265[\216A\214\n\235XS\211\024\001\232\221\023\275XP\000\342\226\227\031\024\241iqK\266\234\024\323\200\247\201F>\270\244#\330\322m\246\224\245\331Hc\3154\306})6\036\342\224\'\265=R\246E\251\224T\352=\252dZ\235S\326\236\253\371PS\272\322+s\203\326\245\013\334S\205H\246\244V\247\006\346\234\016h4\200\366\251Q\205<\340\366\250\310\346\233M#\212\215\252\027\031\035*\273\n\256\342\274\276Y2j\273\032\214\232a4\224\032i\351H1HM\033\252E5*\265N\246\246Z\235\rXCS\251\251\223\232\235@\333R)\340\np\315<S\300\245\305<\nP\264\360\264\340)\300R\342\224\n6\212k(\354(\010\t\245(\000\244+\3521M+\3528\240 \247\210\352EJ\225\022\247U\365\251\224zT\2038\247n\240\036x\244 \037\255*1\007\006\247\030#\212p\007\245<\nv)Fi\343\221K\030\033\276j1\206\342\237\223\212i4\332CQ\265D\334T\016*\007Z\362Vj\205\232\230M74f\220\232ijn\3523\232\005<\032\221O5b3VR\246\003\270\251Q\210\343\025e2@5a8\02504\365\251E<\nx\024\360)\340S\200\247\001K\212p\024\354RQ\2322)\264\2718\244\335FE\003\320T\2528\251W\334T\243\247Jx\307z~\3527\036\324\241\263N\335J\030w\247\202\017\006\236\244\257CS\243+q\320\324\252)\373i\312\027?0\245\003i8\245\003\212B)3M4\332Bi\246\2435\023\n\205\205x\3435DM4\232n\357zB\324\322\324\205\251\273\275\351A\247\212x\251\026\254F*\302\n\262\225:\255N\240\324\313S\240\251Ui\340T\212*E\031\247\201N\013N\000\212p\247R\340b\222\220\232JL\322n\243\266i3FiA\251\025\210\251RQ\322\245\017\31587\024\241\215;u;4\273\251wS\203\324\210\376\2652\225\"\247W\350\017\347S\251\342\2361\216)@\245\351Hy\025\031\004u\246\344\322u\246\236\264\204Tf\232EF\350\010\257\023cL&\230M4\232i4\334\322QO\002\236\265*\212\225V\254 \251\343Z\262\202\254 \251\320T\312*e\025*\203R(\315H\005=EH\0058\016iizR\320M4\232L\212B\324\205\2513\305\'\030\243\240\240\222\007J\003S\324\346\227$\232\225I\007\223R\006\367\247\006\251\024\323\263Fis\315(4\241\210\251RLT\353/\275L\262\343\277\025:\313\3375*\2704\244\212B\337\225#\020E0\364\244\355Hy\353\371\323H\244\333\336\232G\2751\200\257\014&\232M0\323M4\232i\245\035)\300S\300\251\025jU\025:\n\235\026\254\306\265a\005N\242\246QS \251\224T\252*@*@)\340T\200S\200\243\002\220\323KRn\246\226\244-M\335I\272\215\324\271\245\245\014G\322\221\207p\r9\001\306i\343\030\247\251\035)\343\2558T\212i\331\245\245\031\245\245\006\22784\340\325*\311\305N\222\361\305J$\343 \324\202\\\216iw\322o\243}\031\3474\245\251\245\251\273\361\327\245#\021\216)\205\205xQ4\204\323I\246\023IE8\nx\025\"\212\221V\246E\251\321*\302-XE\251\321jeZ\231V\246QS(\251TT\252*@)\340\014sK\322\234\r\006\230O4\303M\'\232ni\271\2434\231\244\315\0314\241\215<\023\330\323\376ls\315*\000s\221N\343\024\003O\r\315H\rH)\340S\205-\024QJ3N\335NW\"\245Y8\251\004\224\341\'\024\276`\243}/\231K\276\223u4\2654\266)\205\353\303\363IM\246\2321N\002\234\005H\005H\005J\242\246E\253(*t\0252\212\235\005N\202\246QS(\251\225jE\025\"\212\220S\262h\311\244&\232X\322\026\004sM\'\212ni\244\322Q\232i4\231\2434\240\324\212i\373\200\357G9\342\224\003O\035)\364\340j@j@i\300\322\346\2274\352(\244\"\200{S\201\"\224?4\341%;}\'\231\357N\022{\323\267\322y\224\273\363HMF\306\274K4\224\204\322\016\264\352\007Z\221EJ\242\244QR\252\325\204Z\260\213S\242\324\312\2652\255N\202\246QS(\251TT\212*AK\2323Fi3IHqM\"\232A\246\346\220\221A`\005!#\256i(\305(\343\2558\023\332\234:\324\253N\245\024\361\322\235\236)\300\361O\006\236\032\224\032p\351O\035)@\245\333A\025\037z_j1A4\231\305\033\250\017\357N\337H^\220I\315H$\310\244-_\377\331"
-byte_png: "\211PNG\r\n\032\n\000\000\000\rIHDR\000\000\002\000\000\000\002\000\010\000\000\000\000\321\023\213&\000\000\001\355IDATx^\355\334\355\n\2020\024\000P\261\367\177\344$\022\214\270\344Wl\272\217s~\004m\2452k\314\273\355\016C\211\306X\000\000\000\000\000\000\000\000\000\000\000\000-\231b\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000p\3343\026\000\000\000\000\260\255\326L\210\343\373%\303\305g8$\000\000\000\000\000\000\000\000\000\000\000\000\260\2307\006\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\371I\376\005\000\000\000\000\000\000\000|XH\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\007\244\331\000\000h_\301c\276\261\340k\243FS,\000\000\000\000\232\'\036\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\300\255$\316\007\000\000\000\000h\337\030\013\000\000\000\000\000\000\000\000\262\260c\r\000\000\000\000\000\000\000\000\000Hi5\203\322j\005\000\000\000\000\000\000\000\220\234\344B\000\000\000\000\000\000\000\000\211H\230\000\000\000\000\000\000\000\360mm\026u\331\346\276V_\n\333\361S\323\242\000\000\000l\330}l\334\375\000\000\000\000@\023J_Oq=q!\000\000\000\000\000\000\200\266\230\007\006\000\000\000\000\000\000\200\036X!\000\000\000\000\235\210A\000\t\365f\232\241w\361\217\001\000\000\000\000\000\000p3\023\331i\324\336\216\217X\000\000\000\000t\307rw\200\376\350\373\001\0008\240\366%\021\000\000\300\037<\010\000\000\000\000$#\324\002\000\000\000\000P\026q[\000\000\310\340\352\\FW\237\217cN\337\227\323_\000j!\000C&;?\255\235j\000\000~2\212\002\000\240\036&\227\000\212\223\271k\316|x\000\240\026qP\020\337\003\220\234\256\026\000\000\000\240[\266\030\364\313\275\007\000\000\000\000\000\000\000\000\000\000\212\363\002\273\027\037\377]\026V#\000\000\000\000IEND\256B`\202"
+byte_jpeg: "\377\330\377\340\000\020JFIF\000\001\002\000\000\001\000\001\000\000\377\333\000C\000\003\002\002\003\002\002\003\003\003\003\004\004\003\004\005\010\005\005\005\005\005\n\007\010\006\010\014\013\r\014\014\013\014\013\r\017\023\020\r\016\022\016\013\014\021\027\021\022\024\024\025\026\025\r\020\030\031\027\025\031\023\025\025\025\377\300\000\013\010\002\000\002\000\001\001\021\000\377\304\000\037\000\000\001\005\001\001\001\001\001\001\000\000\000\000\000\000\000\000\001\002\003\004\005\006\007\010\t\n\013\377\304\000\265\020\000\002\001\003\003\002\004\003\005\005\004\004\000\000\001}\001\002\003\000\004\021\005\022!1A\006\023Qa\007\"q\0242\201\221\241\010#B\261\301\025R\321\360$3br\202\t\n\026\027\030\031\032%&\'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz\203\204\205\206\207\210\211\212\222\223\224\225\226\227\230\231\232\242\243\244\245\246\247\250\251\252\262\263\264\265\266\267\270\271\272\302\303\304\305\306\307\310\311\312\322\323\324\325\326\327\330\331\332\341\342\343\344\345\346\347\350\351\352\361\362\363\364\365\366\367\370\371\372\377\332\000\010\001\001\000\000?\000\214\234\032PiI\244\242\212]\324\340irh\rR+T\252\370\247\357\245\337N\017F\372]\370\244\3632jA(U>\265\021\227\232kKL\363}\350\363iD\264\341-H&\305H\263\373\324\253p}jArGz\177\3338\353@\274>\264\361u\357O\0275\"\334\373\323\205\317\275<\\{\320n)>\322j\304\027\033\272\232\264_+Lf\302\220k\027RCn\341\207CU\322rGZq\2234\306\222\2432\232g\231\223A\223\336\21734\206JC%4\312iU\362j\355\270\3322z\324\205\316i\245\351\014\230\025\004\227A{\324\rz1\326\240{\341\353P=\356\017Zcj\000\n\206MI@\353T\344\324\213\036:U\332)wR\023Fh\315(4\340i(\316\r=Z\244W\247o\245\017N\rN\017HZ\200qHd\2464\224\303%7\314\244\337J$\245\363iD\324\3616)~\320i\302\346\224\\g\2758\\g\275L\222\223S+\232x\220\212Q)\247\211\215/\233\357@\226\246\212\343i\353W\022\347#\255)\237\003\223T\365)\026hq\351Yhx\342\235\346qLi3Q\231*=\374\322\231(\3631Hd\244\363)\013\324\266\374\232\321\214\3601J\344\016\246\253\311:\257z\243s\177\331MR{\222{\324M1\365\250\332S\353P<\334\324/7\035j\264\222\346\253<\333{\327LzP:Rn\243u\033\250\3174\273\250\rK\223FiCS\203S\203\322\206\247\007\247\007\305\033\371\245y\376]\265\021\222\243i)\245\363I\276\232^\223\314\243\314\243\315\305\036u\036u\002ozx\237\336\236\263sW\240\230`f\254\t\206)\014\324y\330\245\022\322\371\264y\264\t\271\251\322\344\203\326\245i\367/\275R\236\354\200A\252\361\313\236i\346N*\007\223\006\230d\246\371\234\321\346R\357\342\230^\236\256(i2x\2536\347\0035k\317\013\365\252\2277\273{\363Y\322\335\227<\232\256\322\222i\205\251\245\2527z\257#\324-%A#\325i\0335\330R\023\332\233E!8\244\334h\335F\352]\324dS\203R\206\245\006\227q\245\337NW\2452`\346\243g\250\332Ja\222\223}4\311M/M2SL\224\206ZC-\'\235\212O?\236\265,nZ\244\022\355=jh\356\361\336\247[\300{\323\276\320\017zp\237\236\265*\3161\326\237\346\212<\317zO3\006\236\262\324\276~\0279\252\223\2711\261\250\340o\224S\336N\325\004\222S<\312B\3704\007\245\337M/@z\004\234\325\224\271\300\250\345\273<\340\325G\220\261\353L4\302i\245\2526z\211\336\253\310\365\0035B\357P\273Wg\272\233I\232BsII\272\215\324\204\321\223K\272\2245.\354\320\032\227u.\3727\322\027\246\263\324M%F^\223\314\3054\311M2SL\264\303%\'\231\232i\222\230\322\323|\341\353R\307w\264u\247\233\254\322}\247\336\225n\260z\324\213xA\353S%\336OZ\260\227\007\326\247\023\323\304\331\357K\346S\326Jt\262\341)\221\276\365a\355Q\206\3321Mi*\'\222\2432Ry\224\241\351w\363@bN)\3314\2314\214\307\035j2\331\344\322\026\246\226\246\226\250\331\252\'z\205\336\240\221\252\006z\205\336\242f\256\332\212i\034\322Q\232m\024\323I\2323F\357zUjR\331\245\317\275(8\372Swd\320\315Q3\324L\364\303&)\236fM#IQ\264\224\303%0\313I\346\361Li\2526\232\2433Q\347\373\322\375\242\234.)\302\177zQ?\275J\227\030=j\344W9\025a&\317z\224MR,\324\361=\023\\|\203\232X\'\001\251\322\266~aP4\225\033=3v{\322\356\2406)\353\223R \003\255=\230\001P\274\236\224\302\336\264\322\324\233\251\271\246\263TL\325\013\275B\315P\310\325\0035B\306\243f\256\352\212i\244\246\322\023\2123M&\233\272\202sM\335J\032\227&\215\306\224\271\30547zFz\205\336\242-Q<\230\240\034\nc=D\322Tm%Fe\2464\270\357Q\264\325\031\232\230f\246\371\336\364y\336\364\t\351\342zp\237\024\365\237\336\254\301s\216\365u.}\352d\270\007\275K\366\221\214\n\004\374\322I>H\024\370\345\251\342\234\262\220{S\036Nx\250\313f\220\032p4\340\325 \220\001\201M\363\010\243\314\315&i7SKR\003\232F8\250\231\252\'j\205\332\241f\250]\252\027j\211\215F\306\273\332)\010\246\232i\242\232\324\326\250\315\033\261M\335\315.\341F\356h-C\032\t\300\250\331\252\026j\215\233\002\242\316Ni\031\352\'z\205\244\250\232Z\211\245\367\250\332J\215\245\250\232Za\226\230f\367\2443P&\247\t\351\342ozQ=8\\\220j\304W\304w\253\221]\206\350j\312O\236\364\3617\275\006_\233\255M\034\276\365<s\205\310\365\246\371\2314\273\363J\030\346\235\272\22474\273\250\316i\303\326\224\234\323I\244\344\320N\005F\315Q3T.\325\023\032\211\232\241sP\261\250\330\324Lk\320@\315\007\255%4\214\032i\353IMji\024\306\246\2656\212i<\322\251\311\240\234\232k5F\315Q1\315E#v\246\023\201\212\215\336\241g\250]\352\006z\205\244\250\332\\T--F\322\324M-0\313M2\321\347c\275(\237\336\234\'\243\317\367\245\023\373\323\326z\263\025\311\007\255]\206\363\324\324\306\357\003 \323\222\343y\316jt\233\336\256[I\2703\036\302\215\374\324\210\371\247\207\247n\311\245V\305.sO^\234\323\263HZ\220s\364\245\'\322\230\315Q3TL\325\023\032\211\332\241cQ1\250\230\324lj&5\350T\354R\021\212i\031\246\322\021\212cR\036\225\031\024\3064\334\342\223<\3227\024!\3004\320s\223McQ\261\250\231\261Q\023\316i\214\325\013\265B\355\212\256\357P\273\324\017%@\362\324-%D\362\324FZa\226\232e\246\231\250\363\251D\324\276q\365\245\023T\2135L\223f\254G1\025a$\315Z\205\252\3325Z\206]\203o\2575(|\324\212qO\r\232z\234S\267f\244A\353O\315!jN\264\354\342\232Z\243f\250\331\252&5\023\032\211\315D\324\306\353Q5B\306\242j\364JU4\270\244#\024\3223HF)\204SH\301\2460\305Dz\324f\220\232k\036)G\335\307\255\007\201\212\215\215D\355P\263f\230\306\241w\250]\252\007z\256\357U\335\352\t$\252\357%B\362T,\365\031zazcIM\363)<\312O6\224KN\022\324\211%O\033\325\230\336\255F\365v\007\253\26169=\005$\022\031%f\317\025uMJ\0335*\232p9\342\246\214c\232\2234\026\246\347\326\227u\033\251\245\251\204\324lj&5\033\032\211\216i\215Q5F\325\013w\250\232\275\026\225i\324R\021M\"\232E0\212\215\205B\302\243<f\233Q\271\355R(\357C\360*\0278\250\034\347\212\214\234TN\330\250\035\252\t\036\253\310\365^G\252\362IU\244z\201\236\241g\250\331\252&\177Jazc=3}4\275\001\351CS\225\252dj\261\033U\230\216j\324f\255\306\370\306O\0258\221\345\033W\205\356j\344\n#P\005YV\251\220\323\303f\246V\002\244\022R\357\2442Q\276\215\324\273\251\t\246\223Q\261\250\330\324d\324li\215\326\243c\305D\375\3526\025\023W\243m\245\245\003\024\244f\220\216))\244sLe\250\230TN\265\013\na\342\243\333\271\305M\214S\034\324\016j\273\276*&z\201\336\241w\252\356\365]\332\253\273\325gz\256\355P\273f\242c\212\211\332\242f\250\331\3522\364\322\324\233\3517R\206\031\251\025\252x\3037AV\342\217\034\232\267\030\342\254\306\265j ;\212\266\214\000\251U\352t8\251C\323\326J\220IO\022Q\346\373\322\207\245\017N\rN\335\357F}\351\244\346\230M0\232\215\272SZ\243n\265\033\n\215\205F\302\243a\326\275\026\224\014R\321E\030\246\342\232\302\243aP\270\250XTL1MA\203\232{5B\355U\344j\250\355\223Q;\324\016\365\003\311U\336J\202I*\264\217U\335\352\007z\211\236\241g\250\231\352&\222\242/M-M-I\223J9\357R*\203V#\n*tp*\304r\n\261\034\225f9*\312IS,\225<n\005I\347\001\336\234&\315H&\251\026Zw\233NW\247\207\315=Z\244\rN\335K\232B\324\302i\r0\363L\"\230E1\205F\302\242aQ\265z5\024\243\255.(#4m\244\3051\2051\205B\313Q2\324.\264\3220~\225\0335@\355U\246~*\253\266*\007z\256\362Uy$\252\357%Wy*\274\222Uy%\250\036Z\201\346\250ZZ\214\313Q\264\264\303%4\311I\274R\031\200\240MO[\216jU\233\236\265:KV#\222\254\307%Y\216Z\260\263\342\245I\261\324\324\242\347\322\236\263{\324\2135J\262\324\202Z\221d\251U\352Uj\221Z\244\rN\rN\335HNh\305&)\010\246\025\246\221Q\260\250\330TL*&\025\350\373h\333KE\024\021E4\216j6\025\033-B\302\242e\346\240s\326\241sU\344j\247#e\217\265W\221\352\253\275V\222LUg\222\253\274\225]\345\252\322KU^_z\201\345\315@\362\324M5F\322\324fj\214\315M7 w\250\315\326\343\305 \232\236\262g\275H\257\212\235$\346\254F\365a\036\247Ijt\23352\315\212\220O\357R,\325*MS$\2652\313R\243\324\350\365:=L\255R\253T\212i\340\323\201\3158\014\323\200\243m!Zk\naZ\215\205D\302\242e\250\331k\321h\245\333K\214Q\212\010\315\030\342\233\326\243aQ\260\250\230T2\034f\2521\342\240s\305V\225\260\rSv\353Uez\251#\325Y\036\253\273\325i\036\252\311&\005T\222Nj\264\222\346\240y*\273I\315F\322T/-B\323TR\\m\025X\314X\346\245\216N\234qRy\200\232z\311\216\36527=jt\177z\2369\006z\324\302\340/J\221&\367\253\t!\306E;\3179\300\251\004\204T\2119&\247[\212\235%\3435\"\316sV\343\223\"\254#\325\204z\260\215S\241\251W\265H\265\"\255<-<-.\332\n\323\n\323\031j6Z\211\226\243e\250\231k\320\200\315(\245\242\212)\t\3056\232\302\243aQ\260\252\227\007\031\025U\317\025^C\305S\230\361\212\253)\300\252r\265R\225\352\254\257U\244j\256\357\305U\225\270\252R\275Vy1\232\254\362\324\r%D\362\324/%W\222j\211\2335\036\357zz9\351S!52sS\251\3058IR+\223\322\246B@\311\2530\260<\223R\233\214\016\264\370\347\035j\302\316\030`\324\201zm\251\023\336\255D\302\245\3075<O\322\255\306j\324f\254\245XJ\235\005J\242\246U\247\205\247\201N\333HV\232R\230R\230\311Q2Tl\225\023%w\324QE\024\207\2456\220\232i4\306\250\334\325\033\206\313\325i:Ui\032\251\316\334\212\253+qTfj\247+U9Z\253\310\325]\337\212\251+\3435JW\252\222\265V\221\352\273IP\263\324L\365\003\234\324{\371\346\214\344\325\210\227\003\232\220u\342\245N\225<hZ\245\362\202s\212O\264m8\305H%/O\022\025\243\315-\305X\204\026\305\\\211\017\025~(\211\0258A\214\032r\305\351R\205aRFpj\344\\\325\310j\344b\254\242\324\350\2652\255J\253R\005\247\205\247\355\243e!JaJc%F\311Q2TL\225\333\342\212(\244\316)\254i\t\342\233\232i9\2461\250\234\325\031O\314j\274\206\252\312j\225\301\252r\267\025RZ\251/J\247-U\220\325YZ\252J\325JS\232\253+UY\032\253\271\346\242f\250\235\252\027jfsNP\001\006\254\306\300\212\221P\325\230\200\003\236\265j\020*i\023r\361T\332\022\0335\"\260QM2n5,k\232\275l\274\212\326\266\20788\253\312\233E<&i\352\2305e#\0140j6\204\251\2530\257\025j1\212\273\r[\214U\204Z\235V\245T\251\025j@\224\360\224\357.\220\2450\2451\243\250\331*&\216\242d\256\306\220\212JF\351M\246\223\232BqM\246\261\2461\250%l\n\245!\371\215@\346\252\312z\325)\352\244\265VAUeZ\251*\325YW\025JaT\346\025JZ\247)\252\256\325\003\265B\306\242`j&SI\260\323\300\305O\030\3435b>je]\265b6\305YY\001Z\202y\006*\241r\306\244A\212\267\0078\255\030\006\010\255ky\000Z\230I\270\361W`_\227\232{\014T\261\020MN\360\356\\\322D\205N;U\224Z\271\n\325\330\226\255F\225:%J\251R\252T\253\035<GN\362\351\014t\323\0351\243\250\314u\023GQ4u\324\342\222\232z\32256\231H\324\332a<Tlj\264\315\301\252\223\034\021U\335\263U\3445R^sUd\351U\244\025ZAU\344Z\253*U\031\222\250\314\265FU\252R\255U\221*\273\245FS4\302\224\202-\306\245[n9\247\013qN\021`b\245D\305K\263\034\323\200\302\323\014\244qQ\026/OT\305<\n\275j\225s\004c\025r\3301\305h\303\031\3175u[h\247\240.j\3446\3479\305]\021e1Q\371u4Q\325\230\223\232\275\nU\270\322\254\"T\313\035L\261\324\253\035<GK\345\322\030\351\014t\306\216\243h\352&\216\242h\353\242\3054\214SZ\232zSi\224\215L4\306\250\230\325Y\272\032\2519\340Uv\250\036\253\311Ud\025^AU\234T\016*\264\242\251N\230\317\255R\2313T\246\213\006\252<$\324\022[\222:Ui-\330v\250\204\014{SZ\335\275)\004%y\247\214\221\3158-(Njh\343\315H\321\347\245\036Q\"\232ms\332\217\263\205\250\330c\212X\3275\243l\207\212\277\034[\253F\332 \242\255\252\342\247\216\022\325~\332\333\030\342\264\243\204\001\322\235\263\232x\264\317\"\237\035\276;T\313\026\rZ\205*\354Q\325\224\216\246X\352d\216\245X\351\342:_.\223\313\2441\323Lu\033GQ4u\023G[dS\010\246\221L\246\221L#\024\326\2460\250\336\242z\255/J\2530\310\252\317\322\253\275A\'J\254\342\253\310*\273\212\202A\332\253\3146\232\251*\344U7L\236\224\215i\275sU\336\325@\367\252\362[f\253\313j@\252\217\026\r4\246{SL9\246\371x\247\010\351DU2GR\204\247\005\002\225\206\005U\231\352\261\033\232\255\333\307\322\257G\205\253p\276j\374-\300\253\320\r\304V\255\264#\025q#\305Z\215\t\024\276Y\315\\\266^pzT\315\020\031\342\230\023&\255A\025^\212:\260\221\324\351\035J\261\324\253\035<GK\345\322\030\351\014t\323\0351\243\250^:\211\243\255B3M#\024\306\025\031\034\322\021L\2460\246\032\215\305B\365^A\234\325g\037)\252\316\274Uw\025\003\212\256\353U\335j\007Z\201\305T\236\240\010[\2654\301\267\250\250\336:g\221\236\325\033@=*\275\304 \n\315\222\034\267J\215\241\305FV\233\345\346\234#\247\010\352E\216\237\345\322\0049\245h\362*\224\361sQ\244|\325\270P\325\270\255\331\361W\355\354\310\253a6U\2730K\n\334\267R\024U\330\2235n$\251\204;\252x\341\305I\260\343\245\"E\226\351W\"\213\025n$\253I\035L\261\324\253\035J\261\323\304t\276^h\362\351\246:i\216\232\321\324-\035B\361\325\354sMa\232\214\212iZc-0\2574\302*2)\214\265\023\255Wu\346\252\3100MVa\305@\353P:\324.\265\003\245W\220b\253H*\263E\3466*x\340T^EW\235r\325\017\225\232_+\002\253J\270\252\223\216*\213\2475^U\250Dd\323\374\254R\371t\345\216\244\021\323\204y\247\030p*\t\001Z\201\327u5 %\272U\353{~\234V\234\021\252\343\212\270\230\307\024\216\233\252\335\204xa[\260  U\330\220\001Vc\\\232\271\024|T\301EN\226\373\322\204\266\301\351V\026*\263\024x\253*\225*%N\221\324\253\035<GK\345\322yt\206:C\0351\243\250\236:\205\343\251\231{\323OJa\031\246\221L\"\230\302\230Fi\214\265\023\n\215\305W\220u\252\262\2575]\305Wu\250]j\027\025\003\214Ui\005@\353\232H\3419\315$\240\364\025\017\222X\320a\300\351Q2\342\252\314\271\252r\307U\036:\201\242\246\371x\246\354\311\251\026\032p\213\025\"\303\232\225-\252Sm\305T\236\327&\241\026\307=*h\255=\252\334p\201S\210MI\024g5g\312\342\247\267\005Z\265m\344\300\025m&\344U\373c\270V\214*[\002\256%\251=\252\3240m\035)Z,\034b\225#\333V\021jx\3235e#\251\225*UJ~\312Q\035!\216\223\313\2441\323\014u\033GP<t\025\342\243aL#\232JmFFi\245i\244`\324\rQ8\250$\025ZE\252\362\n\201\305B\342\240\220Uw\025\003\2451!\336\370\253\r\010Q\212\250\321sI\263\025\034\213U\335*\264\221\325ic\252\317\025@\320\346\233\344P \247\254\\\324\351h[\265X\216\323\007\245M\344`Tn\224\303o\277\265F\326\330\355NHjh\355\311=*\3746y\035*\304zy\'\245X\376\315>\224\253\247\021\332\246[b\275\252xm\211n\225\263ijv\212\327\262\265\371\205l%\272\205\024\242\001\351H\326\204\256@\250Z\r\264\364J\265\032U\224J\231#\311\251V:x\214\232w\227G\227M1\322\030\351\215\035F\321\324/\037\265W#\212c\n\214\212i\030\246\036\264\312i\2467z\211\252\'\025\013\212\256\353\326\253\272\324\016\265\013\255A\"\325vJ\211\322\237o\036\0335#\241<\325w\206\241)QJ\270\252\355\326\240\221j\273\307\232\205\342\250\274\252i\213\332\224BOj\232\033R[\245h\301l\000\344S\232 \265\023/\025\003G\315H\221\361\322\221\341\311\351RCk\236\325v+@\017J\320\267\266\030\255\010mW\322\255%\262\2361S\215<2\364\246\377\000f\363\322\245\213M\301\351ZPZl\035*\334K\262\256DKU\225\030\305X\205s\236*\264\320\362p)\253\0175b8\361Vc\212\247H\261R\210\351\302:_.\217.\223\313\244)Q\262TL\225\023%Q \212k\naZ\214\2551\2050\212\215\252\'\250\350\306j)\027\030\252\362-@\351P:T\016\225\004\221\324.\225\003\361SB\231\\\324\336^EE$\\UG\217\232\206X\363U\314U\014\260\324>O=)\257\006{T_g\245\026\2715<v\203\322\247K`;T\353\036\005G\"T\014\265\026\314\232\261\024\031\355S\255\236{U\230m1\332\256GfOj\267\r\251\035\252\332\304EO\014D\265i\303\006W\245N\266\300\366\253P\331\203\216*Y-v\216\005$6\205\333\245i\305a\265A\3052X\366\232\261m\036EE,|\236)\212\234\325\210\343\253Q\307S,t\361\0358%.\312<\272\nS\nS\032:\211\243\250\231+,\214R\021M+Q\262\324l*2)\205j7J\214\245!Z\212E\310\250\035j\027Z\211\222\242x\270&\253\272\324\022\'\265VkfsVV\022\200\n\224-6D\342\251\272sPJ\234Ur\274\322\030\267S\r\276;SL<t\246y\0314\365\267\366\247\254x\251\002Pp*\031*\273)4G\0275~\336\037j\320\212\337=\252\314v\274\364\253\366\366\271\355V\326\323\332\245\026\236\325<6\240\036\225v80*\314Pd\364\253\360\333\340t\251\r\266\352\267ib\006\016*\324\261\204\\\n\316\232<\265I\022ah)\232\210\307\315O\024uj8\352uN)\341)Dt\276].\312B\224\302\224\306J\211\222\242d\254b\264m\246\225\250\331j6Z\215\226\231\267\332\232\313\305B\313\355I\214\212\211\227\232\205\326\241d\250\3313Q\230Kd\n\256\361\021Q\371%\216*9\023\313lT\351\036P\032f\317\232\207O\226\252<|\324M\026\352\214\332g\265\'\221\216\325\034\221\342\240+J\2503R\034\001L\306O\024\215\305B\315I\215\324\253\006jh\355\275\252\375\275\267N+J\013~\234U\370-A\307\025\243\r\237\035*\322Z{T\302\327\332\234\266\330=*\314v\376\325f(0zU\304\217\212\232(\262j\374Q\205Z\216d\316j\233\303K\345`P#\243\311\366\251#\213\025a\022\246T\251\004t\273)Dt\273)\245)\205)\214\225\023%D\311Xei6\322\021Q\260\250\331j&\024\334\032B\274T.\274\323\n\361Le\346\240t\353Q\025\246\225\250\231H\351Q2f\232\023\006\241\222\002\362\n\230\246\325\305F\023\232s&EU\226,TA0i[\030\252\362\021U\344\252\345y\240\360)\000,je\200\343\2452H\361U\334b\2265\311\253\260\301\273\265]\206\323=\252\364V\330\355W!\203\245iZ\333\3628\255h-\370\351V\226\337=\251\302\014v\251\005\276{T\221\303\203\322\254,\025*EV\342\203\275XU\300\246I\036j/\'\232i\207\255\'\223J\"\300\247\254u*\'\0252\245<-.\312v\3126SJSJS\031*&J\205\222\271\362)\010\246\221L#4\306Z\211\226\230V\220\212\211\327\232n\332\215\226\242e\250\2311L+Md\250\366S\014|\322\307\026^\222H\376cQ\230\351L|T\022G\315D\361`f\251\314\304\023U\334\361U\244<\323\027\223O\"\237\n\214\325\207eU\252r\311\223P0,j\305\264\004\232\326\267\203\201\305hC\020\305Z\216\034\325\373{n\231\025\247ol8\255\030\241\351Wb\267\310\250\347\214%6&\007\212\235R\254\242dT\321E\223W\343\207\345\241\242\307ja\216\223\312\246\010\363\232A\037\315N\020\323\274\234\nT\217\025:F\010\247\004\247\004\245\331G\227HR\232R\243d\250\231*\027J\346\312\363HV\232V\232V\232V\243e\250\212\323J\323Y*2\230\355M+Q2\324M\0357\313\2441\324~U4\305\315J\221aI\246\030}\251\276Oz\014<UY\242\301\252\357\323\232\241:rj\254\203\025\003&i\233piH&\237\0325=\241v\246-\233\023\310\251R\310\372U\310-v\342\264!\206\254\254Ej\325\270\371\205j@\006\005_\200t\255\010E[F\300\250n~q\305T@U\253B\001\270U\330\243\253QG\315]\215@\024\256\200\324E)\nb\243U\3114\251\026Z\247X2zT\302\327=\2527\266\330O\2455S\024\365^j@\224\276]/\227M1\323\031*6J\211\322\240u\256d\257\"\220\2557m!ZaZk%F\311L)\212iZiJ\215\223\025\033%3\313\346\223\313\2441dS\014T\323\0275:E\225\244x\275\2523\r7\313\250\245\266\334\017\025\233s\tL\326|\213UdL\232\211\223\002\241+\226\2531C\270U\230\340\000\325\270\355\224\216\224\343n\243\265\"\302)\3731S\301\324V\212B\035i\351\006\323W\355\326\264\255\342\253\261\200*U\025 \217p\250d\204\003R@v\232\321\205\206*\314L3V\324\340Q\273&\224.i\222\341F;\323c\217\214\324\210\2305n8\307\025e\"\343\212$\2040\252\222\301\264\322\004\311\002\234\252Cc\025(L\212<\272C\035F\311Q2TL\225\003\245r\305rh)M+M+HR\232V\231\345\323Lg\265Fc\244)Q\262Te)<\272Q\026i\306\016*?\'\236\224\277f\317j\235-\3601Mx=\252&\207\002\2411d\364\2474@/5\223|\203&\262fLf\251\270\346\233\345\356\024\317\263\363\232\2325\300\251\321I5m\024\342\235\260\232pLu\245\331\221K\032a\253^\311w\001W\305\266{T\320\300A\351W\243R\005J\271\251\322\244V4\343\031jE\217i\253\021\222*\304lA\253\3216V\227\222jTR\0053\313,\3715:G\305I\345b\247\205x\253H\274qO\362\370\250\245\207p\252\246\")\350\270l\232\230G\203\365\2451\323\032:\211\222\242d\250]*\027Z\3456\365\244\333HV\233\266\220\245&\312B\224\322\224\306\216\230R\243d\244\362\251DT\361\r/\223M0s\322\246\212\014.q\311\251\004>\324\326\2035\004\226\307\322\242\026\3705\r\312\355SXw|\261\254\351\222\252<9=)\321\303Nx@\025\026\334\032\236,\n\266\204T\234S\030\346\234\200\232\2368\211\"\265\354\240#\034V\254qqS\244 T\312\202\236#\251\243\2135j+l\324\257\000QQy[\217J\226;cV\222\314\236\325b;v^\325:[\373U\224\267\334\rBb\332\325$kR\371|T\221\245Z\212<\324\336_\313M1\346\2410ri\206,T\302 c\006\203\035F\351Q2TL\225\003\245@\351\\\230\\\232B\224\322\264\233h\333F\332B\264\322\224\322\224\302\224\337.\201\035(\213\006\244\021\323\204T\253\006\342\005X\026\375\251\377\000f\366\245\3738\003\245A4@U\031\210Z\313\272r\331\025\2274D\223T\345\200\372T?g>\224\323\036\323C.EBb\346\244H\rL\220\232\224\302\330\247GnX\363Wb\263\343\245Z\206\327\006\264\340\214(\253iS\016\3254hML\220\363W!\202\255\307\036)%\217u>\336\327q\346\256\245\250\004qW\340\265\004t\251M\250\035\251\014Ai\013\000\n\216\265\t\214\223NX\261R\205\247\242\325\230\205X m\3053\313\3159b\310\243\310\006\224[\3423Q\262Tl\225\023\245@\353P:T\016\265\311*rh)M+Ln)\204\322d\322\022OjBH\355H\034\032v\314\322\210\263\332\234\261sO\020\346\234!\247\210jx\255\370\315N\220SeP\202\252\274\330\252\223I\232\2412\027\252\262[\222j\007\265\366\252s[s\322\2416\376\325Z\342\337i\250V<\320` \364\251cLT\361\240&\255,\000\216\224\253\020SVcaV#\000\232\264\212jx\326\254\306\231\253\260\305\305YH\361VcZ\231V\244X\363V`\217\025v8\363\212\275o\026\005=\343\305D\361\344UB\271s\216\325\"-;m9S4\375\230\251c\371j`sO\013\232|kS\210\262)L_.*\264\221\341\210\250Y*\'J\256\351PH\265]\322\271EJ\nsQ8\305G\344\263\366\342\245\216\310\236\242\247\026*:\212q\265Lb\240}?q\310<UK\2133\021\310\351M\210\347\203V\243\217\"\245\020S\326\002)\353\016i\342\n\262\226\374b\2451l\025B\345rj\213\305UgP\200\223TL\377\0001\245\014\033\255#\306\010\252\262\3023Q\033l\325k\233S\203\305QH\266\266*\322\332\206\035)\032\323\035\251R\330\203\322\254*\2201Mh\311\247G\023U\330!<U\344\217\002\246D\346\256A\035^\2158\253\t\036j\324p\324\313\rK\034<\325\270\240\253q\305W\240\217\002\226D\250$N*\246\315\255O+\212]\271\024\365Z\220%;f*HS-V\n\000)\310\005O\022\2268\251\232,\n\2574[\371\357U\035*\027J\254\351P:T\016\265\311t\245\306\352AjX\202zU\264\215\021q\216iv\263}\321CG\265rMDH\346\231\235\243\2555\200\230`\325v\260 \345i\360\002\016\3229\025q#\315J\261S\274\2209\246\203\373\300\270\253\321G\232\216\341p8\254\371P\223U\246\0021\317Z\312\272%\363Y\315\031\006\214\343\275!\224\216\365^Y\315\021]d\200j\333\302&L\326{\331\355j\231#\332)\313\036\343V\026\327#\2451\355\210\355H\266\374\364\2530\333\017J\270\226\340\016\224\361\035O\034\031\253\220\301\322\257E\007\025:E\203V\342\217\"\254,T\360\273j\3045n 3W\341Q\266\2332T\014\234sU^?\232\224-;\313\247*b\245QO\333\305:\005\334x\251\261\3174\3409\251\241p\244\032\263#f\241u\252\222\246\032\253\310\265]\326\240u\252\322-rI\026z\325\210`\317QS\255\276\343\355M1\005ny\245yv\246\000\002\252\310\374\032\256\362s\3053\226\253\020\200\275z\324\341s\3151\321wt\344T\361.EL\252)\341x\250b@\323\326\224i\200j\031\3239\252rF\024\022k\"\350\226cT\236<\325ib\305Ux\352\026^1U\344\2175\000R\206\256\3059\333\212tG\314|\032\266-\262\264\301\016\326\253\360F\010\251\032\3207jE\261\366\251\226\323oj\225`\247\013nj\314P\343\265[\212.zU\350\241\342\206]\246\254\333\220j\3168\246\222\t\253v\350\010\251\217\312j\324\023T\347\014*)\000\002\253\0203@\\\323\266\322\355\366\245\003\006\235\232\261m\036\0018\245c\363\322\321\234sVa\1774\001\216E+\236qPJ\2719\250$Z\254\353\326\253\310*\254\213\232\346\342\213\247\025`D\002\322\214\225\300\351Q\263\n\202f\315T\221\262j\0223RF\000\247\261\3075*M\362\361NA\272\254\306\206\247\t\305<\247\313P[\014\\\034\326\232\016\265\004\343\000\232\311\236bMR\221wUgLUyc\315Vx\252\t\"\252\357\035B\321f\205\217mH\237+f\265m[z\212Y\342\333\3152\336\\6+f\3361\"\346\254\210\000\355G\221\236\224\345\265>\225\"\333\037J\236;SS\244A\0175edEZ\255q0\317\024\333{\214\032\274\'\312\324f_\232\256\333\334\020*o7q\253Pt\315O\346`S\013\222=\252,\363R(\310\247\201\3158.iB\n\221R\246C\201\212k\2009\240\0369\244\247\306\3463\305ZD\363~oZI!\300\342\253\311\017\0075Nd\252\262-Vu\254E\210(\346\225\200\305D\355\203\305F\303<\325Y\2175U\373\323)\350)\362\034-G\021\371j\354\003 U\310\226\247\301+N\031\306;Sb\200\031\301\253dl\004\324\022\266\365<V\\\320\222O\025\013CPI\rW\2221U\336!U\244\212\252\311\035Fc\243\312\315\036V*\325\237\312\325\250\320\371\211T\215\261G\316+F\326o,\000j\327\332\201\253V\356\017Z\274\035\000\240K\030\245k\224\003\212\2475\326O\025\020\231\333\275=Q\237\255O\024\004U\224\210\232\221m\311\253Q\307\216\rH\024g\255X\215\266\364\253\010\340\212k\276)\2523S%<\n\221E<\np\024\240PA\240\014\361J\242\244\013V\255\230\001\212\232@\rV\225x\254\371\207&\252H\265ZAX\254;\324\022\032\201\315D\362\235\265U\237&\242c\223ND\315J\022\231(\342\233j\240\234V\204I\263\212\265\037^\225(<S\251\321\360\300\366\251\032L\206\025\t\351PH\265ZH\352\273\245V\222:\256\353\315B\351\305V\222\032\204\307\212M\224\004\247\240\332sZV\263d\000j\331\205\\S>\313\216\224\364\2665a\020\245+3\323F\374\324\201\035\252E\267\365\247\205T\247\207\305<\\m\251\241\272\031\301\034U\243&W+K\346\026\247\243\022j\324`\342\246\\\324\2337S\202b\236\005H\253\232\220-H\005<-(_j6SJ\340\346\225V\244A\271\261R\355\362\237\212\230>\341QJx\254\371\207&\252H*\264\225\203#b\253\310\336\365VI*\006|\324ML\306MO\030\300\247\253\206\342\2310\300\300\252\251!\212lv\255\210O\230\200\347\232\231\\\212\220>i\340\323\203qH\030\002A=jE\204\236\275)\222\303\212\252\353\326\240\2211PH\225VD\250\035j\027Z\211\222\230R\223e.\334T\221\235\246\255\307pEX\027\030\024\345\272\247\213\241OY\367T\242Q\351R\254\240\016\224\033\216:TFM\306\227}*\266jd\251\343vC\355W\021\203\036>\265<C5n1\212\260\251R\005\247\005\247\004\251\021j@*EZ\220%.\337j1\212i\\\320\007\024\261\266\331*I\037sf\221e\002\233$\202\251\316\300\346\2529\250\034f\271\211d\346\253H\371\252\316\331\250\311\3057\255\003\255H\274\212p\\\034\323[\223UnW\0035-\215\371_\225\215h\3038cVU\363\326\236\030\032z\232IA\352;T\266\367\340\235\222\014\037Z\232V_QT\\d\237Jd\211\315Vt\252\356\225]\343\250Y*&J\214\256(\306{Q\262\220.\rH\271\025*\344\365\247\0049\247\204\251P\021S\24052t4\252\264l\347\245.\314\323\326<T\312\225:.EI\032\224<U\330:\n\271\030\253(*`\264\360\231\251\004t\341\035H#\247\254u(LS\204`\320b\030\250\314x\244\333\201M\333\223C\017\226\241|\202j\026\222\242s\232\201\352\026\357\\{\311\232\201\336\242\246\222))\t\3059^\244W\024\326<\324\027\' \325\030?\327V\304#f3\336\256\306\371\0252\217J\225N\r?\"\241d\005\263R\030\303\000{\212pBA\244\2220\3000\250\036:\257$~\325ZD\250\031*&J\205\222\231\267\024\273h\333O\013R*\324\212\rJ\221\237J\224GR*\324\250\2652\306\010\2441\001NT\247\252\324\252\225*-N\251\232\2321\203V\343\253Q\324\3503S*\324\252\265*\245<GN\013\212\260\260\222\271\305!\217\006\215\224\302\264\306J\214\2455\205@\365^A\305BzTOQ\265p\354j&5\0319\244\'\024\323 \025\021\233\232U\2274\377\0007\024\tri\2237\025Q\016\311+E&%j\344\022f\255#\324\252\324\360\364\243\223O\007\212\2221\332\235\267\265F\361{Uw\217\322\253I\037\265W\222?j\201\343\305B\311M)M+@Zr\255H\027\025\"/5n%\006\246\362\275)6c\322\236\252EJ\242\244\013\232_+\035)\312\225*\245H\213S\242\324\352\225<k\212\262\202\254F*\302.jeZ\231\022\247H\351\306 \010\251D\204\361\214\nk\016\364\233r)\254\240\236\0050\2450\255D\351U\344Z\257 \252\356*\027\025\023\n\341\031\25264\322qPK8\\\325f\230\2650\313\357H\263b\236\'\315*\334sOi7\n\206N\001\307Z[\031\313K\261\217^\225\267\032\354\0252I\330\365\251\325\252E\251W\212\221\006jU\025\"\212\034\014sT.n\022&\344\324>ha\232c ~j\031#\307AU\232>i\2062i\205\r\002:v\334R\201R-M\033\225\253\013&jA\315=\0275:\'\265J\251O\t\355N\021\323\202\342\244T\251\343Z\231V\245\214sVPT\361\216j\324kV\0213V\022:\235\023\024\375\231#\212s\306\245r8\2461%pzS1\305!\036\324\205i\214\265\033%W\221*\254\251UdZ\201\305B\325\300\323H\342\253O.8\025FW9\353P\264\330\025\021\230\323|\343Hd=\215:9ry\353VR\\\361S\2140\252\262!I\003/Z\277m\2517\n\365\253\t\3362*\312p*dqS)\251\226\245J\224S_\245a\352\243a8\247\330\035\361\014\325\257$\036\234S\036\003\212\256\360\221Q\030i\206 )\276_4\2051F\312P\264\361\305J\246\247CS\245O\035X\\R\216M<\nu=W\035*T\251\226\246E\253\0101S\306*\324b\256B\225r(\352_.\247\362\007\225\273\275C\263\212\211\206)\224\2704\230\246\225\250\331j\027J\253*UI\022\253:\325w\025\347\354y\250\345}\252k:Yy&\251\313&\343P1\346\230\315Q\227\240IO\rS\307&O=j\324-\272\245)\236\325\033E\264\346\254\301\250<\000\000kWO\324\022\340\341\2705\263\0241\270\317\002\235\345\242\203\363t\244F\007\241\251\325\2058\276\005W\236\344F2Mc^\334\375\245\225\027\361\253\266\221\354@1V\324\342\234FED\351P\264^\325\023G\355L)\212i\216\223e&\314R\205\247\001R\257\025*5N\217S\243\324\252\325\"\265=MH\265\"\363R/\025a*\304|\325\230\326\254\307W!5v#VUwt\024\256\314\006\337J\210\364\250[\255%\024\204f\234 ,\244\324\014\270\250\234UiEU\221j\254\213Ud\025\347\214pj\245\324\200\014V\\\262d\232\256Z\243f\250\231\2522\324\320\374\323\325\352dj\267\003\340\212\322\210\202\240\322K\206\250\2149\251\255\255\331\033p\342\265c\274\221\027\003\255#\3133)!\272\324V\367\363[d0\310\253qkh[\014pjw\326`H\311\363\006~\265\217>\251%\353\225\214\034z\325\353\0132\230g\373\306\264\325p1K\322\2241\241\2449\373\274Sw\016\342\202\001\351Lh\251\246\032O&\220\301G\223G\225\212P\264\345\024\361\221R+b\246F\311\251\224\344\212\235\005N\213\212\225S\320T\212\265*.\rN\202\254\306j\314f\255Dj\334OVc\220\251\3104\255&\343Q;\324e\371\240\034\320ib\033\233\025\240\001\021`\016\325\2350\303\032\201\306j\264\253Ud\025ZJ\251 \2576\231\202\2515\223u)$\325\'j\211\232\243-\232\214\324m\322\233J\0175<f\255B\325z)\360)\336v\343SF\333\210\253q\270\002\254\3047\366\253\001\0061M{p{U\033\213\020\347\212\202=\037{rN+b\317NH@\300\255\001\036\301\322\227\267\024c\232p\024\273iB\003NXA\355O\362\007\245\rn1\326\231\344\201Hb\002\232c\2441f\230b\244\333\2121N\013R\242\325\230\326\254\306\265a\023\322\247D\251\226<\232\177\222T{T\210\271\251UH54f\254\306\325f9*u\222\237\276\232Nj3J\247\006\245Q\221H3\033\003V\205\350+\357U%m\314MBzT2.j\244\253U$Z\253\"\327\224\335\315\201\212\312\226L\232\256\315Q1\246\323OZ\215\251\000\315(\030\251\025\200\251\243~j\302\276i\310\304\032\267\013\346\255\306\303p\347\212\277\014\300\014\n\262\214\0174\362i6\206\251\"\217\034\325\324\000\001\212w^\246\215\271\245\tN\n\005;fi\301\r=V\236\026\227o=\351\031i\2733M1\320#\2440\347\2450\302A\351H\"\366\247\010\351\351\0375b4\253\010\265f5\253\021\246j\314qz\324\252\230\351\322\206\213\003+H\255\316\017Z\230\'q\322\236\274T\250\330\251\221\263O\017\203O\r\232\033\2455[\034T\3610\251\016\rD\313\203\3050\323\030qQ\277J\255(\315T\220UiEx\265\314\333\211\025E\332\242cQ\223I\232BqM<\322\001\212B\324\201\352X\332\254#\325\230\333\"\247N9\355Vbj\271\021\253(\307\275N\231j\262\2126\373\324\311\200\270\251\0014\365\355\232\220\014\323\202\323\300\247\005\247\252\323\300\3158-;m(Z<\261Mh\307jE\213u8\304\005&\317Q\212a_^\224\2421OXjU\217\025<q\325\230\343\315XE\305L\271\247\357\300\240\036sH\3007=\351br\247\006\254\014\021\305=G\025*\214S\361\232Q\221O\034\212t(\013\363JWk\234t\251\003\034S\031\251\224\326\250\236\241a\201U\245Z\253\"W\203\310\371\250\035\252&jnE\033\251\245\251\245\251\205\350\316h\025\"\232\225\rZ\211\252\334g5eW\270\251\342\220\216\r\\\213,\001\253q\034\001S\253T\253S-H\242\244QR\250\315=V\236\026\236\026\224-<-8-\024\231\243\"\232z\361K\270\201H_\212L\212U\343\216\242\246A\221S\'\270\251\320\016\302\245_z\2208\003\212]\364\241\363J\037\024\360\340\365\247\251\007\203R!+\364\2531\262\277\035\rL\243\232\224%9\025s\363\016)\300\004\'\035(U\357\212\010\244&\232Ni\204\322\023\212\215\271\250\233\245B\353U\234f\276|\221\352\026j\214\2657u!zazizij\003T\213\315J\265*\n\263\020\253\221\n\267\030\315ZD\351VPb\254Fj\314c5:-J\253R(\305L\2435\"\256)\341M8\002*A\332\235\212v)\r4\232JL\373Ro\244\355\221M\335J\032\234\rH\222\021S\3078\3163S\2111N\017\232psO\r\232pjpj7\342\236\262v\251\242\227\362\253\010CU\224\227\240?\235YC\221\357R\014c\212p\031\245\351H\303\"\242e#\2550\232o^\235i\247\2554\212\215\2522*)#\3348\257\233\335\25265\0314\302i\245\251\205\263I\232)\352*D\251\220g\025:%Z\215j\334KV\342Z\267\030\253Q\255XE\251\321ju\315J\253\232\225V\245U\251TS\300\247\016iq\212\\\320M4\232M\302\220\260\365\246\227\246\223\201G\033}\351\275\006iK`f\200\365\"6i\331$\361S#\021\214\232\225^\244\017\357R+S\367Q\272\235\273\245\001\251\352\344T\321\315\212\264\223\202*\302O\264{U\230\346\3175:J\033\332\202\302\232_\267j\031\262*3\300\244\355HNG?\2350\212iZk-F\312+\346Ri\204\323\t\2461\246\023M\'\212\007Jr\255J\253R\242\324\350\265b5\253Q%[\211*\334kVcZ\262\202\254F*\302-N\213S*\324\252\265\"\255J\253N\013N\330)\247\212ijizizizn\372B\324\007\243u8`\322\207+\3068\244p\007#4\261\203\214\324\252F*D qR)\346\236\265*5I\232ZQ\234\322\322\203J\033\006\244Y*x\347\343\025f9\360\006\rN\263dpjQq\221\203Jd\244\363qG\231AnsJ_\002\230_\024\323\'\277\024\214EF\314+\3462\324\322i\214i\204\342\233E*\255J\253R\252\324\250\225:%Z\212:\267\024uj5\253Q\245Y\215*\302%N\213V\021j\302-L\213R\250\251\002\323\200\3059M+\032\214\236j6\246\022sL-I\232Bi\271\244\335@jr\271\247\2065*\226\306\010\342\210\300bGj~\006\r\nqR+t\251T\324\253\322\244QO\002\235E\024R\214\323\303S\322R8\251\322oz\225f\247\211\251|\341\353K\346\323\274\332\014\224\335\364\322\364\323!\025\033I_4n\244&\232Ni\204\344\321\214\323\200\305=EJ\253\232\225W\025<b\254D\225n%\253Q\255X\215j\314b\255F*\302-X\215jtZ\231V\246QR\250\305?8\243u!4\323!\006\232\322\006\034\365\246\023L\335M&\233Fi\244\323I\243u8\032\221\rL\030\016\364\200\220x\245\031=jE\030\247\216\203\212\225MH\255S+S\301\305(j\\\323\205\004f\226\220\212@{S\303\021N\022\363O\022\323\274\332O7\006\236&\367\247y\224\236m/\233\232B\331\025\023\032\371\2674\204\346\232M%:\224u\251\020T\310*eZ\2365\253Q%Z\215j\324kV\021*\302-Y\215j\312-N\202\254 \251TT\2521N\007\024n\315\005\2517R\023\232i\3054\214\323\0104\334\342\232X\032\013\000)\244\203\3104\224c\024\243\216\264\365$t\247\214\324\313O\247-=M<\021\212z\236*ElT\212\324\241\251\343\245=i\300R\354\240\212\214\365\245\316\r\000PN)7b\223}\002\\w\247\211\251\014\264\202njA6E\014\365\377\331"
+byte_png: "\211PNG\r\n\032\n\000\000\000\rIHDR\000\000\002\000\000\000\002\000\010\000\000\000\000\321\023\213&\000\000\001GIDATx^\355\3359\016\2000\014E\301(\367?\263E\377+\220\034D\310L\371n`9\313\030\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\300\013f\006\000\000\000\330\234Y\027\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\240\213\227\034\000\000\000\200\273*\003\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000l\2402\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\234\2552\000\000\000\000\000\000\000\000\000\000\000\000<43\000\000\000p\204\206\373\352FJ\000\000\000\000\000\000\200\337h\330\"\003\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@/\377$\001\000\000\000\000\000\000\000\000\000,\344\260&\000\000\000\000\000\000\000\000\000\000\000_p\001c\233\005\005v\341\233P\000\000\000\000IEND\256B`\202"
diff --git a/core/res/res/color-watch/btn_watch_default_dark.xml b/core/res/res/color-watch/btn_watch_default_dark.xml
index 68b0eb6..333b44b 100644
--- a/core/res/res/color-watch/btn_watch_default_dark.xml
+++ b/core/res/res/color-watch/btn_watch_default_dark.xml
@@ -17,6 +17,6 @@
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
     <item android:state_enabled="false"
           android:alpha="?attr/disabledAlpha"
-          android:color="?attr/colorPrimaryDark"/>
-    <item android:color="?attr/colorPrimaryDark"/>
+          android:color="?attr/colorSurface"/>
+    <item android:color="?attr/colorSurface"/>
 </selector>
diff --git a/core/res/res/color-watch/overview_background.xml b/core/res/res/color-watch/overview_background.xml
new file mode 100644
index 0000000..48ad0e7
--- /dev/null
+++ b/core/res/res/color-watch/overview_background.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2021 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <!-- customizing to black for watches as this is used as the background for task transitions
+         (and WindowContainer fallback color) and all themes on watches are typically dark for
+         power savings -->
+    <item android:color="@android:color/black"/>
+</selector>
\ No newline at end of file
diff --git a/core/res/res/color-watch/switch_track_watch_default_dark.xml b/core/res/res/color-watch/switch_track_watch_default_dark.xml
index 15bbeda..5af2566 100644
--- a/core/res/res/color-watch/switch_track_watch_default_dark.xml
+++ b/core/res/res/color-watch/switch_track_watch_default_dark.xml
@@ -17,6 +17,6 @@
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
     <item android:state_enabled="false"
           android:alpha="?attr/disabledAlpha"
-          android:color="?android:colorPrimaryDark" />
-    <item android:color="?android:colorPrimaryDark" />
+          android:color="?android:colorSurface" />
+    <item android:color="?android:colorSurface" />
 </selector>
diff --git a/core/res/res/values-watch/colors_device_defaults.xml b/core/res/res/values-watch/colors_device_defaults.xml
index 6ffd6e6..ee9481c 100644
--- a/core/res/res/values-watch/colors_device_defaults.xml
+++ b/core/res/res/values-watch/colors_device_defaults.xml
@@ -16,102 +16,51 @@
 
 <!-- Colors specific to Theme.DeviceDefault on watches, as specified via themes_device_default.xml
      Note: These colors specifically proide a darker, high-contrast UI that is suitable for
-     wearables with respect to 'glanceability'. OEM customization is supported within this set. -->
+     wearables with respect to 'glanceability'. -->
 <resources>
     <!--
        accent_device_default_dark
-         > from values/colors_material/accent_material_dark
-         > from values/colors_material/material_deep_teal_200
-         = #ff80cbc4
-         ! replaced with custom color #5E97F6
-         ! OEMS can customize as per specification
+         > from values/system_accent1_100
+         ! replaced with color/system_accent1_400
     -->
-    <color name="accent_device_default_dark">#5E97F6</color>
+    <color name="accent_device_default_dark">@color/system_accent1_400</color>
 
     <!--
        foreground_device_default_dark
          - introduced to avoid coupling to foreground_material_dark
          - colorForeground typically falls through Theme.DeviceDefault to Theme.Material
          ! fixed as white for optimal glanceability/contrast
-         ! OEMs should not customize
     -->
     <color name="foreground_device_default_dark">@color/white</color>
 
     <!--
        background_device_default_dark
-         > from values/colors_material/background_material_dark
-         > from values/colors_material/material_grey_850
-         = #ff303030
+         > from values/system_neutral1_900
          ! replaced with custom color #000000
-         ! OEMs can customized as per specification
-           (derived from accent color, constrained by brightness)
     -->
     <color name="background_device_default_dark">#000000</color>
 
-    <!--
-       background_floating_device_default_dark
-         > from values/colors_material/background_floating_material_dark
-         > from values/colors_material/material_grey_800
-         = #ff424242
-         ! replaced with custom color #1D2E4D
-           (derived from accent color, constrained by brightness)
-    -->
-    <color name="background_floating_device_default_dark">#1D2E4D</color>
+    <!-- Derived from accent color at 20% luminance -->
+    <color name="background_floating_device_default_dark">@color/system_accent1_800</color>
 
     <!--
-       primary_device_default_dark
-         > from values/colors_material/primary_material_dark
-         > from values/colors_material/material_grey_900
-         = #ff212121
-         ! replaced with custom color #808080
-         ! OEMs can customize as per specification
-           (derived from background color + foreground @ 50% opacity)
-    -->
-    <color name="primary_device_default_dark">#808080</color>
+        primary_device_default_dark
+          > from values/colors/system_neutral1_900
+          ! replaced with system_neutral1_500
+     -->
+    <color name="primary_device_default_dark">@color/system_neutral1_500</color>
 
-    <!--
-       primary_dark_device_default_dark
-         > from values/colors_material/primary_dark_material_dark
-         = @color/black
-         ! replaced with custom color #333333
-         ! OEMS can customize as per specification
-           (derived from background color + foreground @ 20% opacity)
-    -->
-    <color name="primary_dark_device_default_dark">#333333</color>
+    <!-- Currently matches the "surface dark" definition for phones. -->
+    <color name="surface_dark">@color/system_neutral1_800</color>
 
     <!--
        button_normal_device_default_dark
-         - uses ?attr/disabledAlpha and ?attr/colorPrimaryDark to draw state list
+         - uses ?attr/disabledAlpha and ?attr/colorSurface to draw state list
            (used as colorButtonNormal attribute in theme)
          - see color-watch/btn_watch_default_dark.xml
     -->
     <color name="button_normal_device_default_dark">@color/btn_watch_default_dark</color>
 
-    <!--
-       error_color_device_default_dark
-         - introduced to avoid coupling to error_color_mtterial (also #F4511E)
-         - colorError typically falls through Theme.DeviceDefault to Theme.Material
-         ! OEMs can customize as per specification
-    -->
-    <color name="error_color_device_default_dark">#F4511E</color>
-
-    <!-- no customization required/suggested below this point -->
-
-    <!--
-       background_cache_hint_selector_device_default
-         - note that this is based off of colors/background_cache_hint_selector_device_default
-           xml drawable
-         - uses ?attr/colorBackground and transparency to draw
-         - no color customization required here
-    -->
-
-    <!-- deprecated for Wear
-         these overrides exist only for compatibility with existing
-         WTS theme test heuristics, based on the previous modifications
-         to the material theme, they should not be used for customization
-         as they are not exposed via publicly accessible attributes -->
-    <color name="accent_device_default_dark_60_percent_opacity">#995E97f6</color>
-    <color name="accent_device_default_700">#5385DB</color>
-    <color name="accent_device_default_light">#75A4F5</color>
-    <color name="accent_device_default_50">#93B7F5</color>
+    <!-- Matches the Wear Compose error color. -->
+    <color name="error_color_device_default_dark">#FF746E</color>
 </resources>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index cd25726..599d72a 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -9086,7 +9086,8 @@
         <attr name="dotColor" format="color|reference"/>
         <!-- Color of the dot when it's activated -->
         <attr name="dotActivatedColor" format="color|reference"/>
-
+        <!-- Keep dot in activated state until segment completion -->
+        <attr name="keepDotActivated" format="boolean"/>
     </declare-styleable>
 
     <!-- =============================== -->
@@ -9152,10 +9153,10 @@
              {@link android.os.Build.VERSION_CODES#N} and not used in previous versions. -->
         <attr name="supportsLocalInteraction" format="boolean" />
         <!-- The service that provides {@link android.service.voice.HotwordDetectionService}.
-             @hide @SystemApi -->
+             Expect a component name to be provided. @hide @SystemApi -->
         <attr name="hotwordDetectionService" format="string" />
         <!-- The service that provides {@link android.service.voice.VisualQueryDetectionService}.
-             @hide @SystemApi -->
+             Expect a component name to be provided. @hide @SystemApi -->
         <attr name="visualQueryDetectionService" format="string" />
 
     </declare-styleable>
@@ -10105,13 +10106,12 @@
     <declare-styleable name="CredentialProvider">
         <!-- A string that is displayed to the user in the Credential Manager settings
              screen that can be used to provide more information about a provider. For
-             longer strings (40 char) it will be truncated. If multiple services
-             show the subtitle then the string will be joined together. -->
+             longer strings it will be truncated. -->
         <attr name="settingsSubtitle" format="string" />
     </declare-styleable>
 
     <!-- A list of capabilities that indicates to the OS what kinds of credentials
-             this provider supports. This list is defined in CredentialProviderService. -->
+             this provider supports. -->
     <declare-styleable name="CredentialProvider_Capabilities" parent="CredentialProvider">
         <!-- An individual capability declared by the provider. -->
         <attr name="capability" format="string" />
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index ef19fc1..dd57bf3 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -192,6 +192,10 @@
          available on some devices. -->
     <bool name="config_enableHapticTextHandle">false</bool>
 
+    <!-- Enables or disables proximity service that approximates proximity with aiai attention
+         service. Off by default, since the service may not be available on some devices. -->
+    <bool name="config_enableProximityService">false</bool>
+
     <!-- Whether dialogs should close automatically when the user touches outside
          of them.  This should not normally be modified. -->
     <bool name="config_closeDialogWhenTouchOutside">true</bool>
@@ -3353,7 +3357,7 @@
     <!-- default window ShowCircularMask property -->
     <bool name="config_windowShowCircularMask">false</bool>
 
-    <!-- default value for whether circular emulators (ro.emulator.circular)
+    <!-- default value for whether circular emulators (ro.boot.emulator.circular)
          should show a display overlay on the screen -->
     <bool name="config_windowEnableCircularEmulatorDisplayOverlay">false</bool>
 
@@ -5919,9 +5923,6 @@
     <!-- Whether changing sensor privacy SW setting requires device to be unlocked -->
     <bool name="config_sensorPrivacyRequiresAuthentication">true</bool>
 
-    <!-- List containing the allowed install sources for accessibility service. -->
-    <string-array name="config_accessibility_allowed_install_source" translatable="false"/>
-
     <!-- Default value for Settings.ASSIST_LONG_PRESS_HOME_ENABLED -->
     <bool name="config_assistLongPressHomeEnabledDefault">true</bool>
     <!-- Default value for Settings.ASSIST_TOUCH_GESTURE_ENABLED -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index d837e95..51fd4eb 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -416,6 +416,7 @@
   <java-symbol type="bool" name="config_guestUserAllowEphemeralStateChange" />
   <java-symbol type="bool" name="config_localDisplaysMirrorContent" />
   <java-symbol type="bool" name="config_ignoreUdfpsVote" />
+  <java-symbol type="bool" name="config_enableProximityService" />
   <java-symbol type="array" name="config_localPrivateDisplayPorts" />
   <java-symbol type="integer" name="config_defaultDisplayDefaultColorMode" />
   <java-symbol type="bool" name="config_enableAppWidgetService" />
@@ -4999,8 +5000,7 @@
 
   <java-symbol type="bool" name="config_batteryStatsResetOnUnplugHighBatteryLevel" />
   <java-symbol type="bool" name="config_batteryStatsResetOnUnplugAfterSignificantCharge" />
-
-
+  
   <java-symbol name="materialColorOnSecondaryFixedVariant" type="attr"/>
   <java-symbol name="materialColorOnTertiaryFixedVariant" type="attr"/>
   <java-symbol name="materialColorSurfaceContainerLowest" type="attr"/>
diff --git a/core/tests/coretests/res/drawable-nodpi/test_too_big.png b/core/tests/coretests/res/drawable-nodpi/test_too_big.png
new file mode 100644
index 0000000..3754072
--- /dev/null
+++ b/core/tests/coretests/res/drawable-nodpi/test_too_big.png
Binary files differ
diff --git a/core/tests/coretests/src/android/graphics/drawable/IconTest.java b/core/tests/coretests/src/android/graphics/drawable/IconTest.java
index 75390a2..5d92296 100644
--- a/core/tests/coretests/src/android/graphics/drawable/IconTest.java
+++ b/core/tests/coretests/src/android/graphics/drawable/IconTest.java
@@ -20,6 +20,7 @@
 
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
+import android.graphics.RecordingCanvas;
 import android.graphics.Region;
 import android.os.Handler;
 import android.os.HandlerThread;
@@ -371,6 +372,90 @@
         }
     }
 
+    private int getMaxWidth(int origWidth, int origHeight, int maxNumPixels) {
+        float aspRatio = (float) origWidth / (float) origHeight;
+        int newHeight = (int) Math.sqrt(maxNumPixels / aspRatio);
+        return (int) (newHeight * aspRatio);
+    }
+
+    private int getMaxHeight(int origWidth, int origHeight, int maxNumPixels) {
+        float aspRatio = (float) origWidth / (float) origHeight;
+        return (int) Math.sqrt(maxNumPixels / aspRatio);
+    }
+
+    @SmallTest
+    public void testScaleDownMaxSizeWithBitmap() throws Exception {
+        final int bmpWidth = 13_000;
+        final int bmpHeight = 10_000;
+        final int bmpBpp = 4;
+        final int maxNumPixels = RecordingCanvas.MAX_BITMAP_SIZE / bmpBpp;
+        final int maxWidth = getMaxWidth(bmpWidth, bmpHeight, maxNumPixels);
+        final int maxHeight = getMaxHeight(bmpWidth, bmpHeight, maxNumPixels);
+
+        final Bitmap bm = Bitmap.createBitmap(bmpWidth, bmpHeight, Bitmap.Config.ARGB_8888);
+        final Icon ic = Icon.createWithBitmap(bm);
+        final Drawable drawable = ic.loadDrawable(mContext);
+
+        assertThat(drawable.getIntrinsicWidth()).isEqualTo(maxWidth);
+        assertThat(drawable.getIntrinsicHeight()).isEqualTo(maxHeight);
+    }
+
+    @SmallTest
+    public void testScaleDownMaxSizeWithAdaptiveBitmap() throws Exception {
+        final int bmpWidth = 20_000;
+        final int bmpHeight = 10_000;
+        final int bmpBpp = 4;
+        final int maxNumPixels = RecordingCanvas.MAX_BITMAP_SIZE / bmpBpp;
+        final int maxWidth = getMaxWidth(bmpWidth, bmpHeight, maxNumPixels);
+        final int maxHeight = getMaxHeight(bmpWidth, bmpHeight, maxNumPixels);
+
+        final Bitmap bm = Bitmap.createBitmap(bmpWidth, bmpHeight, Bitmap.Config.ARGB_8888);
+        final Icon ic = Icon.createWithAdaptiveBitmap(bm);
+        final AdaptiveIconDrawable adaptiveDrawable = (AdaptiveIconDrawable) ic.loadDrawable(
+                mContext);
+        final Drawable drawable = adaptiveDrawable.getForeground();
+
+        assertThat(drawable.getIntrinsicWidth()).isEqualTo(maxWidth);
+        assertThat(drawable.getIntrinsicHeight()).isEqualTo(maxHeight);
+    }
+
+    @SmallTest
+    public void testScaleDownMaxSizeWithResource() throws Exception {
+        final Icon ic = Icon.createWithResource(getContext(), R.drawable.test_too_big);
+        final BitmapDrawable drawable = (BitmapDrawable) ic.loadDrawable(mContext);
+
+        assertThat(drawable.getBitmap().getByteCount()).isAtMost(RecordingCanvas.MAX_BITMAP_SIZE);
+    }
+
+    @SmallTest
+    public void testScaleDownMaxSizeWithFile() throws Exception {
+        final Bitmap bit1 = ((BitmapDrawable) getContext().getDrawable(R.drawable.test_too_big))
+                .getBitmap();
+        final File dir = getContext().getExternalFilesDir(null);
+        final File file1 = new File(dir, "file1-too-big.png");
+        bit1.compress(Bitmap.CompressFormat.PNG, 100,
+                new FileOutputStream(file1));
+
+        final Icon ic = Icon.createWithFilePath(file1.toString());
+        final BitmapDrawable drawable = (BitmapDrawable) ic.loadDrawable(mContext);
+
+        assertThat(drawable.getBitmap().getByteCount()).isAtMost(RecordingCanvas.MAX_BITMAP_SIZE);
+    }
+
+    @SmallTest
+    public void testScaleDownMaxSizeWithData() throws Exception {
+        final int bmpBpp = 4;
+        final Bitmap originalBits = ((BitmapDrawable) getContext().getDrawable(
+                R.drawable.test_too_big)).getBitmap();
+        final ByteArrayOutputStream ostream = new ByteArrayOutputStream(
+                originalBits.getWidth() * originalBits.getHeight() * bmpBpp);
+        originalBits.compress(Bitmap.CompressFormat.PNG, 100, ostream);
+        final byte[] pngdata = ostream.toByteArray();
+        final Icon ic = Icon.createWithData(pngdata, 0, pngdata.length);
+        final BitmapDrawable drawable = (BitmapDrawable) ic.loadDrawable(mContext);
+
+        assertThat(drawable.getBitmap().getByteCount()).isAtMost(RecordingCanvas.MAX_BITMAP_SIZE);
+    }
 
     // ======== utils ========
 
diff --git a/core/tests/coretests/src/android/internal/os/anr/AnrLatencyTrackerTests.java b/core/tests/coretests/src/android/internal/os/anr/AnrLatencyTrackerTests.java
index 4eea076..7d5a0364 100644
--- a/core/tests/coretests/src/android/internal/os/anr/AnrLatencyTrackerTests.java
+++ b/core/tests/coretests/src/android/internal/os/anr/AnrLatencyTrackerTests.java
@@ -59,7 +59,10 @@
             .thenReturn(175L)
             .thenReturn(198L)
             .thenReturn(203L)
-            .thenReturn(209L);
+            .thenReturn(209L)
+            .thenReturn(211L)
+            .thenReturn(212L)
+            .thenReturn(220L);
     }
 
     @Test
@@ -68,6 +71,7 @@
         mLatencyTracker.appNotRespondingStarted();
         mLatencyTracker.waitingOnAnrRecordLockStarted();
         mLatencyTracker.waitingOnAnrRecordLockEnded();
+        mLatencyTracker.earlyDumpRequestSubmittedWithSize(5);
         mLatencyTracker.anrRecordPlacingOnQueueWithSize(3);
         mLatencyTracker.appNotRespondingEnded();
 
@@ -90,7 +94,16 @@
         mLatencyTracker.waitingOnProcLockStarted();
         mLatencyTracker.waitingOnProcLockEnded();
 
+        mLatencyTracker.dumpStackTracesTempFileStarted();
+        mLatencyTracker.dumpingPidStarted(5);
+
         mLatencyTracker.dumpStackTracesStarted();
+        mLatencyTracker.copyingFirstPidStarted();
+
+        mLatencyTracker.dumpingPidEnded();
+        mLatencyTracker.dumpStackTracesTempFileEnded();
+
+        mLatencyTracker.copyingFirstPidEnded(true);
         mLatencyTracker.dumpingFirstPidsStarted();
         mLatencyTracker.dumpingPidStarted(1);
         mLatencyTracker.dumpingPidEnded();
@@ -111,7 +124,7 @@
         mLatencyTracker.close();
 
         assertThat(mLatencyTracker.dumpAsCommaSeparatedArrayWithHeader())
-            .isEqualTo("DurationsV2: 50,5,25,8,115,2,3,7,8,15,2,7,23,10,3,6\n\n");
+            .isEqualTo("DurationsV3: 50,5,33,11,112,4,2,4,6,5,1,10,5,10,3,9,11,129,5,8,1\n\n");
         verify(mLatencyTracker, times(1)).pushAtom();
     }
 
@@ -121,6 +134,7 @@
         mLatencyTracker.appNotRespondingStarted();
         mLatencyTracker.waitingOnAnrRecordLockStarted();
         mLatencyTracker.waitingOnAnrRecordLockEnded();
+        mLatencyTracker.earlyDumpRequestSubmittedWithSize(5);
         mLatencyTracker.anrRecordPlacingOnQueueWithSize(3);
         mLatencyTracker.appNotRespondingEnded();
 
@@ -143,7 +157,18 @@
         mLatencyTracker.waitingOnProcLockStarted();
         mLatencyTracker.waitingOnProcLockEnded();
 
+
+
+        mLatencyTracker.dumpStackTracesTempFileStarted();
+        mLatencyTracker.dumpingPidStarted(5);
+
         mLatencyTracker.dumpStackTracesStarted();
+        mLatencyTracker.copyingFirstPidStarted();
+
+        mLatencyTracker.dumpingPidEnded();
+        mLatencyTracker.dumpStackTracesTempFileEnded();
+
+        mLatencyTracker.copyingFirstPidEnded(true);
         mLatencyTracker.dumpingFirstPidsStarted();
         mLatencyTracker.dumpingPidStarted(1);
         mLatencyTracker.dumpingPidEnded();
diff --git a/core/tests/coretests/src/android/os/VibrationEffectTest.java b/core/tests/coretests/src/android/os/VibrationEffectTest.java
index 627feab..f1bd329 100644
--- a/core/tests/coretests/src/android/os/VibrationEffectTest.java
+++ b/core/tests/coretests/src/android/os/VibrationEffectTest.java
@@ -50,6 +50,7 @@
 
 import com.android.internal.R;
 
+import org.jetbrains.annotations.NotNull;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.junit.MockitoJUnitRunner;
@@ -758,6 +759,109 @@
         assertTrue(100 / 255f > ((StepSegment) scaledDown.getSegments().get(1)).getAmplitude());
     }
 
+    private void doTestApplyRepeatingWithNonRepeatingOriginal(@NotNull VibrationEffect original) {
+        assertTrue(original.getDuration() != Long.MAX_VALUE);
+        int loopDelayMs = 123;
+        assertEquals(original, original.applyRepeatingIndefinitely(false, loopDelayMs));
+
+        // Looping with no delay gets the raw repeated effect.
+        VibrationEffect loopingOriginal = VibrationEffect.startComposition()
+                .repeatEffectIndefinitely(original)
+                .compose();
+        assertEquals(Long.MAX_VALUE, loopingOriginal.getDuration());
+        assertEquals(loopingOriginal, original.applyRepeatingIndefinitely(true, 0));
+
+        VibrationEffect loopingPart = VibrationEffect.startComposition()
+                .addEffect(original)
+                .addOffDuration(Duration.ofMillis(loopDelayMs))
+                .compose();
+
+        VibrationEffect loopingWithDelay = VibrationEffect.startComposition()
+                .repeatEffectIndefinitely(loopingPart)
+                .compose();
+        assertEquals(Long.MAX_VALUE, loopingWithDelay.getDuration());
+        assertEquals(loopingWithDelay, original.applyRepeatingIndefinitely(true, loopDelayMs));
+    }
+
+    @Test
+    public void testApplyRepeatingIndefinitely_nonRepeatingOriginal() {
+        VibrationEffect oneshot = VibrationEffect.createOneShot(100, DEFAULT_AMPLITUDE);
+        doTestApplyRepeatingWithNonRepeatingOriginal(oneshot);
+
+        VibrationEffect predefined = VibrationEffect.createPredefined(VibrationEffect.EFFECT_CLICK);
+        doTestApplyRepeatingWithNonRepeatingOriginal(predefined);
+
+        VibrationEffect primitives = VibrationEffect.startComposition()
+                .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK)
+                .addPrimitive(VibrationEffect.Composition.PRIMITIVE_TICK, 1, 100)
+                .compose();
+        doTestApplyRepeatingWithNonRepeatingOriginal(primitives);
+
+        VibrationEffect legacyWaveform = VibrationEffect.createWaveform(
+                new long[]{1, 2, 3}, new int[]{1, 2, 3}, -1);
+        doTestApplyRepeatingWithNonRepeatingOriginal(legacyWaveform);
+
+        // Test a mix of segments ending in a delay, for completeness.
+        doTestApplyRepeatingWithNonRepeatingOriginal(VibrationEffect.startComposition()
+                .addEffect(oneshot)
+                .addEffect(predefined)
+                .addEffect(primitives)
+                .addEffect(legacyWaveform)
+                .addOffDuration(Duration.ofMillis(1000))
+                .compose());
+    }
+
+    @Test
+    public void testApplyRepeatingIndefinitely_repeatingOriginalWaveform() {
+        // The delay parameter has no effect when the effect is already repeating.
+        int delayMs = 999;
+        VibrationEffect waveformNoRepeat = VibrationEffect.createWaveform(
+                new long[]{1, 2, 3}, new int[]{1, 2, 3}, -1);
+        VibrationEffect waveformFullRepeat = VibrationEffect.createWaveform(
+                new long[]{1, 2, 3}, new int[]{1, 2, 3}, 0);
+        assertEquals(waveformFullRepeat,
+                waveformFullRepeat.applyRepeatingIndefinitely(true, delayMs));
+        assertEquals(waveformNoRepeat,
+                waveformFullRepeat.applyRepeatingIndefinitely(false, delayMs));
+
+        VibrationEffect waveformOffsetRepeat = VibrationEffect.createWaveform(
+                new long[]{1, 2, 3}, new int[]{1, 2, 3}, 1);
+        assertEquals(waveformOffsetRepeat,
+                waveformOffsetRepeat.applyRepeatingIndefinitely(true, delayMs));
+        assertEquals(waveformNoRepeat,
+                waveformOffsetRepeat.applyRepeatingIndefinitely(false, delayMs));
+    }
+
+    @Test
+    public void testApplyRepeatingIndefinitely_repeatingOriginalComposition() {
+        // The delay parameter has no effect when the effect is already repeating.
+        int delayMs = 999;
+        VibrationEffect innerEffect = VibrationEffect.startComposition()
+                .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK)
+                .addPrimitive(VibrationEffect.Composition.PRIMITIVE_TICK)
+                .compose();
+
+        VibrationEffect repeatingOriginal = VibrationEffect.startComposition()
+                .repeatEffectIndefinitely(innerEffect)
+                .compose();
+        assertEquals(repeatingOriginal,
+                repeatingOriginal.applyRepeatingIndefinitely(true, delayMs));
+        assertEquals(innerEffect,
+                repeatingOriginal.applyRepeatingIndefinitely(false, delayMs));
+
+        VibrationEffect offsetOriginal = VibrationEffect.startComposition()
+                .addPrimitive(VibrationEffect.Composition.PRIMITIVE_THUD)
+                .repeatEffectIndefinitely(innerEffect)
+                .compose();
+        assertEquals(offsetOriginal,
+                offsetOriginal.applyRepeatingIndefinitely(true, delayMs));
+        assertEquals(VibrationEffect.startComposition()
+                .addPrimitive(VibrationEffect.Composition.PRIMITIVE_THUD)
+                .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK)
+                .addPrimitive(VibrationEffect.Composition.PRIMITIVE_TICK)
+                .compose(),
+                offsetOriginal.applyRepeatingIndefinitely(false, delayMs));
+    }
 
     @Test
     public void testDuration() {
diff --git a/core/tests/ddm/Android.bp b/core/tests/ddm/Android.bp
new file mode 100644
index 0000000..818ea8b
--- /dev/null
+++ b/core/tests/ddm/Android.bp
@@ -0,0 +1,41 @@
+//
+// Copyright (C) 2023 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
+java_test_host {
+    name: "frameworks-base-ddm-unittests",
+    srcs: [
+        "java/android/os/DdmSyncStateTest.java",
+        ":framework-android-os-unit-testable-src",
+    ],
+    static_libs: [
+        "junit",
+    ],
+    test_options: {
+        unit_test: true,
+    },
+    test_suites: [
+        "cts",
+    ],
+}
diff --git a/core/tests/ddm/java/android/os/DdmSyncStateTest.java b/core/tests/ddm/java/android/os/DdmSyncStateTest.java
new file mode 100644
index 0000000..8274ce4
--- /dev/null
+++ b/core/tests/ddm/java/android/os/DdmSyncStateTest.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os.test;
+
+import android.os.DdmSyncState;
+import android.os.DdmSyncState.Stage;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * Test DdmSyncState, the Android app stage boot sync system for DDM Client.
+ */
+
+public class DdmSyncStateTest {
+
+    @Test
+    public void testNoCycle() {
+        DdmSyncState.reset();
+        try {
+            DdmSyncState.next(Stage.Attach);
+            DdmSyncState.next(Stage.Bind);
+            DdmSyncState.next(Stage.Named);
+            DdmSyncState.next(Stage.Debugger);
+            DdmSyncState.next(Stage.Running);
+
+            // Cycling back here which is not allowed
+            DdmSyncState.next(Stage.Attach);
+            Assert.fail("Going back to attach should have failed");
+        } catch (IllegalStateException ignored) {
+
+        }
+    }
+
+    @Test
+    public void testDebuggerFlow() {
+        DdmSyncState.reset();
+        DdmSyncState.next(Stage.Attach);
+        DdmSyncState.next(Stage.Bind);
+        DdmSyncState.next(Stage.Named);
+        DdmSyncState.next(Stage.Debugger);
+        DdmSyncState.next(Stage.Running);
+        Assert.assertEquals(Stage.Running, DdmSyncState.getStage());
+
+    }
+
+    @Test
+    public void testNoDebugFlow() {
+        DdmSyncState.reset();
+        DdmSyncState.next(Stage.Attach);
+        DdmSyncState.next(Stage.Bind);
+        DdmSyncState.next(Stage.Named);
+        // Notice how Stage.Debugger stage is skipped
+        DdmSyncState.next(Stage.Running);
+        Assert.assertEquals(Stage.Running, DdmSyncState.getStage());
+    }
+}
diff --git a/core/tests/mockingcoretests/Android.bp b/core/tests/mockingcoretests/Android.bp
index 96811be..29d7902 100644
--- a/core/tests/mockingcoretests/Android.bp
+++ b/core/tests/mockingcoretests/Android.bp
@@ -40,7 +40,6 @@
         "platform-test-annotations",
         "truth-prebuilt",
         "testables",
-        "ub-uiautomator",
     ],
 
     libs: [
diff --git a/graphics/java/android/graphics/drawable/Icon.java b/graphics/java/android/graphics/drawable/Icon.java
index a76d74e..708feeb 100644
--- a/graphics/java/android/graphics/drawable/Icon.java
+++ b/graphics/java/android/graphics/drawable/Icon.java
@@ -35,6 +35,7 @@
 import android.graphics.BitmapFactory;
 import android.graphics.BlendMode;
 import android.graphics.PorterDuff;
+import android.graphics.RecordingCanvas;
 import android.net.Uri;
 import android.os.AsyncTask;
 import android.os.Build;
@@ -70,6 +71,7 @@
 
 public final class Icon implements Parcelable {
     private static final String TAG = "Icon";
+    private static final boolean DEBUG = false;
 
     /**
      * An icon that was created using {@link Icon#createWithBitmap(Bitmap)}.
@@ -361,15 +363,52 @@
     }
 
     /**
+     * Resizes image if size too large for Canvas to draw
+     * @param bitmap Bitmap to be resized if size > {@link RecordingCanvas.MAX_BITMAP_SIZE}
+     * @return resized bitmap
+     */
+    private Bitmap fixMaxBitmapSize(Bitmap bitmap) {
+        if (bitmap != null && bitmap.getByteCount() > RecordingCanvas.MAX_BITMAP_SIZE) {
+            int bytesPerPixel = bitmap.getRowBytes() / bitmap.getWidth();
+            int maxNumPixels = RecordingCanvas.MAX_BITMAP_SIZE / bytesPerPixel;
+            float aspRatio = (float) bitmap.getWidth() / (float) bitmap.getHeight();
+            int newHeight = (int) Math.sqrt(maxNumPixels / aspRatio);
+            int newWidth = (int) (newHeight * aspRatio);
+
+            if (DEBUG) {
+                Log.d(TAG,
+                        "Image size too large: " + bitmap.getByteCount() + ". Resizing bitmap to: "
+                                + newWidth + " " + newHeight);
+            }
+
+            return scaleDownIfNecessary(bitmap, newWidth, newHeight);
+        }
+        return bitmap;
+    }
+
+    /**
+     * Resizes BitmapDrawable if size too large for Canvas to draw
+     * @param drawable Drawable to be resized if size > {@link RecordingCanvas.MAX_BITMAP_SIZE}
+     * @return resized Drawable
+     */
+    private Drawable fixMaxBitmapSize(Resources res, Drawable drawable) {
+        if (drawable instanceof BitmapDrawable) {
+            Bitmap scaledBmp = fixMaxBitmapSize(((BitmapDrawable) drawable).getBitmap());
+            return new BitmapDrawable(res, scaledBmp);
+        }
+        return drawable;
+    }
+
+    /**
      * Do the heavy lifting of loading the drawable, but stop short of applying any tint.
      */
     private Drawable loadDrawableInner(Context context) {
         switch (mType) {
             case TYPE_BITMAP:
-                return new BitmapDrawable(context.getResources(), getBitmap());
+                return new BitmapDrawable(context.getResources(), fixMaxBitmapSize(getBitmap()));
             case TYPE_ADAPTIVE_BITMAP:
                 return new AdaptiveIconDrawable(null,
-                    new BitmapDrawable(context.getResources(), getBitmap()));
+                    new BitmapDrawable(context.getResources(), fixMaxBitmapSize(getBitmap())));
             case TYPE_RESOURCE:
                 if (getResources() == null) {
                     // figure out where to load resources from
@@ -400,7 +439,8 @@
                     }
                 }
                 try {
-                    return getResources().getDrawable(getResId(), context.getTheme());
+                    return fixMaxBitmapSize(getResources(),
+                            getResources().getDrawable(getResId(), context.getTheme()));
                 } catch (RuntimeException e) {
                     Log.e(TAG, String.format("Unable to load resource 0x%08x from pkg=%s",
                                     getResId(),
@@ -409,21 +449,21 @@
                 }
                 break;
             case TYPE_DATA:
-                return new BitmapDrawable(context.getResources(),
-                    BitmapFactory.decodeByteArray(getDataBytes(), getDataOffset(), getDataLength())
-                );
+                return new BitmapDrawable(context.getResources(), fixMaxBitmapSize(
+                        BitmapFactory.decodeByteArray(getDataBytes(), getDataOffset(),
+                                getDataLength())));
             case TYPE_URI:
                 InputStream is = getUriInputStream(context);
                 if (is != null) {
                     return new BitmapDrawable(context.getResources(),
-                            BitmapFactory.decodeStream(is));
+                            fixMaxBitmapSize(BitmapFactory.decodeStream(is)));
                 }
                 break;
             case TYPE_URI_ADAPTIVE_BITMAP:
                 is = getUriInputStream(context);
                 if (is != null) {
                     return new AdaptiveIconDrawable(null, new BitmapDrawable(context.getResources(),
-                            BitmapFactory.decodeStream(is)));
+                            fixMaxBitmapSize(BitmapFactory.decodeStream(is))));
                 }
                 break;
         }
diff --git a/libs/WindowManager/Shell/res/values-watch/colors.xml b/libs/WindowManager/Shell/res/values-watch/colors.xml
new file mode 100644
index 0000000..82492bf
--- /dev/null
+++ b/libs/WindowManager/Shell/res/values-watch/colors.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright 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.
+ */
+-->
+<resources>
+    <color name="splash_window_background_default">@color/splash_screen_bg_dark</color>
+</resources>
+
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java
index 956af70..68952c0 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java
@@ -32,6 +32,7 @@
 import android.hardware.input.InputManager;
 import android.os.Looper;
 import android.provider.DeviceConfig;
+import android.util.Log;
 import android.view.BatchedInputEventReceiver;
 import android.view.Choreographer;
 import android.view.InputChannel;
@@ -243,6 +244,8 @@
 
     @VisibleForTesting
     void onInputEvent(InputEvent ev) {
+        // TODO: remove logging once b/269505548 is resolved
+        Log.d(TAG, "onInputEvent: " + ev);
         if (!mEnableDragCornerResize && !mEnablePinchResize) {
             // No need to handle anything if neither form of resizing is enabled.
             return;
@@ -393,6 +396,7 @@
 
     @VisibleForTesting
     void onPinchResize(MotionEvent ev) {
+        Log.d(TAG, "onPinchResize: " + ev);
         int action = ev.getActionMasked();
 
         if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
@@ -436,6 +440,10 @@
             mLastPoint.set(x0, y0);
             mLastSecondPoint.set(x1, y1);
 
+            // TODO: remove logging once b/269505548 is resolved
+            Log.d(TAG, "at onPinchResize (" + x0 + ", " + y0 + ")");
+            Log.d(TAG, "at onPinchResize (" + x1 + ", " + y1 + ")");
+
             // Capture inputs
             if (!mThresholdCrossed
                     && (distanceBetween(mDownSecondPoint, mLastSecondPoint) > mTouchSlop
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipPinchInTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipPinchInTest.kt
index 85b2fbc..8eb41b4 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipPinchInTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipPinchInTest.kt
@@ -16,6 +16,7 @@
 
 package com.android.wm.shell.flicker.pip
 
+import android.platform.test.annotations.FlakyTest
 import android.platform.test.annotations.Postsubmit
 import android.tools.common.Rotation
 import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
@@ -34,6 +35,7 @@
 @RunWith(Parameterized::class)
 @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
+@FlakyTest(bugId = 270677470)
 class PipPinchInTest(flicker: FlickerTest) : PipTransition(flicker) {
     override val transition: FlickerBuilder.() -> Unit
         get() = buildTransition { transitions { pipApp.pinchInPipWindow(wmHelper, 0.4f, 30) } }
diff --git a/libs/androidfw/ApkParsing.cpp b/libs/androidfw/ApkParsing.cpp
index 32d2c5b..7eedfdb 100644
--- a/libs/androidfw/ApkParsing.cpp
+++ b/libs/androidfw/ApkParsing.cpp
@@ -56,6 +56,11 @@
         return nullptr;
     }
 
+    // Make sure file starts with 'lib/' prefix.
+    if (strncmp(fileName, APK_LIB.data(), APK_LIB_LEN) != 0) {
+        return nullptr;
+    }
+
     // Make sure there aren't subdirectories by checking if the next / after lib/ is the last slash
     if (memchr(fileName + APK_LIB_LEN, '/', fileNameLen - APK_LIB_LEN) != lastSlash) {
         return nullptr;
diff --git a/libs/androidfw/Idmap.cpp b/libs/androidfw/Idmap.cpp
index 8983574..5f98b8f 100644
--- a/libs/androidfw/Idmap.cpp
+++ b/libs/androidfw/Idmap.cpp
@@ -294,14 +294,14 @@
                                dtohl(header->version), kIdmapCurrentVersion);
     return {};
   }
+  std::optional<std::string_view> target_path = ReadString(&data_ptr, &data_size, "target path");
+    if (!target_path) {
+      return {};
+    }
   std::optional<std::string_view> overlay_path = ReadString(&data_ptr, &data_size, "overlay path");
   if (!overlay_path) {
     return {};
   }
-  std::optional<std::string_view> target_path = ReadString(&data_ptr, &data_size, "target path");
-  if (!target_path) {
-    return {};
-  }
   if (!ReadString(&data_ptr, &data_size, "target name") ||
       !ReadString(&data_ptr, &data_size, "debug info")) {
     return {};
@@ -364,7 +364,7 @@
   return std::unique_ptr<LoadedIdmap>(
       new LoadedIdmap(std::string(idmap_path), header, data_header, target_entries,
                       target_inline_entries, target_inline_entry_values, configurations,
-                      overlay_entries, std::move(idmap_string_pool), *target_path, *overlay_path));
+                      overlay_entries, std::move(idmap_string_pool), *overlay_path, *target_path));
 }
 
 bool LoadedIdmap::IsUpToDate() const {
diff --git a/libs/androidfw/include/androidfw/Errors.h b/libs/androidfw/include/androidfw/Errors.h
index 948162d..6667747 100644
--- a/libs/androidfw/include/androidfw/Errors.h
+++ b/libs/androidfw/include/androidfw/Errors.h
@@ -34,7 +34,7 @@
 
 // Checks whether the result holds an unexpected I/O error.
 template <typename T>
-static inline bool IsIOError(const base::expected<T, NullOrIOError> result) {
+static inline bool IsIOError(const base::expected<T, NullOrIOError>& result) {
   return !result.has_value() && std::holds_alternative<IOError>(result.error());
 }
 
diff --git a/libs/androidfw/tests/ApkParsing_test.cpp b/libs/androidfw/tests/ApkParsing_test.cpp
index 62e88c6..ac1dc9b 100644
--- a/libs/androidfw/tests/ApkParsing_test.cpp
+++ b/libs/androidfw/tests/ApkParsing_test.cpp
@@ -74,4 +74,10 @@
   auto lastSlash = util::ValidLibraryPathLastSlash(path, false, false);
   ASSERT_THAT(lastSlash, IsNull());
 }
+
+TEST(ApkParsingTest, InvalidPrefix) {
+  const char* path = "assets/libhello.so";
+  auto lastSlash = util::ValidLibraryPathLastSlash(path, false, false);
+  ASSERT_THAT(lastSlash, IsNull());
+}
 }
\ No newline at end of file
diff --git a/libs/hwui/AutoBackendTextureRelease.cpp b/libs/hwui/AutoBackendTextureRelease.cpp
index b656b6a..ab85995 100644
--- a/libs/hwui/AutoBackendTextureRelease.cpp
+++ b/libs/hwui/AutoBackendTextureRelease.cpp
@@ -16,6 +16,8 @@
 
 #include "AutoBackendTextureRelease.h"
 
+#include <SkImage.h>
+#include <include/gpu/ganesh/SkImageGanesh.h>
 #include "renderthread/RenderThread.h"
 #include "utils/Color.h"
 #include "utils/PaintUtils.h"
@@ -83,10 +85,10 @@
     AHardwareBuffer_describe(buffer, &desc);
     SkColorType colorType = GrAHardwareBufferUtils::GetSkColorTypeFromBufferFormat(desc.format);
     // The following ref will be counteracted by Skia calling releaseProc, either during
-    // MakeFromTexture if there is a failure, or later when SkImage is discarded. It must
-    // be called before MakeFromTexture, otherwise Skia may remove HWUI's ref on failure.
+    // BorrowTextureFrom if there is a failure, or later when SkImage is discarded. It must
+    // be called before BorrowTextureFrom, otherwise Skia may remove HWUI's ref on failure.
     ref();
-    mImage = SkImage::MakeFromTexture(
+    mImage = SkImages::BorrowTextureFrom(
             context, mBackendTexture, kTopLeft_GrSurfaceOrigin, colorType, kPremul_SkAlphaType,
             uirenderer::DataSpaceToColorSpace(dataspace), releaseProc, this);
 }
diff --git a/libs/hwui/HardwareBitmapUploader.cpp b/libs/hwui/HardwareBitmapUploader.cpp
index b7e9999..19a1dfa 100644
--- a/libs/hwui/HardwareBitmapUploader.cpp
+++ b/libs/hwui/HardwareBitmapUploader.cpp
@@ -25,6 +25,7 @@
 #include <SkBitmap.h>
 #include <SkCanvas.h>
 #include <SkImage.h>
+#include <SkImageAndroid.h>
 #include <SkImageInfo.h>
 #include <SkRefCnt.h>
 #include <gui/TraceUtils.h>
@@ -262,7 +263,8 @@
           }
 
           sk_sp<SkImage> image =
-              SkImage::MakeFromAHardwareBufferWithData(mGrContext.get(), bitmap.pixmap(), ahb);
+              SkImages::TextureFromAHardwareBufferWithData(mGrContext.get(), bitmap.pixmap(),
+                                                           ahb);
           mGrContext->submit(true);
 
           uploadSucceeded = (image.get() != nullptr);
diff --git a/libs/hwui/Properties.cpp b/libs/hwui/Properties.cpp
index 7af6efb..b08ab32 100644
--- a/libs/hwui/Properties.cpp
+++ b/libs/hwui/Properties.cpp
@@ -21,7 +21,7 @@
 #ifdef __ANDROID__
 #include "HWUIProperties.sysprop.h"
 #endif
-#include "SkTraceEventCommon.h"
+#include "src/core/SkTraceEventCommon.h"
 
 #include <algorithm>
 #include <cstdlib>
diff --git a/libs/hwui/Readback.cpp b/libs/hwui/Readback.cpp
index 045de35..377b5bb 100644
--- a/libs/hwui/Readback.cpp
+++ b/libs/hwui/Readback.cpp
@@ -21,6 +21,7 @@
 #include <SkCanvas.h>
 #include <SkColorSpace.h>
 #include <SkImage.h>
+#include <SkImageAndroid.h>
 #include <SkImageInfo.h>
 #include <SkMatrix.h>
 #include <SkPaint.h>
@@ -108,7 +109,8 @@
     sk_sp<SkColorSpace> colorSpace =
             DataSpaceToColorSpace(static_cast<android_dataspace>(dataspace));
     sk_sp<SkImage> image =
-            SkImage::MakeFromAHardwareBuffer(sourceBuffer.get(), kPremul_SkAlphaType, colorSpace);
+            SkImages::DeferredFromAHardwareBuffer(sourceBuffer.get(), kPremul_SkAlphaType, 
+                                                  colorSpace);
 
     if (!image.get()) {
         return request->onCopyFinished(CopyResult::UnknownError);
diff --git a/libs/hwui/SkiaInterpolator.cpp b/libs/hwui/SkiaInterpolator.cpp
index b58f517..c67b135 100644
--- a/libs/hwui/SkiaInterpolator.cpp
+++ b/libs/hwui/SkiaInterpolator.cpp
@@ -18,9 +18,8 @@
 
 #include "include/core/SkScalar.h"
 #include "include/core/SkTypes.h"
-#include "include/private/SkFixed.h"
-#include "src/core/SkTSearch.h"
 
+#include <cstdlib>
 #include <log/log.h>
 
 typedef int Dot14;
@@ -41,18 +40,18 @@
     if (x <= 0) {
         return 0;
     }
-    if (x >= SK_Scalar1) {
+    if (x >= 1.0f) {
         return Dot14_ONE;
     }
-    return SkScalarToFixed(x) >> 2;
+    return static_cast<Dot14>(x * Dot14_ONE);
 }
 
 static float SkUnitCubicInterp(float value, float bx, float by, float cx, float cy) {
     // pin to the unit-square, and convert to 2.14
     Dot14 x = pin_and_convert(value);
 
-    if (x == 0) return 0;
-    if (x == Dot14_ONE) return SK_Scalar1;
+    if (x == 0) return 0.0f;
+    if (x == Dot14_ONE) return 1.0f;
 
     Dot14 b = pin_and_convert(bx);
     Dot14 c = pin_and_convert(cx);
@@ -84,7 +83,7 @@
     A = 3 * b;
     B = 3 * (c - 2 * b);
     C = 3 * (b - c) + Dot14_ONE;
-    return SkFixedToScalar(eval_cubic(t, A, B, C) << 2);
+    return Dot14ToFloat(eval_cubic(t, A, B, C));
 }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -104,7 +103,7 @@
     fFlags = 0;
     fElemCount = static_cast<uint8_t>(elemCount);
     fFrameCount = static_cast<int16_t>(frameCount);
-    fRepeat = SK_Scalar1;
+    fRepeat = 1.0f;
     if (fStorage) {
         free(fStorage);
         fStorage = nullptr;
@@ -136,17 +135,46 @@
 
 float SkiaInterpolatorBase::ComputeRelativeT(SkMSec time, SkMSec prevTime, SkMSec nextTime,
                                              const float blend[4]) {
-    SkASSERT(time > prevTime && time < nextTime);
+    LOG_FATAL_IF(time < prevTime || time > nextTime);
 
     float t = (float)(time - prevTime) / (float)(nextTime - prevTime);
     return blend ? SkUnitCubicInterp(t, blend[0], blend[1], blend[2], blend[3]) : t;
 }
 
+// Returns the index of where the item is or the bit not of the index
+// where the item should go in order to keep arr sorted in ascending order.
+int SkiaInterpolatorBase::binarySearch(const SkTimeCode* arr, int count, SkMSec target) {
+    if (count <= 0) {
+        return ~0;
+    }
+
+    int lo = 0;
+    int hi = count - 1;
+
+    while (lo < hi) {
+        int mid = (hi + lo) / 2;
+        SkMSec elem = arr[mid].fTime;
+        if (elem == target) {
+            return mid;
+        } else if (elem < target) {
+            lo = mid + 1;
+        } else {
+            hi = mid;
+        }
+    }
+    // Check to see if target is greater or less than where we stopped
+    if (target < arr[lo].fTime) {
+        return ~lo;
+    }
+    // e.g. it should go at the end.
+    return ~(lo + 1);
+}
+
 SkiaInterpolatorBase::Result SkiaInterpolatorBase::timeToT(SkMSec time, float* T, int* indexPtr,
                                                            bool* exactPtr) const {
-    SkASSERT(fFrameCount > 0);
+    LOG_FATAL_IF(fFrameCount <= 0);
     Result result = kNormal_Result;
-    if (fRepeat != SK_Scalar1) {
+    if (fRepeat != 1.0f) {
         SkMSec startTime = 0, endTime = 0;  // initialize to avoid warning
         this->getDuration(&startTime, &endTime);
         SkMSec totalTime = endTime - startTime;
@@ -168,10 +196,8 @@
         time = offsetTime + startTime;
     }
 
-    int index = SkTSearch<SkMSec>(&fTimes[0].fTime, fFrameCount, time, sizeof(SkTimeCode));
-
+    int index = SkiaInterpolatorBase::binarySearch(fTimes, fFrameCount, time);
     bool exact = true;
-
     if (index < 0) {
         index = ~index;
         if (index == 0) {
@@ -184,10 +210,11 @@
             }
             result = kFreezeEnd_Result;
         } else {
+            // Need to interpolate between two frames.
             exact = false;
         }
     }
-    SkASSERT(index < fFrameCount);
+    LOG_FATAL_IF(index >= fFrameCount);
     const SkTimeCode* nextTime = &fTimes[index];
     SkMSec nextT = nextTime[0].fTime;
     if (exact) {
@@ -207,7 +234,7 @@
 }
 
 SkiaInterpolator::SkiaInterpolator(int elemCount, int frameCount) {
-    SkASSERT(elemCount > 0);
+    LOG_FATAL_IF(elemCount <= 0);
     this->reset(elemCount, frameCount);
 }
 
@@ -221,21 +248,19 @@
     fValues = (float*)((char*)fStorage + sizeof(SkTimeCode) * frameCount);
 }
 
-#define SK_Fixed1Third (SK_Fixed1 / 3)
-#define SK_Fixed2Third (SK_Fixed1 * 2 / 3)
-
 static const float gIdentityBlend[4] = {0.33333333f, 0.33333333f, 0.66666667f, 0.66666667f};
 
 bool SkiaInterpolator::setKeyFrame(int index, SkMSec time, const float values[],
                                    const float blend[4]) {
-    SkASSERT(values != nullptr);
+    LOG_FATAL_IF(values == nullptr);
 
     if (blend == nullptr) {
         blend = gIdentityBlend;
     }
 
-    bool success = ~index == SkTSearch<SkMSec>(&fTimes->fTime, index, time, sizeof(SkTimeCode));
-    SkASSERT(success);
+    // Verify the time should go after all the frames before index
+    bool success = ~index == SkiaInterpolatorBase::binarySearch(fTimes, index, time);
+    LOG_FATAL_IF(!success);
     if (success) {
         SkTimeCode* timeCode = &fTimes[index];
         timeCode->fTime = time;
@@ -257,7 +282,7 @@
         if (exact) {
             memcpy(values, nextSrc, fElemCount * sizeof(float));
         } else {
-            SkASSERT(index > 0);
+            LOG_FATAL_IF(index <= 0);
 
             const float* prevSrc = nextSrc - fElemCount;
 
diff --git a/libs/hwui/SkiaInterpolator.h b/libs/hwui/SkiaInterpolator.h
index 9422cb5..62e6c1e 100644
--- a/libs/hwui/SkiaInterpolator.h
+++ b/libs/hwui/SkiaInterpolator.h
@@ -68,14 +68,16 @@
     enum Flags { kMirror = 1, kReset = 2, kHasBlend = 4 };
     static float ComputeRelativeT(uint32_t time, uint32_t prevTime, uint32_t nextTime,
                                   const float blend[4] = nullptr);
-    int16_t fFrameCount;
-    uint8_t fElemCount;
-    uint8_t fFlags;
-    float fRepeat;
     struct SkTimeCode {
         uint32_t fTime;
         float fBlend[4];
     };
+    static int binarySearch(const SkTimeCode* arr, int count, uint32_t target);
+
+    int16_t fFrameCount;
+    uint8_t fElemCount;
+    uint8_t fFlags;
+    float fRepeat;
     SkTimeCode* fTimes;  // pointer into fStorage
     void* fStorage;
 };
diff --git a/libs/hwui/hwui/Bitmap.cpp b/libs/hwui/hwui/Bitmap.cpp
index b3eaa0c..f46d3ae 100644
--- a/libs/hwui/hwui/Bitmap.cpp
+++ b/libs/hwui/hwui/Bitmap.cpp
@@ -39,6 +39,8 @@
 #include <SkColor.h>
 #include <SkEncodedImageFormat.h>
 #include <SkHighContrastFilter.h>
+#include <SkImage.h>
+#include <SkImageAndroid.h>
 #include <SkImageEncoder.h>
 #include <SkImagePriv.h>
 #include <SkJpegGainmapEncoder.h>
@@ -263,7 +265,8 @@
     mPixelStorage.hardware.buffer = buffer;
     AHardwareBuffer_acquire(buffer);
     setImmutable();  // HW bitmaps are always immutable
-    mImage = SkImage::MakeFromAHardwareBuffer(buffer, mInfo.alphaType(), mInfo.refColorSpace());
+    mImage = SkImages::DeferredFromAHardwareBuffer(buffer, mInfo.alphaType(),
+                                                   mInfo.refColorSpace());
 }
 #endif
 
@@ -370,7 +373,12 @@
         // Note we don't cache in this case, because the raster image holds a pointer to this Bitmap
         // internally and ~Bitmap won't be invoked.
         // TODO: refactor Bitmap to not derive from SkPixelRef, which would allow caching here.
+#ifdef __ANDROID__
+        // pinnable images are only supported with the Ganesh GPU backend compiled in.
+        image = SkImages::PinnableRasterFromBitmap(skiaBitmap);
+#else
         image = SkMakeImageFromRasterBitmap(skiaBitmap, kNever_SkCopyPixelsMode);
+#endif
     }
     return image;
 }
diff --git a/libs/hwui/jni/CreateJavaOutputStreamAdaptor.cpp b/libs/hwui/jni/CreateJavaOutputStreamAdaptor.cpp
index 15e529e..a66d3b8 100644
--- a/libs/hwui/jni/CreateJavaOutputStreamAdaptor.cpp
+++ b/libs/hwui/jni/CreateJavaOutputStreamAdaptor.cpp
@@ -1,11 +1,11 @@
 #include "CreateJavaOutputStreamAdaptor.h"
 #include "SkData.h"
-#include "SkMalloc.h"
 #include "SkRefCnt.h"
 #include "SkStream.h"
 #include "SkTypes.h"
 #include "Utils.h"
 
+#include <cstdlib>
 #include <nativehelper/JNIHelp.h>
 #include <log/log.h>
 #include <memory>
@@ -177,6 +177,10 @@
     return JavaInputStreamAdaptor::Create(env, stream, storage, swallowExceptions);
 }
 
+static void free_pointer_skproc(const void* ptr, void*) {
+    free((void*)ptr);
+}
+
 sk_sp<SkData> CopyJavaInputStream(JNIEnv* env, jobject inputStream, jbyteArray storage) {
     std::unique_ptr<SkStream> stream(CreateJavaInputStreamAdaptor(env, inputStream, storage));
     if (!stream) {
@@ -186,19 +190,31 @@
     size_t bufferSize = 4096;
     size_t streamLen = 0;
     size_t len;
-    char* data = (char*)sk_malloc_throw(bufferSize);
+    char* data = (char*)malloc(bufferSize);
+    LOG_ALWAYS_FATAL_IF(!data);
 
     while ((len = stream->read(data + streamLen,
                                bufferSize - streamLen)) != 0) {
         streamLen += len;
         if (streamLen == bufferSize) {
             bufferSize *= 2;
-            data = (char*)sk_realloc_throw(data, bufferSize);
+            data = (char*)realloc(data, bufferSize);
+            LOG_ALWAYS_FATAL_IF(!data);
         }
     }
-    data = (char*)sk_realloc_throw(data, streamLen);
-
-    return SkData::MakeFromMalloc(data, streamLen);
+    if (streamLen == 0) {
+        // realloc with size 0 is unspecified behavior in C++11
+        free(data);
+        data = nullptr;
+    } else {
+        // Trim down the buffer to the actual size of the data.
+        LOG_FATAL_IF(streamLen > bufferSize);
+        data = (char*)realloc(data, streamLen);
+        LOG_ALWAYS_FATAL_IF(!data);
+    }
+    // Just in case sk_free differs from free, we ask Skia to use
+    // free to cleanup the buffer that SkData wraps.
+    return SkData::MakeWithProc(data, streamLen, free_pointer_skproc, nullptr);
 }
 
 ///////////////////////////////////////////////////////////////////////////////
diff --git a/libs/hwui/jni/MaskFilter.cpp b/libs/hwui/jni/MaskFilter.cpp
index 048ce02..cbd4520 100644
--- a/libs/hwui/jni/MaskFilter.cpp
+++ b/libs/hwui/jni/MaskFilter.cpp
@@ -1,6 +1,5 @@
 #include "GraphicsJNI.h"
 #include "SkMaskFilter.h"
-#include "SkBlurMask.h"
 #include "SkBlurMaskFilter.h"
 #include "SkBlurTypes.h"
 #include "SkTableMaskFilter.h"
@@ -11,6 +10,13 @@
     }
 }
 
+// From https://skia.googlesource.com/skia/+/d74c99a3cd5eef5f16b2eb226e6b45fe523c8552/src/core/SkBlurMask.cpp#28
+static constexpr float kBLUR_SIGMA_SCALE = 0.57735f;
+
+static float convertRadiusToSigma(float radius) {
+    return radius > 0 ? kBLUR_SIGMA_SCALE * radius + 0.5f : 0.0f;
+}
+
 class SkMaskFilterGlue {
 public:
     static void destructor(JNIEnv* env, jobject, jlong filterHandle) {
@@ -19,7 +25,7 @@
     }
 
     static jlong createBlur(JNIEnv* env, jobject, jfloat radius, jint blurStyle) {
-        SkScalar sigma = SkBlurMask::ConvertRadiusToSigma(radius);
+        SkScalar sigma = convertRadiusToSigma(radius);
         SkMaskFilter* filter = SkMaskFilter::MakeBlur((SkBlurStyle)blurStyle, sigma).release();
         ThrowIAE_IfNull(env, filter);
         return reinterpret_cast<jlong>(filter);
@@ -34,7 +40,7 @@
             direction[i] = values[i];
         }
 
-        SkScalar sigma = SkBlurMask::ConvertRadiusToSigma(radius);
+        SkScalar sigma = convertRadiusToSigma(radius);
         SkMaskFilter* filter =  SkBlurMaskFilter::MakeEmboss(sigma,
                 direction, ambient, specular).release();
         ThrowIAE_IfNull(env, filter);
diff --git a/libs/hwui/jni/android_graphics_HardwareRenderer.cpp b/libs/hwui/jni/android_graphics_HardwareRenderer.cpp
index 6a7411f..de5c86a 100644
--- a/libs/hwui/jni/android_graphics_HardwareRenderer.cpp
+++ b/libs/hwui/jni/android_graphics_HardwareRenderer.cpp
@@ -27,7 +27,7 @@
 #include <SkColorSpace.h>
 #include <SkData.h>
 #include <SkImage.h>
-#include <SkImagePriv.h>
+#include <SkImageAndroid.h>
 #include <SkPicture.h>
 #include <SkPixmap.h>
 #include <SkSerialProcs.h>
@@ -473,7 +473,7 @@
         // actually cross thread boundaries here, make a copy so it's immutable proper
         if (bitmap && !bitmap->isImmutable()) {
             ATRACE_NAME("Copying mutable bitmap");
-            return SkImage::MakeFromBitmap(*bitmap);
+            return SkImages::RasterFromBitmap(*bitmap);
         }
         if (img->isTextureBacked()) {
             ATRACE_NAME("Readback of texture image");
@@ -493,7 +493,7 @@
                 return sk_ref_sp(img);
             }
             bm.setImmutable();
-            return SkMakeImageFromRasterBitmap(bm, kNever_SkCopyPixelsMode);
+            return SkImages::PinnableRasterFromBitmap(bm);
         }
         return sk_ref_sp(img);
     }
diff --git a/libs/hwui/pipeline/skia/ShaderCache.h b/libs/hwui/pipeline/skia/ShaderCache.h
index f5506d6..0492d70 100644
--- a/libs/hwui/pipeline/skia/ShaderCache.h
+++ b/libs/hwui/pipeline/skia/ShaderCache.h
@@ -24,6 +24,7 @@
 #include <string>
 #include <vector>
 
+class GrDirectContext;
 class SkData;
 
 namespace android {
diff --git a/libs/hwui/pipeline/skia/SkiaPipeline.cpp b/libs/hwui/pipeline/skia/SkiaPipeline.cpp
index 8ea71f1..76d5305 100644
--- a/libs/hwui/pipeline/skia/SkiaPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaPipeline.cpp
@@ -21,9 +21,9 @@
 #include <SkColorSpace.h>
 #include <SkData.h>
 #include <SkImage.h>
+#include <SkImageAndroid.h>
 #include <SkImageEncoder.h>
 #include <SkImageInfo.h>
-#include <SkImagePriv.h>
 #include <SkMatrix.h>
 #include <SkMultiPictureDocument.h>
 #include <SkOverdrawCanvas.h>
@@ -75,7 +75,7 @@
         return false;
     }
     for (SkImage* image : mutableImages) {
-        if (SkImage_pinAsTexture(image, mRenderThread.getGrContext())) {
+        if (skgpu::ganesh::PinAsTexture(mRenderThread.getGrContext(), image)) {
             mPinnedImages.emplace_back(sk_ref_sp(image));
         } else {
             return false;
@@ -86,7 +86,7 @@
 
 void SkiaPipeline::unpinImages() {
     for (auto& image : mPinnedImages) {
-        SkImage_unpinAsTexture(image.get(), mRenderThread.getGrContext());
+        skgpu::ganesh::UnpinTexture(mRenderThread.getGrContext(), image.get());
     }
     mPinnedImages.clear();
 }
@@ -222,8 +222,8 @@
         ATRACE_FORMAT("Bitmap#prepareToDraw %dx%d", bitmap->width(), bitmap->height());
         auto image = bitmap->makeImage();
         if (image.get()) {
-            SkImage_pinAsTexture(image.get(), context);
-            SkImage_unpinAsTexture(image.get(), context);
+            skgpu::ganesh::PinAsTexture(context, image.get());
+            skgpu::ganesh::UnpinTexture(context, image.get());
             // A submit is necessary as there may not be a frame coming soon, so without a call
             // to submit these texture uploads can just sit in the queue building up until
             // we run out of RAM
diff --git a/libs/hwui/pipeline/skia/VkInteropFunctorDrawable.cpp b/libs/hwui/pipeline/skia/VkInteropFunctorDrawable.cpp
index e168a7b..12c14e4 100644
--- a/libs/hwui/pipeline/skia/VkInteropFunctorDrawable.cpp
+++ b/libs/hwui/pipeline/skia/VkInteropFunctorDrawable.cpp
@@ -34,6 +34,8 @@
 #include "utils/TimeUtils.h"
 
 #include <SkBlendMode.h>
+#include <SkImage.h>
+#include <SkImageAndroid.h>
 
 namespace android {
 namespace uirenderer {
@@ -181,9 +183,9 @@
     // drawing into the offscreen surface, so we need to reset it here.
     canvas->resetMatrix();
 
-    auto functorImage = SkImage::MakeFromAHardwareBuffer(mFrameBuffer.get(), kPremul_SkAlphaType,
-                                                         canvas->imageInfo().refColorSpace(),
-                                                         kBottomLeft_GrSurfaceOrigin);
+    auto functorImage = SkImages::DeferredFromAHardwareBuffer(
+        mFrameBuffer.get(), kPremul_SkAlphaType, canvas->imageInfo().refColorSpace(),
+        kBottomLeft_GrSurfaceOrigin);
     canvas->drawImage(functorImage, 0, 0, SkSamplingOptions(), &paint);
     canvas->restore();
 }
diff --git a/libs/hwui/tests/unit/AutoBackendTextureReleaseTests.cpp b/libs/hwui/tests/unit/AutoBackendTextureReleaseTests.cpp
index 138b3efd..b8b3f0a 100644
--- a/libs/hwui/tests/unit/AutoBackendTextureReleaseTests.cpp
+++ b/libs/hwui/tests/unit/AutoBackendTextureReleaseTests.cpp
@@ -46,7 +46,7 @@
 
     EXPECT_EQ(1, TestUtils::getUsageCount(textureRelease));
 
-    // SkImage::MakeFromTexture should fail if given null GrDirectContext.
+    // SkImages::BorrowTextureFrom should fail if given null GrDirectContext.
     textureRelease->makeImage(buffer, HAL_DATASPACE_UNKNOWN, /*context = */ nullptr);
 
     EXPECT_EQ(1, TestUtils::getUsageCount(textureRelease));
diff --git a/libs/hwui/tests/unit/CacheManagerTests.cpp b/libs/hwui/tests/unit/CacheManagerTests.cpp
index 2b90bda..03a955c 100644
--- a/libs/hwui/tests/unit/CacheManagerTests.cpp
+++ b/libs/hwui/tests/unit/CacheManagerTests.cpp
@@ -20,7 +20,7 @@
 #include "renderthread/EglManager.h"
 #include "tests/common/TestUtils.h"
 
-#include <SkImagePriv.h>
+#include <SkImageAndroid.h>
 #include "include/gpu/GpuTypes.h" // from Skia
 
 using namespace android;
@@ -57,9 +57,8 @@
 
     // create an image and pin it so that we have something with a unique key in the cache
     sk_sp<Bitmap> bitmap = Bitmap::allocateHeapBitmap(SkImageInfo::MakeA8(width, height));
-    sk_sp<SkImage> image = bitmap->makeImage();
-    ASSERT_TRUE(SkImage_pinAsTexture(image.get(), grContext));
-
+    sk_sp<SkImage> image = bitmap->makeImage(); // calls skgpu::ganesh::PinAsTexture under the hood.
+    ASSERT_TRUE(skgpu::ganesh::PinAsTexture(grContext, image.get()));
     // attempt to trim all memory while we still hold strong refs
     renderThread.cacheManager().trimMemory(TrimLevel::COMPLETE);
     ASSERT_TRUE(0 == grContext->getResourceCachePurgeableBytes());
@@ -71,7 +70,7 @@
     }
 
     // unpin the image which should add a unique purgeable key to the cache
-    SkImage_unpinAsTexture(image.get(), grContext);
+    skgpu::ganesh::UnpinTexture(grContext, image.get());
 
     // verify that we have enough purgeable bytes
     const size_t purgeableBytes = grContext->getResourceCachePurgeableBytes();
diff --git a/libs/hwui/tests/unit/DeferredLayerUpdaterTests.cpp b/libs/hwui/tests/unit/DeferredLayerUpdaterTests.cpp
index 0c389bfe8..cfa18ae 100644
--- a/libs/hwui/tests/unit/DeferredLayerUpdaterTests.cpp
+++ b/libs/hwui/tests/unit/DeferredLayerUpdaterTests.cpp
@@ -40,7 +40,7 @@
     // push the deferred updates to the layer
     SkBitmap bitmap;
     bitmap.allocN32Pixels(16, 16);
-    sk_sp<SkImage> layerImage = SkImage::MakeFromBitmap(bitmap);
+    sk_sp<SkImage> layerImage = SkImages::RasterFromBitmap(bitmap);
     layerUpdater->updateLayer(true, layerImage, 0, SkRect::MakeEmpty());
 
     // the backing layer should now have all the properties applied.
diff --git a/location/java/android/location/ILocationManager.aidl b/location/java/android/location/ILocationManager.aidl
index 42b72d4..72761ef 100644
--- a/location/java/android/location/ILocationManager.aidl
+++ b/location/java/android/location/ILocationManager.aidl
@@ -98,12 +98,16 @@
     void addGnssAntennaInfoListener(in IGnssAntennaInfoListener listener, String packageName, @nullable String attributionTag, String listenerId);
     void removeGnssAntennaInfoListener(in IGnssAntennaInfoListener listener);
 
+    @EnforcePermission("INTERACT_ACROSS_USERS")
     void addProviderRequestListener(in IProviderRequestListener listener);
     void removeProviderRequestListener(in IProviderRequestListener listener);
 
     int getGnssBatchSize();
+    @EnforcePermission("LOCATION_HARDWARE")
     void startGnssBatch(long periodNanos, in ILocationListener listener, String packageName, @nullable String attributionTag, String listenerId);
+    @EnforcePermission("LOCATION_HARDWARE")
     void flushGnssBatch();
+    @EnforcePermission("LOCATION_HARDWARE")
     void stopGnssBatch();
 
     boolean hasProvider(String provider);
@@ -111,7 +115,9 @@
     List<String> getProviders(in Criteria criteria, boolean enabledOnly);
     String getBestProvider(in Criteria criteria, boolean enabledOnly);
     ProviderProperties getProviderProperties(String provider);
+    @EnforcePermission("READ_DEVICE_CONFIG")
     boolean isProviderPackage(@nullable String provider, String packageName, @nullable String attributionTag);
+    @EnforcePermission("READ_DEVICE_CONFIG")
     List<String> getProviderPackages(String provider);
 
     @EnforcePermission("LOCATION_HARDWARE")
diff --git a/location/java/android/location/altitude/AltitudeConverter.java b/location/java/android/location/altitude/AltitudeConverter.java
index eb73b69..3dc024ef 100644
--- a/location/java/android/location/altitude/AltitudeConverter.java
+++ b/location/java/android/location/altitude/AltitudeConverter.java
@@ -31,6 +31,14 @@
 /**
  * Converts altitudes reported above the World Geodetic System 1984 (WGS84) reference ellipsoid
  * into ones above Mean Sea Level.
+ *
+ * <p>Reference:
+ *
+ * <pre>
+ * Brian Julian and Michael Angermann.
+ * "Resource efficient and accurate altitude conversion to Mean Sea Level."
+ * To appear in 2023 IEEE/ION Position, Location and Navigation Symposium (PLANS).
+ * </pre>
  */
 public final class AltitudeConverter {
 
@@ -81,27 +89,47 @@
         long s2CellId = S2CellIdUtils.fromLatLngDegrees(location.getLatitude(),
                 location.getLongitude());
 
-        // (0,0) cell.
+        // Cell-space properties and coordinates.
+        int sizeIj = 1 << (S2CellIdUtils.MAX_LEVEL - params.mapS2Level);
+        int maxIj = 1 << S2CellIdUtils.MAX_LEVEL;
         long s0 = S2CellIdUtils.getParent(s2CellId, params.mapS2Level);
+        int f0 = S2CellIdUtils.getFace(s2CellId);
+        int i0 = S2CellIdUtils.getI(s2CellId);
+        int j0 = S2CellIdUtils.getJ(s2CellId);
+        int i1 = i0 + sizeIj;
+        int j1 = j0 + sizeIj;
+
+        // Non-boundary region calculation - simplest and most common case.
+        if (i1 < maxIj && j1 < maxIj) {
+            return new long[]{
+                    s0,
+                    S2CellIdUtils.getParent(S2CellIdUtils.fromFij(f0, i1, j0), params.mapS2Level),
+                    S2CellIdUtils.getParent(S2CellIdUtils.fromFij(f0, i0, j1), params.mapS2Level),
+                    S2CellIdUtils.getParent(S2CellIdUtils.fromFij(f0, i1, j1), params.mapS2Level)
+            };
+        }
+
+        // Boundary region calculation.
         long[] edgeNeighbors = new long[4];
         S2CellIdUtils.getEdgeNeighbors(s0, edgeNeighbors);
-
-        // (1,0) cell.
-        int i1 = S2CellIdUtils.getI(s2CellId) > S2CellIdUtils.getI(s0) ? -1 : 1;
-        long s1 = edgeNeighbors[i1 + 2];
-
-        // (0,1) cell.
-        int i2 = S2CellIdUtils.getJ(s2CellId) > S2CellIdUtils.getJ(s0) ? 1 : -1;
-        long s2 = edgeNeighbors[i2 + 1];
-
-        // (1,1) cell.
-        S2CellIdUtils.getEdgeNeighbors(s1, edgeNeighbors);
-        long s3 = 0;
-        for (int i = 0; i < edgeNeighbors.length; i++) {
-            if (edgeNeighbors[i] == s0) {
-                int i3 = (i + i1 * i2 + edgeNeighbors.length) % edgeNeighbors.length;
-                s3 = edgeNeighbors[i3] == s2 ? 0 : edgeNeighbors[i3];
-                break;
+        long s1 = edgeNeighbors[1];
+        long s2 = edgeNeighbors[2];
+        long s3;
+        if (f0 % 2 == 1) {
+            S2CellIdUtils.getEdgeNeighbors(s1, edgeNeighbors);
+            if (i1 < maxIj) {
+                s3 = edgeNeighbors[2];
+            } else {
+                s3 = s1;
+                s1 = edgeNeighbors[1];
+            }
+        } else {
+            S2CellIdUtils.getEdgeNeighbors(s2, edgeNeighbors);
+            if (j1 < maxIj) {
+                s3 = edgeNeighbors[1];
+            } else {
+                s3 = s2;
+                s2 = edgeNeighbors[3];
             }
         }
 
@@ -118,13 +146,12 @@
      * Mean Sea Level altitude accuracy is added if the {@code location} has a valid vertical
      * accuracy; otherwise, does not add a corresponding accuracy.
      */
-    private static void addMslAltitude(@NonNull MapParamsProto params, @NonNull long[] s2CellIds,
+    private static void addMslAltitude(@NonNull MapParamsProto params,
             @NonNull double[] geoidHeightsMeters, @NonNull Location location) {
-        long s0 = s2CellIds[0];
         double h0 = geoidHeightsMeters[0];
         double h1 = geoidHeightsMeters[1];
         double h2 = geoidHeightsMeters[2];
-        double h3 = s2CellIds[3] == 0 ? h0 : geoidHeightsMeters[3];
+        double h3 = geoidHeightsMeters[3];
 
         // Bilinear interpolation on an S2 square of size equal to that of a map cell. wi and wj
         // are the normalized [0,1] weights in the i and j directions, respectively, allowing us to
@@ -132,8 +159,8 @@
         long s2CellId = S2CellIdUtils.fromLatLngDegrees(location.getLatitude(),
                 location.getLongitude());
         double sizeIj = 1 << (S2CellIdUtils.MAX_LEVEL - params.mapS2Level);
-        double wi = Math.abs(S2CellIdUtils.getI(s2CellId) - S2CellIdUtils.getI(s0)) / sizeIj;
-        double wj = Math.abs(S2CellIdUtils.getJ(s2CellId) - S2CellIdUtils.getJ(s0)) / sizeIj;
+        double wi = (S2CellIdUtils.getI(s2CellId) % sizeIj) / sizeIj;
+        double wj = (S2CellIdUtils.getJ(s2CellId) % sizeIj) / sizeIj;
         double offsetMeters = h0 + (h1 - h0) * wi + (h2 - h0) * wj + (h3 - h1 - h2 + h0) * wi * wj;
 
         location.setMslAltitudeMeters(location.getAltitude() - offsetMeters);
@@ -167,7 +194,7 @@
         MapParamsProto params = GeoidHeightMap.getParams(context);
         long[] s2CellIds = findMapSquare(params, location);
         double[] geoidHeightsMeters = mGeoidHeightMap.readGeoidHeights(params, context, s2CellIds);
-        addMslAltitude(params, s2CellIds, geoidHeightsMeters, location);
+        addMslAltitude(params, geoidHeightsMeters, location);
     }
 
     /**
@@ -190,7 +217,7 @@
             return false;
         }
 
-        addMslAltitude(params, s2CellIds, geoidHeightsMeters, location);
+        addMslAltitude(params, geoidHeightsMeters, location);
         return true;
     }
 }
diff --git a/location/java/com/android/internal/location/altitude/GeoidHeightMap.java b/location/java/com/android/internal/location/altitude/GeoidHeightMap.java
index 73b6ab5..8067050 100644
--- a/location/java/com/android/internal/location/altitude/GeoidHeightMap.java
+++ b/location/java/com/android/internal/location/altitude/GeoidHeightMap.java
@@ -99,8 +99,8 @@
 
     /**
      * Adds to {@code values} values in the unit interval [0, 1] for the map cells identified by
-     * {@code s2CellIds}. Returns true if values are present for all non-zero IDs; otherwise,
-     * returns false and adds NaNs for absent values.
+     * {@code s2CellIds}. Returns true if values are present for all IDs; otherwise, returns false
+     * and adds NaNs for absent values.
      */
     private static boolean getUnitIntervalValues(@NonNull MapParamsProto params,
             @NonNull TileFunction tileFunction,
@@ -109,10 +109,8 @@
 
         S2TileProto[] tiles = new S2TileProto[len];
         for (int i = 0; i < len; i++) {
-            if (s2CellIds[i] != 0) {
-                long cacheKey = getCacheKey(params, s2CellIds[i]);
-                tiles[i] = tileFunction.getTile(cacheKey);
-            }
+            long cacheKey = getCacheKey(params, s2CellIds[i]);
+            tiles[i] = tileFunction.getTile(cacheKey);
             values[i] = Double.NaN;
         }
 
@@ -128,9 +126,6 @@
 
         boolean allFound = true;
         for (int i = 0; i < len; i++) {
-            if (s2CellIds[i] == 0) {
-                continue;
-            }
             if (Double.isNaN(values[i])) {
                 allFound = false;
             } else {
@@ -195,7 +190,7 @@
         }
 
         for (int i = tileIndex; i < tiles.length; i++) {
-            if (s2CellIds[i] == 0 || tiles[i] != tiles[tileIndex]) {
+            if (tiles[i] != tiles[tileIndex]) {
                 continue;
             }
 
@@ -226,15 +221,14 @@
     private static void validate(@NonNull MapParamsProto params, @NonNull long[] s2CellIds) {
         Preconditions.checkArgument(s2CellIds.length == 4);
         for (long s2CellId : s2CellIds) {
-            Preconditions.checkArgument(
-                    s2CellId == 0 || S2CellIdUtils.getLevel(s2CellId) == params.mapS2Level);
+            Preconditions.checkArgument(S2CellIdUtils.getLevel(s2CellId) == params.mapS2Level);
         }
     }
 
     /**
      * Returns the geoid heights in meters associated with the map cells identified by
-     * {@code s2CellIds}. Throws an {@link IOException} if a geoid height cannot be calculated for a
-     * non-zero ID.
+     * {@code s2CellIds}. Throws an {@link IOException} if a geoid height cannot be calculated for
+     * an ID.
      */
     @NonNull
     public double[] readGeoidHeights(@NonNull MapParamsProto params, @NonNull Context context,
@@ -254,8 +248,8 @@
 
     /**
      * Same as {@link #readGeoidHeights(MapParamsProto, Context, long[])} except that data will not
-     * be loaded from raw assets. Returns the heights if present for all non-zero IDs; otherwise,
-     * returns null.
+     * be loaded from raw assets. Returns the heights if present for all IDs; otherwise, returns
+     * null.
      */
     @Nullable
     public double[] readGeoidHeights(@NonNull MapParamsProto params, @NonNull long[] s2CellIds) {
@@ -269,8 +263,8 @@
 
     /**
      * Adds to {@code heightsMeters} the geoid heights in meters associated with the map cells
-     * identified by {@code s2CellIds}. Returns true if heights are present for all non-zero IDs;
-     * otherwise, returns false and adds NaNs for absent heights.
+     * identified by {@code s2CellIds}. Returns true if heights are present for all IDs; otherwise,
+     * returns false and adds NaNs for absent heights.
      */
     private boolean getGeoidHeights(@NonNull MapParamsProto params,
             @NonNull TileFunction tileFunction, @NonNull long[] s2CellIds,
@@ -292,9 +286,6 @@
         // Enable batch loading by finding all cache keys upfront.
         long[] cacheKeys = new long[len];
         for (int i = 0; i < len; i++) {
-            if (s2CellIds[i] == 0) {
-                continue;
-            }
             cacheKeys[i] = getCacheKey(params, s2CellIds[i]);
         }
 
@@ -302,7 +293,7 @@
         S2TileProto[] loadedTiles = new S2TileProto[len];
         String[] diskTokens = new String[len];
         for (int i = 0; i < len; i++) {
-            if (s2CellIds[i] == 0 || diskTokens[i] != null) {
+            if (diskTokens[i] != null) {
                 continue;
             }
             loadedTiles[i] = mCacheTiles.get(cacheKeys[i]);
@@ -319,7 +310,7 @@
 
         // Attempt to load tiles from disk.
         for (int i = 0; i < len; i++) {
-            if (s2CellIds[i] == 0 || loadedTiles[i] != null) {
+            if (loadedTiles[i] != null) {
                 continue;
             }
 
diff --git a/location/java/com/android/internal/location/altitude/S2CellIdUtils.java b/location/java/com/android/internal/location/altitude/S2CellIdUtils.java
index 5f11387..08bcda4 100644
--- a/location/java/com/android/internal/location/altitude/S2CellIdUtils.java
+++ b/location/java/com/android/internal/location/altitude/S2CellIdUtils.java
@@ -70,6 +70,34 @@
         return fromLatLngRadians(Math.toRadians(latDegrees), Math.toRadians(lngDegrees));
     }
 
+    /** Returns the leaf S2 cell ID of the specified (face, i, j) coordinate. */
+    public static long fromFij(int face, int i, int j) {
+        int bits = (face & SWAP_MASK);
+        // Update most significant bits.
+        long msb = ((long) face) << (POS_BITS - 33);
+        for (int k = 7; k >= 4; --k) {
+            bits = lookupBits(i, j, k, bits);
+            msb = updateBits(msb, k, bits);
+            bits = maskBits(bits);
+        }
+        // Update least significant bits.
+        long lsb = 0;
+        for (int k = 3; k >= 0; --k) {
+            bits = lookupBits(i, j, k, bits);
+            lsb = updateBits(lsb, k, bits);
+            bits = maskBits(bits);
+        }
+        return (((msb << 32) + lsb) << 1) + 1;
+    }
+
+    /**
+     * Returns the face of the specified S2 cell. The returned face is in [0, 5] for valid S2 cell
+     * IDs. Behavior is undefined for invalid S2 cell IDs.
+     */
+    public static int getFace(long s2CellId) {
+        return (int) (s2CellId >>> POS_BITS);
+    }
+
     /**
      * Returns the ID of the parent of the specified S2 cell at the specified parent level.
      * Behavior is undefined for invalid S2 cell IDs or parent levels not in
@@ -219,26 +247,6 @@
         return fromFij(face, i, j);
     }
 
-    /** Returns the leaf S2 cell ID of the specified (face, i, j) coordinate. */
-    private static long fromFij(int face, int i, int j) {
-        int bits = (face & SWAP_MASK);
-        // Update most significant bits.
-        long msb = ((long) face) << (POS_BITS - 33);
-        for (int k = 7; k >= 4; --k) {
-            bits = lookupBits(i, j, k, bits);
-            msb = updateBits(msb, k, bits);
-            bits = maskBits(bits);
-        }
-        // Update least significant bits.
-        long lsb = 0;
-        for (int k = 3; k >= 0; --k) {
-            bits = lookupBits(i, j, k, bits);
-            lsb = updateBits(lsb, k, bits);
-            bits = maskBits(bits);
-        }
-        return (((msb << 32) + lsb) << 1) + 1;
-    }
-
     private static long fromFijWrap(int face, int i, int j) {
         double u = iToU(i);
         double v = jToV(j);
@@ -314,10 +322,6 @@
         return bits & (SWAP_MASK | INVERT_MASK);
     }
 
-    private static int getFace(long s2CellId) {
-        return (int) (s2CellId >>> POS_BITS);
-    }
-
     private static boolean isLeaf(long s2CellId) {
         return ((int) s2CellId & LEAF_MASK) != 0;
     }
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index f9d4efe..b251468 100644
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -221,6 +221,7 @@
 
     boolean isSurroundFormatEnabled(int audioFormat);
 
+    @EnforcePermission("WRITE_SETTINGS")
     boolean setEncodedSurroundMode(int mode);
 
     int getEncodedSurroundMode(int targetSdkVersion);
@@ -254,6 +255,7 @@
 
     void forceVolumeControlStream(int streamType, IBinder cb);
 
+    @EnforcePermission("REMOTE_AUDIO_PLAYBACK")
     void setRingtonePlayer(IRingtonePlayer player);
     IRingtonePlayer getRingtonePlayer();
     int getUiSoundsStreamType();
@@ -358,6 +360,7 @@
 
     oneway void playerHasOpPlayAudio(in int piid, in boolean hasOpPlayAudio);
 
+    @EnforcePermission("BLUETOOTH_STACK")
     void handleBluetoothActiveDeviceChanged(in BluetoothDevice newDevice,
             in BluetoothDevice previousDevice, in BluetoothProfileConnectionInfo info);
 
diff --git a/media/java/android/media/IRingtonePlayer.aidl b/media/java/android/media/IRingtonePlayer.aidl
index 5a7ff7f..97cc1a8 100644
--- a/media/java/android/media/IRingtonePlayer.aidl
+++ b/media/java/android/media/IRingtonePlayer.aidl
@@ -30,11 +30,13 @@
     @UnsupportedAppUsage
     oneway void play(IBinder token, in Uri uri, in AudioAttributes aa, float volume, boolean looping);
     oneway void playWithVolumeShaping(IBinder token, in Uri uri, in AudioAttributes aa,
-        float volume, boolean looping, in @nullable VolumeShaper.Configuration volumeShaperConfig);
+        float volume, boolean looping, boolean hapticGeneratorEnabled,
+        in @nullable VolumeShaper.Configuration volumeShaperConfig);
     oneway void stop(IBinder token);
     boolean isPlaying(IBinder token);
-    oneway void setPlaybackProperties(IBinder token, float volume, boolean looping,
-        boolean hapticGeneratorEnabled);
+    oneway void setLooping(IBinder token, boolean looping);
+    oneway void setVolume(IBinder token, float volume);
+    oneway void setHapticGeneratorEnabled(IBinder token, boolean hapticGeneratorEnabled);
 
     /** Used for Notification sound playback. */
     oneway void playAsync(in Uri uri, in UserHandle user, boolean looping, in AudioAttributes aa);
diff --git a/media/java/android/media/LocalRingtonePlayer.java b/media/java/android/media/LocalRingtonePlayer.java
new file mode 100644
index 0000000..4aa24af
--- /dev/null
+++ b/media/java/android/media/LocalRingtonePlayer.java
@@ -0,0 +1,250 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.content.res.AssetFileDescriptor;
+import android.media.audiofx.HapticGenerator;
+import android.net.Uri;
+import android.os.Trace;
+import android.util.Log;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Objects;
+
+/**
+ * Plays a ringtone on the local process.
+ * @hide
+ */
+public class LocalRingtonePlayer
+        implements Ringtone.RingtonePlayer, MediaPlayer.OnCompletionListener {
+    private static final String TAG = "LocalRingtonePlayer";
+
+    // keep references on active Ringtones until stopped or completion listener called.
+    private static final ArrayList<LocalRingtonePlayer> sActiveRingtones = new ArrayList<>();
+
+    private final MediaPlayer mMediaPlayer;
+    private final AudioAttributes mAudioAttributes;
+    private final Ringtone.Injectables mInjectables;
+    private final AudioManager mAudioManager;
+    private final VolumeShaper mVolumeShaper;
+    private HapticGenerator mHapticGenerator;
+
+    private LocalRingtonePlayer(@NonNull MediaPlayer mediaPlayer,
+            @NonNull AudioAttributes audioAttributes, @NonNull Ringtone.Injectables injectables,
+            @NonNull AudioManager audioManager, @Nullable HapticGenerator hapticGenerator,
+            @Nullable VolumeShaper volumeShaper) {
+        Objects.requireNonNull(mediaPlayer);
+        Objects.requireNonNull(audioAttributes);
+        Objects.requireNonNull(injectables);
+        Objects.requireNonNull(audioManager);
+        mMediaPlayer = mediaPlayer;
+        mAudioAttributes = audioAttributes;
+        mInjectables = injectables;
+        mAudioManager = audioManager;
+        mVolumeShaper = volumeShaper;
+        mHapticGenerator = hapticGenerator;
+    }
+
+    /**
+     * Creates a {@link LocalRingtonePlayer} for a Uri, returning null if the Uri can't be
+     * loaded in the local player.
+     */
+    @Nullable
+    static LocalRingtonePlayer create(@NonNull Context context,
+            @NonNull AudioManager audioManager, @NonNull Uri soundUri,
+            @NonNull AudioAttributes audioAttributes,
+            @NonNull Ringtone.Injectables injectables,
+            @Nullable VolumeShaper.Configuration volumeShaperConfig,
+            @Nullable AudioDeviceInfo preferredDevice, boolean initialHapticGeneratorEnabled,
+            boolean initialLooping, float initialVolume) {
+        Objects.requireNonNull(context);
+        Objects.requireNonNull(soundUri);
+        Objects.requireNonNull(audioAttributes);
+        Trace.beginSection("createLocalMediaPlayer");
+        MediaPlayer mediaPlayer = injectables.newMediaPlayer();
+        HapticGenerator hapticGenerator = null;
+        try {
+            mediaPlayer.setDataSource(context, soundUri);
+            mediaPlayer.setAudioAttributes(audioAttributes);
+            mediaPlayer.setPreferredDevice(preferredDevice);
+            mediaPlayer.setLooping(initialLooping);
+            mediaPlayer.setVolume(initialVolume);
+            if (initialHapticGeneratorEnabled) {
+                hapticGenerator = injectables.createHapticGenerator(mediaPlayer);
+                hapticGenerator.setEnabled(true);
+            }
+            VolumeShaper volumeShaper = null;
+            if (volumeShaperConfig != null) {
+                volumeShaper = mediaPlayer.createVolumeShaper(volumeShaperConfig);
+            }
+            mediaPlayer.prepare();
+            return new LocalRingtonePlayer(mediaPlayer, audioAttributes, injectables, audioManager,
+                    hapticGenerator, volumeShaper);
+        } catch (SecurityException | IOException e) {
+            if (hapticGenerator != null) {
+                hapticGenerator.release();
+            }
+            // volume shaper closes with media player
+            mediaPlayer.release();
+            return null;
+        } finally {
+            Trace.endSection();
+        }
+    }
+
+    /**
+     * Creates a {@link LocalRingtonePlayer} for an externally referenced file descriptor. This is
+     * intended for loading a fallback from an internal resource, rather than via a Uri.
+     */
+    @Nullable
+    static LocalRingtonePlayer createForFallback(
+            @NonNull AudioManager audioManager, @NonNull AssetFileDescriptor afd,
+            @NonNull AudioAttributes audioAttributes,
+            @NonNull Ringtone.Injectables injectables,
+            @Nullable VolumeShaper.Configuration volumeShaperConfig,
+            @Nullable AudioDeviceInfo preferredDevice,
+            boolean initialLooping, float initialVolume) {
+        // Haptic generator not supported for fallback.
+        Objects.requireNonNull(audioManager);
+        Objects.requireNonNull(afd);
+        Objects.requireNonNull(audioAttributes);
+        Trace.beginSection("createFallbackLocalMediaPlayer");
+
+        MediaPlayer mediaPlayer = injectables.newMediaPlayer();
+        try {
+            if (afd.getDeclaredLength() < 0) {
+                mediaPlayer.setDataSource(afd.getFileDescriptor());
+            } else {
+                mediaPlayer.setDataSource(afd.getFileDescriptor(),
+                        afd.getStartOffset(),
+                        afd.getDeclaredLength());
+            }
+            mediaPlayer.setAudioAttributes(audioAttributes);
+            mediaPlayer.setPreferredDevice(preferredDevice);
+            mediaPlayer.setLooping(initialLooping);
+            mediaPlayer.setVolume(initialVolume);
+            VolumeShaper volumeShaper = null;
+            if (volumeShaperConfig != null) {
+                volumeShaper = mediaPlayer.createVolumeShaper(volumeShaperConfig);
+            }
+            mediaPlayer.prepare();
+            return new LocalRingtonePlayer(mediaPlayer, audioAttributes, injectables, audioManager,
+                    /* hapticGenerator= */ null, volumeShaper);
+        } catch (SecurityException | IOException e) {
+            Log.e(TAG, "Failed to open fallback ringtone");
+            mediaPlayer.release();
+            return null;
+        } finally {
+            Trace.endSection();
+        }
+    }
+
+    @Override
+    public boolean play() {
+        // Play ringtones if stream volume is over 0 or if it is a haptic-only ringtone
+        // (typically because ringer mode is vibrate).
+        if (mAudioManager.getStreamVolume(AudioAttributes.toLegacyStreamType(mAudioAttributes))
+                == 0 && (mAudioAttributes.areHapticChannelsMuted() || !hasHapticChannels())) {
+            return true;  // Successfully played while muted.
+        }
+        synchronized (sActiveRingtones) {
+            sActiveRingtones.add(this);
+        }
+
+        mMediaPlayer.setOnCompletionListener(this);
+        mMediaPlayer.start();
+        if (mVolumeShaper != null) {
+            mVolumeShaper.apply(VolumeShaper.Operation.PLAY);
+        }
+        return true;
+    }
+
+    @Override
+    public boolean isPlaying() {
+        return mMediaPlayer.isPlaying();
+    }
+
+    @Override
+    public void stopAndRelease() {
+        synchronized (sActiveRingtones) {
+            sActiveRingtones.remove(this);
+        }
+        if (mHapticGenerator != null) {
+            mHapticGenerator.release();
+        }
+        mMediaPlayer.setOnCompletionListener(null);
+        mMediaPlayer.reset();
+        mMediaPlayer.release();
+    }
+
+    @Override
+    public void setPreferredDevice(@Nullable AudioDeviceInfo audioDeviceInfo) {
+        mMediaPlayer.setPreferredDevice(audioDeviceInfo);
+    }
+
+    @Override
+    public void setLooping(boolean looping) {
+        mMediaPlayer.setLooping(looping);
+    }
+
+    @Override
+    public void setHapticGeneratorEnabled(boolean enabled) {
+        if (enabled && mHapticGenerator == null) {
+            mHapticGenerator = mInjectables.createHapticGenerator(mMediaPlayer);
+        }
+        if (mHapticGenerator != null) {
+            mHapticGenerator.setEnabled(enabled);
+        }
+    }
+
+    @Override
+    public void setVolume(float volume) {
+        mMediaPlayer.setVolume(volume);
+    }
+
+    /**
+     * Same as AudioManager.hasHapticChannels except it assumes an already created ringtone.
+     * @hide
+     */
+    @Override
+    public boolean hasHapticChannels() {
+        // FIXME: support remote player, or internalize haptic channels support and remove entirely.
+        try {
+            Trace.beginSection("LocalRingtonePlayer.hasHapticChannels");
+            for (MediaPlayer.TrackInfo trackInfo : mMediaPlayer.getTrackInfo()) {
+                if (trackInfo.hasHapticChannels()) {
+                    return true;
+                }
+            }
+        } finally {
+            Trace.endSection();
+        }
+        return false;
+    }
+
+    @Override
+    public void onCompletion(MediaPlayer mp) {
+        synchronized (sActiveRingtones) {
+            sActiveRingtones.remove(this);
+        }
+        mp.setOnCompletionListener(null); // Help the Java GC: break the refcount cycle.
+    }
+}
diff --git a/media/java/android/media/OWNERS b/media/java/android/media/OWNERS
index 1f9a51d..6d6a9f8 100644
--- a/media/java/android/media/OWNERS
+++ b/media/java/android/media/OWNERS
@@ -8,4 +8,7 @@
 # go/android-fwk-media-solutions for info on areas of ownership.
 include platform/frameworks/av:/media/janitors/media_solutions_OWNERS
 
-per-file *Image* = file:/graphics/java/android/graphics/OWNERS
\ No newline at end of file
+per-file *Image* = file:/graphics/java/android/graphics/OWNERS
+
+# Haptics team also works on Ringtone
+per-file *Ringtone* = file:/services/core/java/com/android/server/vibrator/OWNERS
diff --git a/media/java/android/media/Ringtone.java b/media/java/android/media/Ringtone.java
index e78dc31..4be88fb 100644
--- a/media/java/android/media/Ringtone.java
+++ b/media/java/android/media/Ringtone.java
@@ -16,6 +16,8 @@
 
 package android.media;
 
+import android.annotation.IntDef;
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.ContentProvider;
@@ -27,16 +29,19 @@
 import android.media.audiofx.HapticGenerator;
 import android.net.Uri;
 import android.os.Binder;
-import android.os.Build;
+import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.Trace;
 import android.provider.MediaStore;
 import android.provider.MediaStore.MediaColumns;
 import android.provider.Settings;
 import android.util.Log;
+
 import com.android.internal.annotations.VisibleForTesting;
+
 import java.io.IOException;
-import java.util.ArrayList;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 
 /**
  * Ringtone provides a quick method for playing a ringtone, notification, or
@@ -49,7 +54,38 @@
  */
 public class Ringtone {
     private static final String TAG = "Ringtone";
-    private static final boolean LOGD = true;
+
+    /**
+     * The ringtone should only play sound. Any vibration is managed externally.
+     * @hide
+     */
+    public static final int MEDIA_SOUND = 1;
+    /**
+     * The ringtone should only play vibration. Any sound is managed externally.
+     * @hide
+     */
+    public static final int MEDIA_VIBRATION = 1 << 1;
+    /**
+     * The ringtone should play sound and vibration.
+     * @hide
+     */
+    public static final int MEDIA_SOUND_AND_VIBRATION = MEDIA_SOUND | MEDIA_VIBRATION;
+
+    // This is not a public value, because apps shouldn't enable "all" media - that wouldn't be
+    // safe if new media types were added.
+    static final int MEDIA_ALL = MEDIA_SOUND | MEDIA_VIBRATION;
+
+    /**
+     * Declares the types of media that this Ringtone is allowed to play.
+     * @hide
+     */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = "MEDIA_", value = {
+            MEDIA_SOUND,
+            MEDIA_VIBRATION,
+            MEDIA_SOUND_AND_VIBRATION,
+    })
+    public @interface RingtoneMedia {}
 
     private static final String[] MEDIA_COLUMNS = new String[] {
         MediaStore.Audio.Media._ID,
@@ -59,51 +95,52 @@
     private static final String MEDIA_SELECTION = MediaColumns.MIME_TYPE + " LIKE 'audio/%' OR "
             + MediaColumns.MIME_TYPE + " IN ('application/ogg', 'application/x-flac')";
 
-    // keep references on active Ringtones until stopped or completion listener called.
-    private static final ArrayList<Ringtone> sActiveRingtones = new ArrayList<Ringtone>();
-
     private final Context mContext;
     private final AudioManager mAudioManager;
     private VolumeShaper.Configuration mVolumeShaperConfig;
-    private VolumeShaper mVolumeShaper;
 
     /**
      * Flag indicating if we're allowed to fall back to remote playback using
-     * {@link #mRemotePlayer}. Typically this is false when we're the remote
+     * {@link #mRemoteRingtoneService}. Typically this is false when we're the remote
      * player and there is nobody else to delegate to.
      */
     private final boolean mAllowRemote;
-    private final IRingtonePlayer mRemotePlayer;
-    private final Binder mRemoteToken;
+    private final IRingtonePlayer mRemoteRingtoneService;
+    private final Injectables mInjectables;
 
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    private MediaPlayer mLocalPlayer;
-    private final MyOnCompletionListener mCompletionListener = new MyOnCompletionListener();
-    private HapticGenerator mHapticGenerator;
+    private final int mEnabledMedia;
 
-    @UnsupportedAppUsage
-    private Uri mUri;
+    private final Uri mUri;
     private String mTitle;
 
-    private AudioAttributes mAudioAttributes = new AudioAttributes.Builder()
-            .setUsage(AudioAttributes.USAGE_NOTIFICATION_RINGTONE)
-            .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
-            .build();
+    private AudioAttributes mAudioAttributes;
     private boolean mPreferBuiltinDevice;
+    private RingtonePlayer mActivePlayer;
     // playback properties, use synchronized with mPlaybackSettingsLock
     private boolean mIsLooping = false;
-    private float mVolume = 1.0f;
+    private float mVolume;
     private boolean mHapticGeneratorEnabled = false;
     private final Object mPlaybackSettingsLock = new Object();
 
-    /** {@hide} */
-    @UnsupportedAppUsage
-    public Ringtone(Context context, boolean allowRemote) {
-        mContext = context;
+    private Ringtone(Builder builder) {
+        mContext = builder.mContext;
+        mEnabledMedia = builder.mEnabledMedia;
+        mUri = builder.mUri;
+        mAudioAttributes = builder.mAudioAttributes;
+        mInjectables = builder.mInjectables;
+        mPreferBuiltinDevice = builder.mPreferBuiltinDevice;
+        mVolumeShaperConfig = builder.mVolumeShaperConfig;
+        mVolume = builder.mInitialSoundVolume;
+        mIsLooping = builder.mLooping;
         mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
-        mAllowRemote = allowRemote;
-        mRemotePlayer = allowRemote ? mAudioManager.getRingtonePlayer() : null;
-        mRemoteToken = allowRemote ? new Binder() : null;
+        mRemoteRingtoneService = builder.mAllowRemote ? mAudioManager.getRingtonePlayer() : null;
+        mAllowRemote = (mRemoteRingtoneService != null);
+    }
+
+    /** @hide */
+    @RingtoneMedia
+    public int getEnabledMedia() {
+        return mEnabledMedia;
     }
 
     /**
@@ -114,10 +151,15 @@
      */
     @Deprecated
     public void setStreamType(int streamType) {
-        PlayerBase.deprecateStreamTypeForPlayback(streamType, "Ringtone", "setStreamType()");
-        setAudioAttributes(new AudioAttributes.Builder()
+        setAudioAttributes(
+                getAudioAttributesForLegacyStreamType(streamType, "setStreamType()"));
+    }
+
+    private AudioAttributes getAudioAttributesForLegacyStreamType(int streamType, String originOp) {
+        PlayerBase.deprecateStreamTypeForPlayback(streamType, "Ringtone", originOp);
+        return new AudioAttributes.Builder()
                 .setInternalLegacyStreamType(streamType)
-                .build());
+                .build();
     }
 
     /**
@@ -138,23 +180,45 @@
      */
     public void setAudioAttributes(AudioAttributes attributes)
             throws IllegalArgumentException {
-        setAudioAttributesField(attributes);
-        // The audio attributes have to be set before the media player is prepared.
-        // Re-initialize it.
-        setUri(mUri, mVolumeShaperConfig);
-        createLocalMediaPlayer();
-    }
-
-    /**
-     * Same as {@link #setAudioAttributes(AudioAttributes)} except this one does not create
-     * the media player.
-     * @hide
-     */
-    public void setAudioAttributesField(@Nullable AudioAttributes attributes) {
+        // TODO: deprecate this method - it will be done with a builder.
         if (attributes == null) {
             throw new IllegalArgumentException("Invalid null AudioAttributes for Ringtone");
         }
         mAudioAttributes = attributes;
+        // Setting the audio attributes requires re-initializing the player.
+        if (mActivePlayer != null) {
+            // The audio attributes have to be set before the media player is prepared.
+            // Re-initialize it.
+            reinitializeActivePlayer();
+        }
+    }
+
+    /** @hide */
+    @VisibleForTesting
+    public boolean getPreferBuiltinDevice() {
+        return mPreferBuiltinDevice;
+    }
+
+    /** @hide */
+    @VisibleForTesting
+    public VolumeShaper.Configuration getVolumeShaperConfig() {
+        return mVolumeShaperConfig;
+    }
+
+    /**
+     * Returns whether this player is local only, or can defer to the remote player. The
+     * result may differ from the builder if there is no remote player available at all.
+     * @hide
+     */
+    @VisibleForTesting
+    public boolean isLocalOnly() {
+        return !mAllowRemote;
+    }
+
+    /** @hide */
+    @VisibleForTesting
+    public boolean isUsingRemotePlayer() {
+        return mActivePlayer instanceof RemoteRingtonePlayer;
     }
 
     /**
@@ -176,94 +240,82 @@
     }
 
     /**
-     * Sets the preferred device of the ringtong playback to the built-in device.
-     *
-     * @hide
-     */
-    public boolean preferBuiltinDevice(boolean enable) {
-        mPreferBuiltinDevice = enable;
-        if (mLocalPlayer == null) {
-            return true;
-        }
-        return mLocalPlayer.setPreferredDevice(getBuiltinDevice(mAudioManager));
-    }
-
-    /**
      * Creates a local media player for the ringtone using currently set attributes.
      * @return true if media player creation succeeded or is deferred,
      * false if it did not succeed and can't be tried remotely.
      * @hide
      */
-    public boolean createLocalMediaPlayer() {
-        Trace.beginSection("createLocalMediaPlayer");
-        if (mUri == null) {
-            Log.e(TAG, "Could not create media player as no URI was provided.");
-            return mAllowRemote && mRemotePlayer != null;
-        }
-        destroyLocalPlayer();
-        // try opening uri locally before delegating to remote player
-        mLocalPlayer = new MediaPlayer();
+    public boolean reinitializeActivePlayer() {
+        // Try creating a local media player, or fallback to creating a remote one.
+        Trace.beginSection("reinitializeActivePlayer");
         try {
-            mLocalPlayer.setDataSource(mContext, mUri);
-            mLocalPlayer.setAudioAttributes(mAudioAttributes);
-            mLocalPlayer.setPreferredDevice(
-                    mPreferBuiltinDevice ? getBuiltinDevice(mAudioManager) : null);
-            synchronized (mPlaybackSettingsLock) {
-                applyPlaybackProperties_sync();
+            if (mActivePlayer != null) {
+                // This would only happen if calling the deprecated setAudioAttributes after
+                // building the Ringtone.
+                stopAndReleaseActivePlayer();
             }
-            if (mVolumeShaperConfig != null) {
-                mVolumeShaper = mLocalPlayer.createVolumeShaper(mVolumeShaperConfig);
-            }
-            mLocalPlayer.prepare();
 
-        } catch (SecurityException | IOException e) {
-            destroyLocalPlayer();
-            if (!mAllowRemote) {
-                Log.w(TAG, "Remote playback not allowed: " + e);
-            }
-        }
-
-        if (LOGD) {
-            if (mLocalPlayer != null) {
-                Log.d(TAG, "Successfully created local player");
+            AudioDeviceInfo preferredDevice =
+                    mPreferBuiltinDevice ? getBuiltinDevice(mAudioManager) : null;
+            if (mUri != null) {
+                mActivePlayer = LocalRingtonePlayer.create(mContext, mAudioManager, mUri,
+                        mAudioAttributes, mInjectables, mVolumeShaperConfig, preferredDevice,
+                        mHapticGeneratorEnabled, mIsLooping, mVolume);
             } else {
-                Log.d(TAG, "Problem opening; delegating to remote player");
+                // Using the remote player won't help play a null Uri. Revert straight to fallback.
+                mActivePlayer = createFallbackRingtonePlayer();
+                // Fall through to attempting remote fallback play if null.
             }
+
+            if (mActivePlayer == null && mAllowRemote) {
+                mActivePlayer = new RemoteRingtonePlayer(mRemoteRingtoneService, mUri,
+                        mAudioAttributes,
+                        mVolumeShaperConfig, mHapticGeneratorEnabled, mIsLooping, mVolume);
+            }
+            return mActivePlayer != null;
+        } finally {
+            Trace.endSection();
         }
-        Trace.endSection();
-        return mLocalPlayer != null || (mAllowRemote && mRemotePlayer != null);
+    }
+
+    @Nullable
+    private LocalRingtonePlayer createFallbackRingtonePlayer() {
+        int ringtoneType = RingtoneManager.getDefaultType(mUri);
+        if (ringtoneType != -1
+                && RingtoneManager.getActualDefaultRingtoneUri(mContext, ringtoneType) == null) {
+            Log.w(TAG, "not playing fallback for " + mUri);
+            return null;
+        }
+        // Default ringtone, try fallback ringtone.
+        try (AssetFileDescriptor afd = mContext.getResources().openRawResourceFd(
+                    com.android.internal.R.raw.fallbackring)) {
+            if (afd == null) {
+                Log.e(TAG, "Could not load fallback ringtone");
+                return null;
+            }
+
+            AudioDeviceInfo preferredDevice =
+                    mPreferBuiltinDevice ? getBuiltinDevice(mAudioManager) : null;
+            return LocalRingtonePlayer.createForFallback(mAudioManager, afd,
+                    mAudioAttributes, mInjectables, mVolumeShaperConfig, preferredDevice,
+                    mIsLooping, mVolume);
+        } catch (NotFoundException nfe) {
+            Log.e(TAG, "Fallback ringtone does not exist");
+            return null;
+        } catch (IOException e) {
+            // As with the above messages, not including much information about the
+            // failure so as not to expose details of the fallback ringtone resource.
+            Log.e(TAG, "Exception reading fallback ringtone");
+            return null;
+        }
     }
 
     /**
      * Same as AudioManager.hasHapticChannels except it assumes an already created ringtone.
-     * If the ringtone has not been created, it will load based on URI provided at {@link #setUri}
-     * and if not URI has been set, it will assume no haptic channels are present.
      * @hide
      */
     public boolean hasHapticChannels() {
-        // FIXME: support remote player, or internalize haptic channels support and remove entirely.
-        try {
-            android.os.Trace.beginSection("Ringtone.hasHapticChannels");
-            if (mLocalPlayer != null) {
-                for(MediaPlayer.TrackInfo trackInfo : mLocalPlayer.getTrackInfo()) {
-                    if (trackInfo.hasHapticChannels()) {
-                        return true;
-                    }
-                }
-            }
-        } finally {
-            android.os.Trace.endSection();
-        }
-        return false;
-    }
-
-    /**
-     * Returns whether a local player has been created for this ringtone.
-     * @hide
-     */
-    @VisibleForTesting
-    public boolean hasLocalPlayer() {
-        return mLocalPlayer != null;
+        return (mActivePlayer == null) ? false : mActivePlayer.hasHapticChannels();
     }
 
     /**
@@ -282,7 +334,9 @@
     public void setLooping(boolean looping) {
         synchronized (mPlaybackSettingsLock) {
             mIsLooping = looping;
-            applyPlaybackProperties_sync();
+            if (mActivePlayer != null) {
+                mActivePlayer.setLooping(looping);
+            }
         }
     }
 
@@ -302,11 +356,17 @@
      *   corresponds to no attenuation being applied.
      */
     public void setVolume(float volume) {
+        if (volume < 0.0f) {
+            volume = 0.0f;
+        } else if (volume > 1.0f) {
+            volume = 1.0f;
+        }
+
         synchronized (mPlaybackSettingsLock) {
-            if (volume < 0.0f) { volume = 0.0f; }
-            if (volume > 1.0f) { volume = 1.0f; }
             mVolume = volume;
-            applyPlaybackProperties_sync();
+            if (mActivePlayer != null) {
+                mActivePlayer.setVolume(volume);
+            }
         }
     }
 
@@ -328,12 +388,14 @@
      * @see android.media.audiofx.HapticGenerator#isAvailable()
      */
     public boolean setHapticGeneratorEnabled(boolean enabled) {
-        if (!HapticGenerator.isAvailable()) {
+        if (!mInjectables.isHapticGeneratorAvailable()) {
             return false;
         }
         synchronized (mPlaybackSettingsLock) {
             mHapticGeneratorEnabled = enabled;
-            applyPlaybackProperties_sync();
+            if (mActivePlayer != null) {
+                mActivePlayer.setHapticGeneratorEnabled(enabled);
+            }
         }
         return true;
     }
@@ -349,32 +411,6 @@
     }
 
     /**
-     * Must be called synchronized on mPlaybackSettingsLock
-     */
-    private void applyPlaybackProperties_sync() {
-        if (mLocalPlayer != null) {
-            mLocalPlayer.setVolume(mVolume);
-            mLocalPlayer.setLooping(mIsLooping);
-            if (mHapticGenerator == null && mHapticGeneratorEnabled) {
-                mHapticGenerator = HapticGenerator.create(mLocalPlayer.getAudioSessionId());
-            }
-            if (mHapticGenerator != null) {
-                mHapticGenerator.setEnabled(mHapticGeneratorEnabled);
-            }
-        } else if (mAllowRemote && (mRemotePlayer != null)) {
-            try {
-                mRemotePlayer.setPlaybackProperties(
-                        mRemoteToken, mVolume, mIsLooping, mHapticGeneratorEnabled);
-            } catch (RemoteException e) {
-                Log.w(TAG, "Problem setting playback properties: ", e);
-            }
-        } else {
-            Log.w(TAG,
-                    "Neither local nor remote player available when applying playback properties");
-        }
-    }
-
-    /**
      * Returns a human-presentable title for ringtone. Looks in media
      * content provider. If not in either, uses the filename
      *
@@ -456,39 +492,6 @@
         return title;
     }
 
-    /**
-     * Set {@link Uri} to be used for ringtone playback.
-     * {@link IRingtonePlayer}.
-     *
-     * @hide
-     */
-    @UnsupportedAppUsage
-    public void setUri(Uri uri) {
-        setUri(uri, null);
-    }
-
-    /**
-     * @hide
-     */
-    public void setVolumeShaperConfig(@Nullable VolumeShaper.Configuration volumeShaperConfig) {
-        mVolumeShaperConfig = volumeShaperConfig;
-    }
-
-    /**
-     * Set {@link Uri} to be used for ringtone playback. Attempts to open
-     * locally, otherwise will delegate playback to remote
-     * {@link IRingtonePlayer}. Add {@link VolumeShaper} if required.
-     *
-     * @hide
-     */
-    public void setUri(Uri uri, @Nullable VolumeShaper.Configuration volumeShaperConfig) {
-        mVolumeShaperConfig = volumeShaperConfig;
-        mUri = uri;
-        if (mUri == null) {
-            destroyLocalPlayer();
-        }
-    }
-
     /** {@hide} */
     @UnsupportedAppUsage
     public Uri getUri() {
@@ -499,36 +502,16 @@
      * Plays the ringtone.
      */
     public void play() {
-        if (mLocalPlayer != null) {
-            // Play ringtones if stream volume is over 0 or if it is a haptic-only ringtone
-            // (typically because ringer mode is vibrate).
-            if (mAudioManager.getStreamVolume(AudioAttributes.toLegacyStreamType(mAudioAttributes))
-                    != 0) {
-                startLocalPlayer();
-            } else if (!mAudioAttributes.areHapticChannelsMuted() && hasHapticChannels()) {
-                // is haptic only ringtone
-                startLocalPlayer();
+        if (mActivePlayer != null) {
+            if (mActivePlayer.play()) {
+                return;
+            } else {
+                // Discard active player: play() is only meant to be called once.
+                stopAndReleaseActivePlayer();
             }
-        } else if (mAllowRemote && (mRemotePlayer != null) && (mUri != null)) {
-            final Uri canonicalUri = mUri.getCanonicalUri();
-            final boolean looping;
-            final float volume;
-            synchronized (mPlaybackSettingsLock) {
-                looping = mIsLooping;
-                volume = mVolume;
-            }
-            try {
-                mRemotePlayer.playWithVolumeShaping(mRemoteToken, canonicalUri, mAudioAttributes,
-                        volume, looping, mVolumeShaperConfig);
-            } catch (RemoteException e) {
-                if (!playFallbackRingtone()) {
-                    Log.w(TAG, "Problem playing ringtone: " + e);
-                }
-            }
-        } else {
-            if (!playFallbackRingtone()) {
-                Log.w(TAG, "Neither local nor remote playback available");
-            }
+        }
+        if (!playFallbackRingtone()) {
+            Log.w(TAG, "Neither local nor remote playback available");
         }
     }
 
@@ -536,45 +519,13 @@
      * Stops a playing ringtone.
      */
     public void stop() {
-        if (mLocalPlayer != null) {
-            destroyLocalPlayer();
-        } else if (mAllowRemote && (mRemotePlayer != null)) {
-            try {
-                mRemotePlayer.stop(mRemoteToken);
-            } catch (RemoteException e) {
-                Log.w(TAG, "Problem stopping ringtone: " + e);
-            }
-        }
+        stopAndReleaseActivePlayer();
     }
 
-    private void destroyLocalPlayer() {
-        if (mLocalPlayer != null) {
-            if (mHapticGenerator != null) {
-                mHapticGenerator.release();
-                mHapticGenerator = null;
-            }
-            mLocalPlayer.setOnCompletionListener(null);
-            mLocalPlayer.reset();
-            mLocalPlayer.release();
-            mLocalPlayer = null;
-            mVolumeShaper = null;
-            synchronized (sActiveRingtones) {
-                sActiveRingtones.remove(this);
-            }
-        }
-    }
-
-    private void startLocalPlayer() {
-        if (mLocalPlayer == null) {
-            return;
-        }
-        synchronized (sActiveRingtones) {
-            sActiveRingtones.add(this);
-        }
-        mLocalPlayer.setOnCompletionListener(mCompletionListener);
-        mLocalPlayer.start();
-        if (mVolumeShaper != null) {
-            mVolumeShaper.apply(VolumeShaper.Operation.PLAY);
+    private void stopAndReleaseActivePlayer() {
+        if (mActivePlayer != null) {
+            mActivePlayer.stopAndRelease();
+            mActivePlayer = null;
         }
     }
 
@@ -584,87 +535,333 @@
      * @return True if playing, false otherwise.
      */
     public boolean isPlaying() {
-        if (mLocalPlayer != null) {
-            return mLocalPlayer.isPlaying();
-        } else if (mAllowRemote && (mRemotePlayer != null)) {
-            try {
-                return mRemotePlayer.isPlaying(mRemoteToken);
-            } catch (RemoteException e) {
-                Log.w(TAG, "Problem checking ringtone: " + e);
-                return false;
-            }
+        if (mActivePlayer != null) {
+            return mActivePlayer.isPlaying();
         } else {
-            Log.w(TAG, "Neither local nor remote playback available");
+            Log.w(TAG, "No active ringtone player");
             return false;
         }
     }
 
+    /**
+     * Fallback during the play stage rather than initialization, typically due to an issue
+     * communicating with the remote player.
+     */
     private boolean playFallbackRingtone() {
+        if (mActivePlayer != null) {
+            Log.wtf(TAG, "Playing fallback ringtone with another active player");
+            stopAndReleaseActivePlayer();
+        }
         int streamType = AudioAttributes.toLegacyStreamType(mAudioAttributes);
         if (mAudioManager.getStreamVolume(streamType) == 0) {
+            // TODO: Return true? If volume is off, this is a successful play.
             return false;
         }
-        int ringtoneType = RingtoneManager.getDefaultType(mUri);
-        if (ringtoneType != -1 &&
-                RingtoneManager.getActualDefaultRingtoneUri(mContext, ringtoneType) == null) {
-            Log.w(TAG, "not playing fallback for " + mUri);
+        mActivePlayer = createFallbackRingtonePlayer();
+        if (mActivePlayer == null) {
+            return false;  // the create method logs if it returns null.
+        } else if (mActivePlayer.play()) {
+            return true;
+        } else {
+            stopAndReleaseActivePlayer();
             return false;
         }
-        // Default ringtone, try fallback ringtone.
-        try {
-            AssetFileDescriptor afd = mContext.getResources().openRawResourceFd(
-                    com.android.internal.R.raw.fallbackring);
-            if (afd == null) {
-                Log.e(TAG, "Could not load fallback ringtone");
-                return false;
-            }
-            mLocalPlayer = new MediaPlayer();
-            if (afd.getDeclaredLength() < 0) {
-                mLocalPlayer.setDataSource(afd.getFileDescriptor());
-            } else {
-                mLocalPlayer.setDataSource(afd.getFileDescriptor(),
-                        afd.getStartOffset(),
-                        afd.getDeclaredLength());
-            }
-            mLocalPlayer.setAudioAttributes(mAudioAttributes);
-            synchronized (mPlaybackSettingsLock) {
-                applyPlaybackProperties_sync();
-            }
-            if (mVolumeShaperConfig != null) {
-                mVolumeShaper = mLocalPlayer.createVolumeShaper(mVolumeShaperConfig);
-            }
-            mLocalPlayer.prepare();
-            startLocalPlayer();
-            afd.close();
-        } catch (IOException ioe) {
-            destroyLocalPlayer();
-            Log.e(TAG, "Failed to open fallback ringtone");
-            return false;
-        } catch (NotFoundException nfe) {
-            Log.e(TAG, "Fallback ringtone does not exist");
-            return false;
-        }
-        return true;
     }
 
     void setTitle(String title) {
         mTitle = title;
     }
 
-    @Override
-    protected void finalize() {
-        if (mLocalPlayer != null) {
-            mLocalPlayer.release();
+    /**
+     * Build a {@link Ringtone} to easily play sounds for ringtones, alarms and notifications.
+     *
+     * TODO: when un-hide, deprecate Ringtone: setAudioAttributes.
+     * @hide
+     */
+    public static final class Builder {
+        private final Context mContext;
+        private final int mEnabledMedia;
+        private Uri mUri;
+        private final AudioAttributes mAudioAttributes;
+        // Not a static default since it doesn't really need to be in memory forever.
+        private Injectables mInjectables = new Injectables();
+        private VolumeShaper.Configuration mVolumeShaperConfig;
+        private boolean mPreferBuiltinDevice = false;
+        private boolean mAllowRemote = true;
+        private float mInitialSoundVolume = 1.0f;
+        private boolean mLooping = false;
+
+        /**
+         * Constructs a builder to play the given media types from the mediaUri. If the mediaUri
+         * is null (for example, an unset-setting), then fallback logic will dictate what plays.
+         *
+         * <p>When built, if the ringtone is already known to be a no-op, such as explicitly
+         * silent, then the {@link #build} may return null.
+         *
+         * @param context The context for playing the ringtone.
+         * @param enabledMedia Which media to play. Media not included is implicitly muted.
+        * @param audioAttributes The attributes to use for playback, which affects the volumes and
+         *                        settings that are applied.
+         */
+        public Builder(@NonNull Context context, @RingtoneMedia int enabledMedia,
+                @NonNull AudioAttributes audioAttributes) {
+            if (enabledMedia != MEDIA_SOUND) {
+                throw new UnsupportedOperationException("Other media types not supported yet");
+            }
+            mContext = context;
+            mEnabledMedia = enabledMedia;
+            mAudioAttributes = audioAttributes;
+        }
+
+        /**
+         * Inject test intercepters for static methods.
+         * @hide
+         */
+        @NonNull
+        public Builder setInjectables(Injectables injectables) {
+            mInjectables = injectables;
+            return this;
+        }
+
+        /**
+         * The uri for the ringtone media to play. This is typically a user's preference for the
+         * sound. If null, then it is treated as though the user's preference is unset and
+         * fallback behavior, such as using the default ringtone setting, are used instead.
+         *
+         * When sound media is enabled, this is assumed to be a sound URI.
+         */
+        @NonNull
+        public Builder setUri(@Nullable Uri uri) {
+            mUri = uri;
+            return this;
+        }
+
+        /**
+         * Sets whether the resulting ringtone should loop until {@link Ringtone#stop()} is called,
+         * or just play once.
+         */
+        @NonNull
+        public Builder setLooping(boolean looping) {
+            mLooping = looping;
+            return this;
+        }
+
+        /**
+         * Sets the VolumeShaper.Configuration to apply to the ringtone.
+         * @hide
+         */
+        @NonNull
+        public Builder setVolumeShaperConfig(
+                @Nullable VolumeShaper.Configuration volumeShaperConfig) {
+            mVolumeShaperConfig = volumeShaperConfig;
+            return this;
+        }
+
+        /**
+         * Sets the initial sound volume for the ringtone.
+         */
+        @NonNull
+        public Builder setInitialSoundVolume(float initialSoundVolume) {
+            mInitialSoundVolume = initialSoundVolume;
+            return this;
+        }
+
+        /**
+         * Sets the preferred device of the ringtone playback to the built-in device.
+         * @hide
+         */
+        @NonNull
+        public Builder setPreferBuiltinDevice() {
+            mPreferBuiltinDevice = true;
+            return this;
+        }
+
+        /**
+         * Prevent fallback to the remote service. This is primarily intended for use within the
+         * remote IRingtonePlayer service itself, to avoid loops.
+         * @hide
+         */
+        @NonNull
+        public Builder setLocalOnly() {
+            mAllowRemote = false;
+            return this;
+        }
+
+        /**
+         * Returns the built Ringtone, or null if there was a problem loading the Uri and there
+         * are no fallback options available.
+         */
+        @Nullable
+        public Ringtone build() {
+            try {
+                Ringtone ringtone = new Ringtone(this);
+                if (ringtone.reinitializeActivePlayer()) {
+                    return ringtone;
+                } else {
+                    Log.e(TAG, "Failed to open ringtone " + mUri);
+                    return null;
+                }
+            } catch (Exception ex) {
+                // Catching Exception isn't great, but was done in the old
+                // RingtoneManager.getRingtone and hides errors like DocumentsProvider throwing
+                // IllegalArgumentException instead of FileNotFoundException, and also robolectric
+                // failures when ShadowMediaPlayer wasn't pre-informed of the ringtone.
+                Log.e(TAG, "Failed to open ringtone " + mUri + ": " + ex);
+                return null;
+            }
         }
     }
 
-    class MyOnCompletionListener implements MediaPlayer.OnCompletionListener {
+    /**
+     * Play a specific ringtone. This interface is implemented by either local (this process) or
+     * proxied-remote playback via AudioManager.getRingtonePlayer, so that the caller
+     * (Ringtone class) can just use a single player after the initial creation.
+     * @hide
+     */
+    interface RingtonePlayer {
+        /**
+         * Start playing the ringtone, returning false if there was a problem that
+         * requires falling back to the fallback ringtone resource.
+         */
+        boolean play();
+        boolean isPlaying();
+        void stopAndRelease();
+
+        // Mutating playback methods.
+        void setPreferredDevice(@Nullable AudioDeviceInfo audioDeviceInfo);
+        void setLooping(boolean looping);
+        void setHapticGeneratorEnabled(boolean enabled);
+        void setVolume(float volume);
+
+        boolean hasHapticChannels();
+    }
+
+    /**
+     * Remote RingtonePlayer. All operations are delegated via the IRingtonePlayer interface, which
+     * should ultimately be backed by a RingtoneLocalPlayer within the system services.
+     */
+    static class RemoteRingtonePlayer implements RingtonePlayer {
+        private final IBinder mRemoteToken = new Binder();
+        private final IRingtonePlayer mRemoteRingtoneService;
+        private final Uri mCanonicalUri;
+        private final VolumeShaper.Configuration mVolumeShaperConfig;
+        private final AudioAttributes mAudioAttributes;
+        private boolean mIsLooping;
+        private float mVolume;
+        private boolean mIsHapticGeneratorEnabled;
+
+        RemoteRingtonePlayer(@NonNull IRingtonePlayer remoteRingtoneService,
+                @NonNull Uri uri, @NonNull AudioAttributes audioAttributes,
+                @Nullable VolumeShaper.Configuration volumeShaperConfig,
+                boolean isHapticGeneratorEnabled, boolean initialIsLooping, float initialVolume) {
+            mRemoteRingtoneService = remoteRingtoneService;
+            mCanonicalUri = (uri == null) ? null : uri.getCanonicalUri();
+            mAudioAttributes = audioAttributes;
+            mVolumeShaperConfig = volumeShaperConfig;
+            mIsHapticGeneratorEnabled = isHapticGeneratorEnabled;
+            mIsLooping = initialIsLooping;
+            mVolume = initialVolume;
+        }
+
         @Override
-        public void onCompletion(MediaPlayer mp) {
-            synchronized (sActiveRingtones) {
-                sActiveRingtones.remove(Ringtone.this);
+        public boolean play() {
+            try {
+                mRemoteRingtoneService.playWithVolumeShaping(mRemoteToken, mCanonicalUri,
+                        mAudioAttributes, mVolume, mIsLooping, mIsHapticGeneratorEnabled,
+                        mVolumeShaperConfig);
+                return true;
+            } catch (RemoteException e) {
+                Log.w(TAG, "Problem playing ringtone: " + e);
+                return false;
             }
-            mp.setOnCompletionListener(null); // Help the Java GC: break the refcount cycle.
+        }
+
+        @Override
+        public boolean isPlaying() {
+            try {
+                return mRemoteRingtoneService.isPlaying(mRemoteToken);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Problem checking ringtone isPlaying: " + e);
+                return false;
+            }
+        }
+
+        @Override
+        public void stopAndRelease() {
+            try {
+                mRemoteRingtoneService.stop(mRemoteToken);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Problem stopping ringtone: " + e);
+            }
+        }
+
+        @Override
+        public void setPreferredDevice(@Nullable AudioDeviceInfo audioDeviceInfo) {
+            // un-implemented for remote (but not used outside system).
+        }
+
+        @Override
+        public void setLooping(boolean looping) {
+            mIsLooping = looping;
+            try {
+                mRemoteRingtoneService.setLooping(mRemoteToken, looping);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Problem setting looping: " + e);
+            }
+        }
+
+        @Override
+        public void setHapticGeneratorEnabled(boolean enabled) {
+            mIsHapticGeneratorEnabled = enabled;
+            try {
+                mRemoteRingtoneService.setHapticGeneratorEnabled(mRemoteToken, enabled);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Problem setting hapticGeneratorEnabled: " + e);
+            }
+        }
+
+        @Override
+        public void setVolume(float volume) {
+            mVolume = volume;
+            try {
+                mRemoteRingtoneService.setVolume(mRemoteToken, volume);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Problem setting volume: " + e);
+            }
+        }
+
+        @Override
+        public boolean hasHapticChannels() {
+            // FIXME: support remote player, or internalize haptic channels support and remove
+            // entirely.
+            return false;
+        }
+    }
+
+    /**
+     * Interface for intercepting static methods and constructors, for unit testing only.
+     * @hide
+     */
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+    public static class Injectables {
+        /** Intercept {@code new MediaPlayer()}. */
+        @NonNull
+        public MediaPlayer newMediaPlayer() {
+            return new MediaPlayer();
+        }
+
+        /** Intercept {@link HapticGenerator#isAvailable}. */
+        public boolean isHapticGeneratorAvailable() {
+            return HapticGenerator.isAvailable();
+        }
+
+        /**
+         * Intercept {@link HapticGenerator#create} using
+         * {@link MediaPlayer#getAudioSessionId()} from the given media player.
+         */
+        @Nullable
+        public HapticGenerator createHapticGenerator(@NonNull MediaPlayer mediaPlayer) {
+            return HapticGenerator.create(mediaPlayer.getAudioSessionId());
         }
     }
 }
diff --git a/media/java/android/media/RingtoneManager.java b/media/java/android/media/RingtoneManager.java
index d2b21ae..ebf02a2 100644
--- a/media/java/android/media/RingtoneManager.java
+++ b/media/java/android/media/RingtoneManager.java
@@ -16,7 +16,6 @@
 
 package android.media;
 
-import android.Manifest;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
@@ -39,10 +38,7 @@
 import android.os.Build;
 import android.os.Environment;
 import android.os.FileUtils;
-import android.os.IBinder;
 import android.os.ParcelFileDescriptor;
-import android.os.RemoteException;
-import android.os.ServiceManager;
 import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.os.UserManager;
@@ -357,6 +353,25 @@
         }
     }
 
+    /** @hide */
+    @NonNull
+    public static AudioAttributes getDefaultAudioAttributes(int ringtoneType) {
+        AudioAttributes.Builder builder = new AudioAttributes.Builder();
+        switch (ringtoneType) {
+            case TYPE_ALARM:
+                builder.setUsage(AudioAttributes.USAGE_ALARM);
+                break;
+            case TYPE_NOTIFICATION:
+                builder.setUsage(AudioAttributes.USAGE_NOTIFICATION);
+                break;
+            default:  // ringtone or all
+                builder.setUsage(AudioAttributes.USAGE_NOTIFICATION_RINGTONE);
+                break;
+        }
+        builder.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION);
+        return builder.build();
+    }
+
     /**
      * Whether retrieving another {@link Ringtone} will stop playing the
      * previously retrieved {@link Ringtone}.
@@ -481,8 +496,10 @@
             mPreviousRingtone.stop();
         }
 
-        mPreviousRingtone =
-                getRingtone(mContext, getRingtoneUri(position), inferStreamType(), true);
+        mPreviousRingtone = new Ringtone.Builder(
+                mContext, Ringtone.MEDIA_SOUND, getDefaultAudioAttributes(mType))
+                .setUri(getRingtoneUri(position))
+                .build();
         return mPreviousRingtone;
     }
 
@@ -677,40 +694,9 @@
      * @return A {@link Ringtone} for the given URI, or null.
      */
     public static Ringtone getRingtone(final Context context, Uri ringtoneUri) {
-        // Don't set the stream type
-        return getRingtone(context, ringtoneUri, -1, true);
-    }
-
-    /**
-     * Returns a {@link Ringtone} with {@link VolumeShaper} if required for a given sound URI.
-     * <p>
-     * If the given URI cannot be opened for any reason, this method will
-     * attempt to fallback on another sound. If it cannot find any, it will
-     * return null.
-     *
-     * @param context A context used to query.
-     * @param ringtoneUri The {@link Uri} of a sound or ringtone.
-     * @param volumeShaperConfig config for volume shaper of the ringtone if applied.
-     * @return A {@link Ringtone} for the given URI, or null.
-     *
-     * @hide
-     */
-    public static Ringtone getRingtone(
-            final Context context, Uri ringtoneUri,
-            @Nullable VolumeShaper.Configuration volumeShaperConfig) {
-        // Don't set the stream type
-        return getRingtone(context, ringtoneUri, -1 /* streamType */, volumeShaperConfig, true);
-    }
-
-    /**
-     * @hide
-     */
-    public static Ringtone getRingtone(final Context context, Uri ringtoneUri,
-            @Nullable VolumeShaper.Configuration volumeShaperConfig,
-            boolean createLocalMediaPlayer) {
-        // Don't set the stream type
-        return getRingtone(context, ringtoneUri, -1 /* streamType */, volumeShaperConfig,
-                createLocalMediaPlayer);
+        return new Ringtone.Builder(context, Ringtone.MEDIA_SOUND, getDefaultAudioAttributes(-1))
+                .setUri(ringtoneUri)
+                .build();
     }
 
     /**
@@ -719,64 +705,11 @@
     public static Ringtone getRingtone(final Context context, Uri ringtoneUri,
             @Nullable VolumeShaper.Configuration volumeShaperConfig,
             AudioAttributes audioAttributes) {
-        // Don't set the stream type
-        Ringtone ringtone = getRingtone(context, ringtoneUri, -1 /* streamType */,
-                volumeShaperConfig, false);
-        if (ringtone != null) {
-            ringtone.setAudioAttributesField(audioAttributes);
-            if (!ringtone.createLocalMediaPlayer()) {
-                Log.e(TAG, "Failed to open ringtone " + ringtoneUri);
-                return null;
-            }
-        }
-        return ringtone;
-    }
-
-    //FIXME bypass the notion of stream types within the class
-    /**
-     * Returns a {@link Ringtone} for a given sound URI on the given stream
-     * type. Normally, if you change the stream type on the returned
-     * {@link Ringtone}, it will re-create the {@link MediaPlayer}. This is just
-     * an optimized route to avoid that.
-     *
-     * @param streamType The stream type for the ringtone, or -1 if it should
-     *            not be set (and the default used instead).
-     * @param createLocalMediaPlayer when true, the ringtone returned will be fully
-     *      created otherwise, it will require the caller to create the media player manually
-     *      {@link Ringtone#createLocalMediaPlayer()} in order to play the Ringtone.
-     * @see #getRingtone(Context, Uri)
-     */
-    @UnsupportedAppUsage
-    private static Ringtone getRingtone(final Context context, Uri ringtoneUri, int streamType,
-            boolean createLocalMediaPlayer) {
-        return getRingtone(context, ringtoneUri, streamType, null /* volumeShaperConfig */,
-                createLocalMediaPlayer);
-    }
-
-    private static Ringtone getRingtone(final Context context, Uri ringtoneUri, int streamType,
-            @Nullable VolumeShaper.Configuration volumeShaperConfig,
-            boolean createLocalMediaPlayer) {
-        try {
-            final Ringtone r = new Ringtone(context, true);
-            if (streamType >= 0) {
-                //FIXME deprecated call
-                r.setStreamType(streamType);
-            }
-
-            r.setVolumeShaperConfig(volumeShaperConfig);
-            r.setUri(ringtoneUri, volumeShaperConfig);
-            if (createLocalMediaPlayer) {
-                if (!r.createLocalMediaPlayer()) {
-                    Log.e(TAG, "Failed to open ringtone " + ringtoneUri);
-                    return null;
-                }
-            }
-            return r;
-        } catch (Exception ex) {
-            Log.e(TAG, "Failed to open ringtone " + ringtoneUri + ": " + ex);
-        }
-
-        return null;
+        // TODO: move caller(s) away from this method: inline the builder call.
+        return new Ringtone.Builder(context, Ringtone.MEDIA_SOUND, audioAttributes)
+                .setUri(ringtoneUri)
+                .setVolumeShaperConfig(volumeShaperConfig)
+                .build();
     }
 
     /**
diff --git a/media/java/android/media/projection/TEST_MAPPING b/media/java/android/media/projection/TEST_MAPPING
index 4324930..a792498 100644
--- a/media/java/android/media/projection/TEST_MAPPING
+++ b/media/java/android/media/projection/TEST_MAPPING
@@ -13,20 +13,6 @@
           "exclude-annotation": "org.junit.Ignore"
         }
       ]
-    },
-    {
-      "name": "CtsMediaProjectionTestCases",
-      "options": [
-        {
-          "exclude-annotation": "android.platform.test.annotations.FlakyTest"
-        },
-        {
-          "exclude-annotation": "androidx.test.filters.FlakyTest"
-        },
-        {
-          "exclude-annotation": "org.junit.Ignore"
-        }
-      ]
     }
   ]
 }
diff --git a/media/tests/MediaFrameworkTest/Android.bp b/media/tests/MediaFrameworkTest/Android.bp
index 06ec949e..ca20225e 100644
--- a/media/tests/MediaFrameworkTest/Android.bp
+++ b/media/tests/MediaFrameworkTest/Android.bp
@@ -20,7 +20,9 @@
         "androidx.test.ext.junit",
         "androidx.test.rules",
         "android-ex-camera2",
+        "testables",
         "testng",
+        "truth-prebuilt",
     ],
     jni_libs: [
         "libdexmakerjvmtiagent",
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/OWNERS b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/OWNERS
new file mode 100644
index 0000000..6d5f82c
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/OWNERS
@@ -0,0 +1,2 @@
+# Haptics team also works on Ringtone
+per-file *Ringtone* = file:/services/core/java/com/android/server/vibrator/OWNERS
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/RingtoneTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/RingtoneTest.java
new file mode 100644
index 0000000..d8e3f8d
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/RingtoneTest.java
@@ -0,0 +1,410 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.mediaframeworktest.unit;
+
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyObject;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.isNull;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.res.AssetFileDescriptor;
+import android.media.AudioAttributes;
+import android.media.AudioManager;
+import android.media.IRingtonePlayer;
+import android.media.MediaPlayer;
+import android.media.Ringtone;
+import android.media.audiofx.HapticGenerator;
+import android.net.Uri;
+import android.os.IBinder;
+import android.testing.TestableContext;
+import android.util.ArrayMap;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.mediaframeworktest.R;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TestRule;
+import org.junit.runner.Description;
+import org.junit.runner.RunWith;
+import org.junit.runners.model.Statement;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+
+import java.io.FileNotFoundException;
+import java.util.ArrayDeque;
+import java.util.Map;
+import java.util.Queue;
+
+@RunWith(AndroidJUnit4.class)
+public class RingtoneTest {
+
+    private static final Uri SOUND_URI = Uri.parse("content://fake-sound-uri");
+
+    private static final AudioAttributes RINGTONE_ATTRIBUTES =
+            audioAttributes(AudioAttributes.USAGE_NOTIFICATION_RINGTONE);
+
+    @Rule
+    public final RingtoneInjectablesTrackingTestRule
+            mMediaPlayerRule = new RingtoneInjectablesTrackingTestRule();
+
+    @Captor ArgumentCaptor<IBinder> mIBinderCaptor;
+    @Mock IRingtonePlayer mMockRemotePlayer;
+    private TestableContext mContext;
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+        TestableContext testContext =
+                new TestableContext(InstrumentationRegistry.getTargetContext(), null);
+
+        AudioManager realAudioManager = testContext.getSystemService(AudioManager.class);
+        AudioManager spyAudioManager = spy(realAudioManager);
+        when(spyAudioManager.getRingtonePlayer()).thenReturn(mMockRemotePlayer);
+        testContext.addMockSystemService(Context.AUDIO_SERVICE, spyAudioManager);
+
+        mContext = spy(testContext);
+    }
+
+    @Test
+    public void testRingtone_fullLifecycleUsingLocalMediaPlayer() throws Exception {
+        MediaPlayer mockMediaPlayer = mMediaPlayerRule.expectLocalMediaPlayer();
+        Ringtone ringtone =
+                newBuilder(Ringtone.MEDIA_SOUND, RINGTONE_ATTRIBUTES).setUri(SOUND_URI).build();
+        assertThat(ringtone).isNotNull();
+        assertThat(ringtone.isUsingRemotePlayer()).isFalse();
+
+        // Verify all the properties.
+        assertThat(ringtone.getEnabledMedia()).isEqualTo(Ringtone.MEDIA_SOUND);
+        assertThat(ringtone.getUri()).isEqualTo(SOUND_URI);
+        assertThat(ringtone.getAudioAttributes()).isEqualTo(RINGTONE_ATTRIBUTES);
+        assertThat(ringtone.getVolume()).isEqualTo(1.0f);
+        assertThat(ringtone.isLooping()).isEqualTo(false);
+        assertThat(ringtone.isHapticGeneratorEnabled()).isEqualTo(false);
+        assertThat(ringtone.getPreferBuiltinDevice()).isFalse();
+        assertThat(ringtone.getVolumeShaperConfig()).isNull();
+        assertThat(ringtone.isLocalOnly()).isFalse();
+
+        // Prepare
+        verifyLocalPlayerSetup(mockMediaPlayer, SOUND_URI,
+                audioAttributes(AudioAttributes.USAGE_NOTIFICATION_RINGTONE));
+        verify(mockMediaPlayer).setVolume(1.0f);
+        verify(mockMediaPlayer).setLooping(false);
+        verify(mockMediaPlayer).prepare();
+
+        // Play
+        ringtone.play();
+        verifyLocalPlay(mockMediaPlayer);
+
+        // Verify dynamic controls.
+        ringtone.setVolume(0.8f);
+        verify(mockMediaPlayer).setVolume(0.8f);
+        ringtone.setLooping(true);
+        verify(mockMediaPlayer).setLooping(true);
+        HapticGenerator mockHapticGenerator =
+                mMediaPlayerRule.expectHapticGenerator(mockMediaPlayer);
+        ringtone.setHapticGeneratorEnabled(true);
+        verify(mockHapticGenerator).setEnabled(true);
+
+        // Release
+        ringtone.stop();
+        verifyLocalStop(mockMediaPlayer);
+        verifyNoMoreInteractions(mockMediaPlayer);
+        verify(mockHapticGenerator).release();
+        verifyNoMoreInteractions(mockHapticGenerator);
+        verifyZeroInteractions(mMockRemotePlayer);
+    }
+
+    @Test
+    public void testRingtone_fullLifecycleUsingRemoteMediaPlayer() throws Exception {
+        MediaPlayer mockMediaPlayer = mMediaPlayerRule.expectLocalMediaPlayer();
+        setupFileNotFound(mockMediaPlayer, SOUND_URI);
+        Ringtone ringtone =
+                newBuilder(Ringtone.MEDIA_SOUND, RINGTONE_ATTRIBUTES)
+                .setUri(SOUND_URI)
+                .build();
+        assertThat(ringtone).isNotNull();
+        assertThat(ringtone.isUsingRemotePlayer()).isTrue();
+
+        // Verify all the properties.
+        assertThat(ringtone.getEnabledMedia()).isEqualTo(Ringtone.MEDIA_SOUND);
+        assertThat(ringtone.getUri()).isEqualTo(SOUND_URI);
+        assertThat(ringtone.getAudioAttributes()).isEqualTo(RINGTONE_ATTRIBUTES);
+        assertThat(ringtone.getVolume()).isEqualTo(1.0f);
+        assertThat(ringtone.isLooping()).isEqualTo(false);
+        assertThat(ringtone.isHapticGeneratorEnabled()).isEqualTo(false);
+        assertThat(ringtone.getPreferBuiltinDevice()).isFalse();
+        assertThat(ringtone.getVolumeShaperConfig()).isNull();
+        assertThat(ringtone.isLocalOnly()).isFalse();
+
+        // Initialization did try to create a local media player.
+        verify(mockMediaPlayer).setDataSource(mContext, SOUND_URI);
+        // setDataSource throws file not found, so nothing else will happen on the local player.
+        verify(mockMediaPlayer).release();
+
+        // Delegates to remote media player.
+        ringtone.play();
+        verify(mMockRemotePlayer).playWithVolumeShaping(mIBinderCaptor.capture(), eq(SOUND_URI),
+                eq(audioAttributes(AudioAttributes.USAGE_NOTIFICATION_RINGTONE)),
+                eq(1.0f), eq(false), eq(false), isNull());
+        IBinder remoteToken = mIBinderCaptor.getValue();
+
+        // Verify dynamic controls.
+        ringtone.setVolume(0.8f);
+        verify(mMockRemotePlayer).setVolume(remoteToken, 0.8f);
+        ringtone.setLooping(true);
+        verify(mMockRemotePlayer).setLooping(remoteToken, true);
+        ringtone.setHapticGeneratorEnabled(true);
+        verify(mMockRemotePlayer).setHapticGeneratorEnabled(remoteToken, true);
+
+        ringtone.stop();
+        verify(mMockRemotePlayer).stop(remoteToken);
+        verifyNoMoreInteractions(mMockRemotePlayer);
+        verifyNoMoreInteractions(mockMediaPlayer);
+    }
+
+    @Test
+    public void testRingtone_nullMediaOnBuilderUsesFallback() throws Exception {
+        AssetFileDescriptor testResourceFd =
+                mContext.getResources().openRawResourceFd(R.raw.shortmp3);
+        // Ensure it will flow as expected.
+        assertThat(testResourceFd).isNotNull();
+        assertThat(testResourceFd.getDeclaredLength()).isAtLeast(0);
+        mContext.getOrCreateTestableResources()
+                .addOverride(com.android.internal.R.raw.fallbackring, testResourceFd);
+
+        MediaPlayer mockMediaPlayer = mMediaPlayerRule.expectLocalMediaPlayer();
+        Ringtone ringtone = newBuilder(Ringtone.MEDIA_SOUND, RINGTONE_ATTRIBUTES)
+                .setUri(null)
+                .build();
+        assertThat(ringtone).isNotNull();
+        assertThat(ringtone.isUsingRemotePlayer()).isFalse();
+
+        // Delegates straight to fallback in local player.
+        // Prepare
+        verifyLocalPlayerFallbackSetup(mockMediaPlayer, testResourceFd, RINGTONE_ATTRIBUTES);
+        verify(mockMediaPlayer).setVolume(1.0f);
+        verify(mockMediaPlayer).setLooping(false);
+        verify(mockMediaPlayer).prepare();
+
+        // Play
+        ringtone.play();
+        verifyLocalPlay(mockMediaPlayer);
+
+        // Release
+        ringtone.stop();
+        verifyLocalStop(mockMediaPlayer);
+
+        verifyNoMoreInteractions(mockMediaPlayer);
+        verifyNoMoreInteractions(mMockRemotePlayer);
+    }
+
+    @Test
+    public void testRingtone_nullMediaOnBuilderUsesFallbackViaRemote() throws Exception {
+        mContext.getOrCreateTestableResources()
+                .addOverride(com.android.internal.R.raw.fallbackring, null);
+        Ringtone ringtone = newBuilder(Ringtone.MEDIA_SOUND, RINGTONE_ATTRIBUTES)
+                .setUri(null)
+                .setLooping(true) // distinct from haptic generator, to match plumbing
+                .build();
+        assertThat(ringtone).isNotNull();
+        // Local player fallback fails as the resource isn't found (no media player creation is
+        // attempted), and then goes on to create the remote player.
+        assertThat(ringtone.isUsingRemotePlayer()).isTrue();
+
+        ringtone.play();
+        verify(mMockRemotePlayer).playWithVolumeShaping(mIBinderCaptor.capture(), isNull(),
+                eq(audioAttributes(AudioAttributes.USAGE_NOTIFICATION_RINGTONE)),
+                eq(1.0f), eq(true), eq(false), isNull());
+        ringtone.stop();
+        verify(mMockRemotePlayer).stop(mIBinderCaptor.getValue());
+        verifyNoMoreInteractions(mMockRemotePlayer);
+    }
+
+    @Test
+    public void testRingtone_noMediaSetOnBuilderFallbackFailsAndNoRemote() throws Exception {
+        mContext.getOrCreateTestableResources()
+                .addOverride(com.android.internal.R.raw.fallbackring, null);
+        Ringtone ringtone = newBuilder(Ringtone.MEDIA_SOUND, RINGTONE_ATTRIBUTES)
+                .setUri(null)
+                .setLocalOnly()
+                .build();
+        // Local player fallback fails as the resource isn't found (no media player creation is
+        // attempted), and since there is no local player, the ringtone ends up having nothing to
+        // do.
+        assertThat(ringtone).isNull();
+    }
+
+    private Ringtone.Builder newBuilder(@Ringtone.RingtoneMedia int ringtoneMedia,
+            AudioAttributes audioAttributes) {
+        return new Ringtone.Builder(mContext, ringtoneMedia, audioAttributes)
+                .setInjectables(mMediaPlayerRule.injectables);
+    }
+
+    private static AudioAttributes audioAttributes(int audioUsage) {
+        return new AudioAttributes.Builder()
+                .setUsage(audioUsage)
+                .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
+                .build();
+    }
+
+    /** Makes the mock get some sort of file access problem. */
+    private void setupFileNotFound(MediaPlayer mockMediaPlayer, Uri uri) throws Exception {
+        doThrow(new FileNotFoundException("Fake file not found"))
+                .when(mockMediaPlayer).setDataSource(any(Context.class), eq(uri));
+    }
+
+    private void verifyLocalPlayerSetup(MediaPlayer mockPlayer, Uri expectedUri,
+            AudioAttributes expectedAudioAttributes) throws Exception {
+        verify(mockPlayer).setDataSource(mContext, expectedUri);
+        verify(mockPlayer).setAudioAttributes(expectedAudioAttributes);
+        verify(mockPlayer).setPreferredDevice(null);
+        verify(mockPlayer).prepare();
+    }
+
+    private void verifyLocalPlayerFallbackSetup(MediaPlayer mockPlayer, AssetFileDescriptor afd,
+            AudioAttributes expectedAudioAttributes) throws Exception {
+        // This is very specific but it's a simple way to test that the test resource matches.
+        if (afd.getDeclaredLength() < 0) {
+            verify(mockPlayer).setDataSource(afd.getFileDescriptor());
+        } else {
+            verify(mockPlayer).setDataSource(afd.getFileDescriptor(),
+                    afd.getStartOffset(),
+                    afd.getDeclaredLength());
+        }
+        verify(mockPlayer).setAudioAttributes(expectedAudioAttributes);
+        verify(mockPlayer).setPreferredDevice(null);
+        verify(mockPlayer).prepare();
+    }
+
+    private void verifyLocalPlay(MediaPlayer mockMediaPlayer) {
+        verify(mockMediaPlayer).setOnCompletionListener(anyObject());
+        verify(mockMediaPlayer).start();
+    }
+
+    private void verifyLocalStop(MediaPlayer mockMediaPlayer) {
+        verify(mockMediaPlayer).setOnCompletionListener(isNull());
+        verify(mockMediaPlayer).reset();
+        verify(mockMediaPlayer).release();
+    }
+
+    /**
+     * This rule ensures that all expected media player creations from the factory do actually
+     * occur. The reason for this level of control is that creating a media player is fairly
+     * expensive and blocking, so we do want unit tests of this class to "declare" interactions
+     * of all created media players.
+     *
+     * This needs to be a TestRule so that the teardown assertions can be skipped if the test has
+     * failed (and media player assertions may just be a distracting side effect). Otherwise, the
+     * teardown failures hide the real test ones.
+     */
+    public static class RingtoneInjectablesTrackingTestRule implements TestRule {
+        public Ringtone.Injectables injectables = new TestInjectables();
+        public boolean hapticGeneratorAvailable = true;
+
+        // Queue of (local) media players, in order of expected creation. Enqueue using
+        // expectNewMediaPlayer(), dequeued by the media player factory passed to Ringtone.
+        // This queue is asserted to be empty at the end of the test.
+        private Queue<MediaPlayer> mMockMediaPlayerQueue = new ArrayDeque<>();
+
+        // Similar to media players, but for haptic generator, which also needs releasing.
+        private Map<MediaPlayer, HapticGenerator> mMockHapticGeneratorMap = new ArrayMap<>();
+
+        @Override
+        public Statement apply(Statement base, Description description) {
+            return new Statement() {
+                @Override
+                public void evaluate() throws Throwable {
+                    base.evaluate();
+                    // Only assert if the test didn't fail (base.evaluate() would throw).
+                    assertWithMessage("Test setup an expectLocalMediaPlayer but it wasn't consumed")
+                            .that(mMockMediaPlayerQueue).isEmpty();
+                    // Only assert if the test didn't fail (base.evaluate() would throw).
+                    assertWithMessage(
+                            "Test setup an expectLocalHapticGenerator but it wasn't consumed")
+                            .that(mMockHapticGeneratorMap).isEmpty();
+                }
+            };
+        }
+
+        private MediaPlayer expectLocalMediaPlayer() {
+            MediaPlayer mockMediaPlayer = Mockito.mock(MediaPlayerMockableNatives.class);
+            mMockMediaPlayerQueue.add(mockMediaPlayer);
+            return mockMediaPlayer;
+        }
+
+        private HapticGenerator expectHapticGenerator(MediaPlayer mockMediaPlayer) {
+            HapticGenerator mockHapticGenerator = Mockito.mock(HapticGenerator.class);
+            // A test should never want this.
+            assertWithMessage("Can't expect a second haptic generator created "
+                    + "for one media player")
+                    .that(mMockHapticGeneratorMap.put(mockMediaPlayer, mockHapticGenerator))
+                    .isNull();
+            return mockHapticGenerator;
+        }
+
+        private class TestInjectables extends Ringtone.Injectables {
+            @Override
+            public MediaPlayer newMediaPlayer() {
+                assertWithMessage(
+                        "Unexpected MediaPlayer creation. Bug or need expectNewMediaPlayer")
+                        .that(mMockMediaPlayerQueue)
+                        .isNotEmpty();
+                return mMockMediaPlayerQueue.remove();
+            }
+
+            @Override
+            public boolean isHapticGeneratorAvailable() {
+                return hapticGeneratorAvailable;
+            }
+
+            @Override
+            public HapticGenerator createHapticGenerator(MediaPlayer mediaPlayer) {
+                HapticGenerator mockHapticGenerator = mMockHapticGeneratorMap.remove(mediaPlayer);
+                assertWithMessage("Unexpected HapticGenerator creation. "
+                        + "Bug or need expectHapticGenerator")
+                        .that(mockHapticGenerator)
+                        .isNotNull();
+                return mockHapticGenerator;
+            }
+        }
+    }
+
+    /** Mocks don't work directly on native calls, but if they're overridden then it does work. */
+    private static class MediaPlayerMockableNatives extends MediaPlayer {
+        @Override
+        public void setLooping(boolean value) {
+            throw new IllegalStateException("Expected mock to intercept");
+        }
+    }
+}
diff --git a/native/android/performance_hint.cpp b/native/android/performance_hint.cpp
index 27666caa..b3628fa 100644
--- a/native/android/performance_hint.cpp
+++ b/native/android/performance_hint.cpp
@@ -69,7 +69,7 @@
 
     int updateTargetWorkDuration(int64_t targetDurationNanos);
     int reportActualWorkDuration(int64_t actualDurationNanos);
-    int sendHint(int32_t hint);
+    int sendHint(SessionHint hint);
     int setThreads(const int32_t* threadIds, size_t size);
     int getThreadIds(int32_t* const threadIds, size_t* size);
 
@@ -243,7 +243,7 @@
     return 0;
 }
 
-int APerformanceHintSession::sendHint(int32_t hint) {
+int APerformanceHintSession::sendHint(SessionHint hint) {
     if (hint < 0 || hint >= static_cast<int32_t>(mLastHintSentTimestamp.size())) {
         ALOGE("%s: invalid session hint %d", __FUNCTION__, hint);
         return EINVAL;
@@ -335,7 +335,7 @@
     delete session;
 }
 
-int APerformanceHint_sendHint(void* session, int32_t hint) {
+int APerformanceHint_sendHint(void* session, SessionHint hint) {
     return reinterpret_cast<APerformanceHintSession*>(session)->sendHint(hint);
 }
 
diff --git a/native/android/tests/performance_hint/PerformanceHintNativeTest.cpp b/native/android/tests/performance_hint/PerformanceHintNativeTest.cpp
index 321a7dd..791adfd 100644
--- a/native/android/tests/performance_hint/PerformanceHintNativeTest.cpp
+++ b/native/android/tests/performance_hint/PerformanceHintNativeTest.cpp
@@ -127,7 +127,7 @@
     result = APerformanceHint_reportActualWorkDuration(session, -1L);
     EXPECT_EQ(EINVAL, result);
 
-    int hintId = 2;
+    SessionHint hintId = SessionHint::CPU_LOAD_RESET;
     EXPECT_CALL(*iSession, sendHint(Eq(hintId))).Times(Exactly(1));
     result = APerformanceHint_sendHint(session, hintId);
     EXPECT_EQ(0, result);
@@ -140,7 +140,7 @@
     result = APerformanceHint_sendHint(session, hintId);
     EXPECT_EQ(0, result);
 
-    result = APerformanceHint_sendHint(session, -1);
+    result = APerformanceHint_sendHint(session, static_cast<SessionHint>(-1));
     EXPECT_EQ(EINVAL, result);
 
     EXPECT_CALL(*iSession, close()).Times(Exactly(1));
diff --git a/packages/PackageInstaller/AndroidManifest.xml b/packages/PackageInstaller/AndroidManifest.xml
index 9ee6fbd..1edb751 100644
--- a/packages/PackageInstaller/AndroidManifest.xml
+++ b/packages/PackageInstaller/AndroidManifest.xml
@@ -9,6 +9,8 @@
     <uses-permission android:name="android.permission.INSTALL_PACKAGES" />
     <uses-permission android:name="android.permission.DELETE_PACKAGES" />
     <uses-permission android:name="android.permission.READ_INSTALL_SESSIONS" />
+    <uses-permission android:name="android.permission.READ_INSTALLED_SESSION_PATHS" />
+    <uses-permission android:name="android.permission.WAKE_LOCK" />
     <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
     <uses-permission android:name="android.permission.HIDE_NON_SYSTEM_OVERLAY_WINDOWS" />
     <uses-permission android:name="android.permission.USE_RESERVED_DISK" />
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java b/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java
index c81e75b..3ba2acb 100644
--- a/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java
@@ -375,16 +375,15 @@
             final int sessionId = intent.getIntExtra(PackageInstaller.EXTRA_SESSION_ID,
                     -1 /* defaultValue */);
             final SessionInfo info = mInstaller.getSessionInfo(sessionId);
-            final String resolvedBaseCodePath = intent.getStringExtra(
-                    PackageInstaller.EXTRA_RESOLVED_BASE_PATH);
-            if (info == null || !info.isSealed() || resolvedBaseCodePath == null) {
+            String resolvedPath = info.getResolvedBaseApkPath();
+            if (info == null || !info.isSealed() || resolvedPath == null) {
                 Log.w(TAG, "Session " + mSessionId + " in funky state; ignoring");
                 finish();
                 return;
             }
 
             mSessionId = sessionId;
-            packageSource = Uri.fromFile(new File(resolvedBaseCodePath));
+            packageSource = Uri.fromFile(new File(resolvedPath));
             mOriginatingURI = null;
             mReferrerURI = null;
             mPendingUserActionReason = info.getPendingUserActionReason();
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/UninstallUninstalling.java b/packages/PackageInstaller/src/com/android/packageinstaller/UninstallUninstalling.java
index b60aba8..e6710ff 100644
--- a/packages/PackageInstaller/src/com/android/packageinstaller/UninstallUninstalling.java
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/UninstallUninstalling.java
@@ -83,7 +83,7 @@
                 }
 
                 UserManager customUserManager = UninstallUninstalling.this
-                        .createContextAsUser(UserHandle.of(user.getIdentifier()), 0)
+                        .createContextAsUser(user, 0)
                         .getSystemService(UserManager.class);
                 if (customUserManager.isUserOfType(UserManager.USER_TYPE_PROFILE_CLONE)) {
                     isCloneUser = true;
@@ -117,7 +117,7 @@
                 int flags = allUsers ? PackageManager.DELETE_ALL_USERS : 0;
                 flags |= keepData ? PackageManager.DELETE_KEEP_DATA : 0;
 
-                getPackageManager().getPackageInstaller().uninstall(
+                createContextAsUser(user, 0).getPackageManager().getPackageInstaller().uninstall(
                         new VersionedPackage(mAppInfo.packageName,
                                 PackageManager.VERSION_CODE_HIGHEST),
                         flags, pendingIntent.getIntentSender());
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/UninstallerActivity.java b/packages/PackageInstaller/src/com/android/packageinstaller/UninstallerActivity.java
old mode 100755
new mode 100644
index 7250bdd..9c67817
--- a/packages/PackageInstaller/src/com/android/packageinstaller/UninstallerActivity.java
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/UninstallerActivity.java
@@ -367,10 +367,10 @@
                 int flags = mDialogInfo.allUsers ? PackageManager.DELETE_ALL_USERS : 0;
                 flags |= keepData ? PackageManager.DELETE_KEEP_DATA : 0;
 
-                getPackageManager().getPackageInstaller().uninstall(
-                        new VersionedPackage(mDialogInfo.appInfo.packageName,
-                                PackageManager.VERSION_CODE_HIGHEST),
-                        flags, pendingIntent.getIntentSender());
+                createContextAsUser(mDialogInfo.user, 0).getPackageManager().getPackageInstaller()
+                        .uninstall(new VersionedPackage(mDialogInfo.appInfo.packageName,
+                                PackageManager.VERSION_CODE_HIGHEST), flags,
+                                pendingIntent.getIntentSender());
             } catch (Exception e) {
                 notificationManager.cancel(uninstallId);
 
diff --git a/packages/SettingsLib/CollapsingToolbarBaseActivity/src/com/android/settingslib/collapsingtoolbar/CollapsingToolbarBaseActivity.java b/packages/SettingsLib/CollapsingToolbarBaseActivity/src/com/android/settingslib/collapsingtoolbar/CollapsingToolbarBaseActivity.java
index 01f92c4..19b7e85 100644
--- a/packages/SettingsLib/CollapsingToolbarBaseActivity/src/com/android/settingslib/collapsingtoolbar/CollapsingToolbarBaseActivity.java
+++ b/packages/SettingsLib/CollapsingToolbarBaseActivity/src/com/android/settingslib/collapsingtoolbar/CollapsingToolbarBaseActivity.java
@@ -17,6 +17,7 @@
 package com.android.settingslib.collapsingtoolbar;
 
 import android.app.ActionBar;
+import android.content.pm.PackageManager;
 import android.os.Bundle;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -59,7 +60,8 @@
     @Override
     protected void onCreate(@Nullable Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
-        if (mCustomizeLayoutResId > 0 && !BuildCompatUtils.isAtLeastS()) {
+        // for backward compatibility on R devices or wearable devices due to small device size.
+        if (mCustomizeLayoutResId > 0 && (!BuildCompatUtils.isAtLeastS() || isWatch())) {
             super.setContentView(mCustomizeLayoutResId);
             return;
         }
@@ -157,6 +159,14 @@
         return getToolbarDelegate().getAppBarLayout();
     }
 
+    private boolean isWatch() {
+        PackageManager packageManager = getPackageManager();
+        if (packageManager == null) {
+            return false;
+        }
+        return packageManager.hasSystemFeature(PackageManager.FEATURE_WATCH);
+    }
+
     private CollapsingToolbarDelegate getToolbarDelegate() {
         if (mToolbardelegate == null) {
             mToolbardelegate = new CollapsingToolbarDelegate(new DelegateCallback());
diff --git a/packages/SettingsLib/Spa/OWNERS b/packages/SettingsLib/Spa/OWNERS
index 2887872..464328e 100644
--- a/packages/SettingsLib/Spa/OWNERS
+++ b/packages/SettingsLib/Spa/OWNERS
@@ -4,3 +4,6 @@
 hanxu@google.com
 kellyz@google.com
 pierreqian@google.com
+lijun@google.com
+songchenxi@google.com
+cyl@google.com
diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java
index d5386c1..42d94ec 100644
--- a/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java
+++ b/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java
@@ -415,7 +415,7 @@
                                 String.valueOf(Global.Wearable.EARLY_UPDATES_STATUS_ABORTED),
                           }));
         VALIDATORS.put(Global.Wearable.DYNAMIC_COLOR_THEME_ENABLED, BOOLEAN_VALIDATOR);
-	VALIDATORS.put(Global.Wearable.SCREENSHOT_ENABLED, BOOLEAN_VALIDATOR);
+        VALIDATORS.put(Global.Wearable.SCREENSHOT_ENABLED, BOOLEAN_VALIDATOR);
         VALIDATORS.put(Global.Wearable.UPGRADE_DATA_MIGRATION_STATUS,
                        new DiscreteValueValidator(
                         new String[] {
@@ -423,5 +423,6 @@
                             String.valueOf(Global.Wearable.UPGRADE_DATA_MIGRATION_PENDING),
                             String.valueOf(Global.Wearable.UPGRADE_DATA_MIGRATION_DONE)
                         }));
+        VALIDATORS.put(Global.Wearable.DISABLE_AOD_WHILE_PLUGGED, BOOLEAN_VALIDATOR);
     }
 }
diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java
index 85623b2..0aa3860 100644
--- a/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java
+++ b/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java
@@ -219,6 +219,7 @@
         VALIDATORS.put(System.SHOW_BATTERY_PERCENT, BOOLEAN_VALIDATOR);
         VALIDATORS.put(System.NOTIFICATION_LIGHT_PULSE, BOOLEAN_VALIDATOR);
         VALIDATORS.put(System.WEAR_ACCESSIBILITY_GESTURE_ENABLED, BOOLEAN_VALIDATOR);
+        VALIDATORS.put(System.WEAR_ACCESSIBILITY_GESTURE_ENABLED_DURING_OOBE, BOOLEAN_VALIDATOR);
         VALIDATORS.put(System.CLOCKWORK_BLUETOOTH_SETTINGS_PREF, BOOLEAN_VALIDATOR);
         VALIDATORS.put(System.UNREAD_NOTIFICATION_DOT_INDICATOR, BOOLEAN_VALIDATOR);
         VALIDATORS.put(System.AUTO_LAUNCH_MEDIA_CONTROLS, BOOLEAN_VALIDATOR);
diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
index 19f1a86..33ea370 100644
--- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
+++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
@@ -100,6 +100,7 @@
                     Settings.System.MIN_REFRESH_RATE, // depends on hardware capabilities
                     Settings.System.PEAK_REFRESH_RATE, // depends on hardware capabilities
                     Settings.System.SCREEN_BRIGHTNESS_FLOAT,
+                    Settings.System.WEAR_ACCESSIBILITY_GESTURE_ENABLED_DURING_OOBE,
                     Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ,
                     Settings.System.MULTI_AUDIO_FOCUS_ENABLED // form-factor/OEM specific
                     );
@@ -668,7 +669,8 @@
                     Settings.Global.Wearable.ACCESSIBILITY_VIBRATION_WATCH_ENABLED,
                     Settings.Global.Wearable.ACCESSIBILITY_VIBRATION_WATCH_TYPE,
                     Settings.Global.Wearable.ACCESSIBILITY_VIBRATION_WATCH_SPEED,
-                    Settings.Global.Wearable.SCREENSHOT_ENABLED);
+                    Settings.Global.Wearable.SCREENSHOT_ENABLED,
+                    Settings.Global.Wearable.DISABLE_AOD_WHILE_PLUGGED);
 
     private static final Set<String> BACKUP_DENY_LIST_SECURE_SETTINGS =
              newHashSet(
diff --git a/packages/SettingsProvider/test/src/com/android/providers/settings/InstallNonMarketAppsDeprecationTest.java b/packages/SettingsProvider/test/src/com/android/providers/settings/InstallNonMarketAppsDeprecationTest.java
index ff11f70..2b33057 100644
--- a/packages/SettingsProvider/test/src/com/android/providers/settings/InstallNonMarketAppsDeprecationTest.java
+++ b/packages/SettingsProvider/test/src/com/android/providers/settings/InstallNonMarketAppsDeprecationTest.java
@@ -19,6 +19,7 @@
 import static junit.framework.Assert.assertEquals;
 import static junit.framework.Assert.assertFalse;
 import static junit.framework.Assert.assertTrue;
+import static org.junit.Assume.assumeTrue;
 
 import android.content.Context;
 import android.content.pm.UserInfo;
@@ -116,6 +117,8 @@
 
     @Test
     public void testValueForNewUser() throws Exception {
+        assumeTrue(mUm.supportsMultipleUsers());
+
         UserInfo newUser = mUm.createUser("TEST_USER", 0);
         mUsersAddedByTest.add(newUser.id);
         String value = getSecureSettingForUserViaShell(newUser.id);
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index fedfb43..59bfb2e 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -830,6 +830,9 @@
 
     <uses-permission android:name="android.permission.LOG_FOREGROUND_RESOURCE_USE"/>
 
+    <!-- Permission required for CTS test - CtsPackageInstallTestCases -->
+    <uses-permission android:name="android.permission.READ_INSTALLED_SESSION_PATHS" />
+
     <application android:label="@string/app_label"
                 android:theme="@android:style/Theme.DeviceDefault.DayNight"
                 android:defaultToDeviceProtectedStorage="true"
diff --git a/packages/SystemUI/docs/dagger.md b/packages/SystemUI/docs/dagger.md
index 9b4c21e..4a6240b 100644
--- a/packages/SystemUI/docs/dagger.md
+++ b/packages/SystemUI/docs/dagger.md
@@ -108,20 +108,13 @@
 
 ### Using injection with Fragments
 
-Fragments are created as part of the FragmentManager, so they need to be
-setup so the manager knows how to create them. To do that, add a method
-to com.android.systemui.fragments.FragmentService$FragmentCreator that
-returns your fragment class. That is all that is required, once the method
-exists, FragmentService will automatically pick it up and use injection
-whenever your fragment needs to be created.
+Fragments are created as part of the FragmentManager, so injectable Fragments need to be registered
+so the manager knows how to create them. This is done via
+[FragmentService#addFragmentInstantiationProvider](../src/com/android/systemui/fragments/FragmentService.java).
+Pass it the class of your fragment and a `Provider` for your fragment at some time before your
+Fragment is accessed.
 
-```java
-public interface FragmentCreator {
-    NavigationBarFragment createNavigationBar();
-}
-```
-
-If you need to create your fragment (i.e. for the add or replace transaction),
+When you need to create your fragment (i.e. for the add or replace transaction),
 then the FragmentHostManager can do this for you.
 
 ```java
diff --git a/packages/SystemUI/monet/src/com/android/systemui/monet/dynamiccolor/MaterialDynamicColors.java b/packages/SystemUI/monet/src/com/android/systemui/monet/dynamiccolor/MaterialDynamicColors.java
index 5212e8e..106d6e7 100644
--- a/packages/SystemUI/monet/src/com/android/systemui/monet/dynamiccolor/MaterialDynamicColors.java
+++ b/packages/SystemUI/monet/src/com/android/systemui/monet/dynamiccolor/MaterialDynamicColors.java
@@ -16,6 +16,8 @@
 
 package com.android.systemui.monet.dynamiccolor;
 
+import android.os.SystemProperties;
+
 import com.android.systemui.monet.dislike.DislikeAnalyzer;
 import com.android.systemui.monet.hct.Hct;
 import com.android.systemui.monet.hct.ViewingConditions;
@@ -31,7 +33,8 @@
 @SuppressWarnings({"AndroidJdkLibsChecker", "NewApi"})
 public final class MaterialDynamicColors {
     private static final double CONTAINER_ACCENT_TONE_DELTA = 15.0;
-
+    private static final boolean IS_FIDELITY_ON_ALL_VARIANTS = SystemProperties.getBoolean(
+            "persist.fidelity_on_theme_variants", false);
 
     private MaterialDynamicColors() {
     }
@@ -374,6 +377,9 @@
     }
 
     private static boolean isFidelity(DynamicScheme scheme) {
+        if (IS_FIDELITY_ON_ALL_VARIANTS) {
+            return scheme.variant != Variant.NEUTRAL && scheme.variant != Variant.MONOCHROME;
+        }
         return scheme.variant == Variant.FIDELITY || scheme.variant == Variant.CONTENT;
     }
 
diff --git a/packages/SystemUI/proguard.flags b/packages/SystemUI/proguard.flags
index 10bb00c..a8ed843 100644
--- a/packages/SystemUI/proguard.flags
+++ b/packages/SystemUI/proguard.flags
@@ -1,156 +1,13 @@
-# Preserve line number information for debugging stack traces.
--keepattributes SourceFile,LineNumberTable
+-include proguard_common.flags
 
-# Preserve relationship information that can impact simple class naming.
--keepattributes EnclosingMethod,InnerClasses
-
--keep class com.android.systemui.recents.OverviewProxyRecentsImpl
--keep class com.android.systemui.statusbar.car.CarStatusBar
--keep class com.android.systemui.statusbar.phone.CentralSurfaces
 -keep class com.android.systemui.statusbar.tv.TvStatusBar
--keep class ** extends com.android.systemui.SystemUIInitializer {
-    *;
-}
--keep class * extends com.android.systemui.CoreStartable
--keep class * implements com.android.systemui.CoreStartable$Injector
-
-# Needed for builds to properly initialize KeyFrames from xml scene
--keepclassmembers class * extends androidx.constraintlayout.motion.widget.Key {
-  public <init>();
-}
-
-# Needed to ensure callback field references are kept in their respective
-# owning classes when the downstream callback registrars only store weak refs.
-# TODO(b/264686688): Handle these cases with more targeted annotations.
--keepclassmembers,allowaccessmodification class com.android.systemui.**, com.android.keyguard.** {
-  private com.android.keyguard.KeyguardUpdateMonitorCallback *;
-  private com.android.systemui.privacy.PrivacyConfig$Callback *;
-  private com.android.systemui.privacy.PrivacyItemController$Callback *;
-  private com.android.systemui.settings.UserTracker$Callback *;
-  private com.android.systemui.statusbar.phone.StatusBarWindowCallback *;
-  private com.android.systemui.util.service.Observer$Callback *;
-  private com.android.systemui.util.service.ObservableServiceConnection$Callback *;
-}
-# Note that these rules are temporary companions to the above rules, required
-# for cases like Kotlin where fields with anonymous types use the anonymous type
-# rather than the supertype.
--if class * extends com.android.keyguard.KeyguardUpdateMonitorCallback
--keepclassmembers,allowaccessmodification class com.android.systemui.**, com.android.keyguard.** {
-  <1> *;
-}
--if class * extends com.android.systemui.privacy.PrivacyConfig$Callback
--keepclassmembers,allowaccessmodification class com.android.systemui.**, com.android.keyguard.** {
-  <1> *;
-}
--if class * extends com.android.systemui.privacy.PrivacyItemController$Callback
--keepclassmembers,allowaccessmodification class com.android.systemui.**, com.android.keyguard.** {
-  <1> *;
-}
--if class * extends com.android.systemui.settings.UserTracker$Callback
--keepclassmembers,allowaccessmodification class com.android.systemui.**, com.android.keyguard.** {
-  <1> *;
-}
--if class * extends com.android.systemui.statusbar.phone.StatusBarWindowCallback
--keepclassmembers,allowaccessmodification class com.android.systemui.**, com.android.keyguard.** {
-  <1> *;
-}
--if class * extends com.android.systemui.util.service.Observer$Callback
--keepclassmembers,allowaccessmodification class com.android.systemui.**, com.android.keyguard.** {
-  <1> *;
-}
--if class * extends com.android.systemui.util.service.ObservableServiceConnection$Callback
--keepclassmembers,allowaccessmodification class com.android.systemui.**, com.android.keyguard.** {
-  <1> *;
-}
-
--keepclasseswithmembers class * {
-    public <init>(android.content.Context, android.util.AttributeSet);
-}
-
--keep class ** extends androidx.preference.PreferenceFragment
--keep class com.android.systemui.tuner.*
-
-# The plugins subpackage acts as a shared library that might be referenced in
-# dynamically-loaded plugin APKs.
--keep class com.android.systemui.plugins.** {
-    *;
-}
--keep class com.android.systemui.fragments.FragmentService$FragmentCreator {
-    *;
-}
--keep class androidx.core.app.CoreComponentFactory
-
--keep public class * extends com.android.systemui.CoreStartable {
-    public <init>(android.content.Context);
-}
-
-# Keep the wm shell lib
--keep class com.android.wm.shell.*
-# Keep the protolog group methods that are called by the generated code
--keepclassmembers class com.android.wm.shell.protolog.ShellProtoLogGroup {
+-keep class com.android.systemui.SystemUIInitializerImpl {
     *;
 }
 
--keep,allowoptimization,allowaccessmodification class com.android.systemui.dagger.GlobalRootComponent { !synthetic *; }
--keep,allowoptimization,allowaccessmodification class com.android.systemui.dagger.GlobalRootComponent$SysUIComponentImpl { !synthetic *; }
--keep,allowoptimization,allowaccessmodification class com.android.systemui.dagger.Dagger** { !synthetic *; }
--keep,allowoptimization,allowaccessmodification class com.android.systemui.tv.Dagger** { !synthetic *; }
-
-# Prevent optimization or access modification of any referenced code that may
-# conflict with code in the bootclasspath.
-# TODO(b/222468116): Resolve such collisions in the build system.
--keepnames class android.**.nano.** { *; }
--keepnames class com.android.**.nano.** { *; }
--keepnames class com.android.internal.protolog.** { *; }
--keepnames class android.hardware.common.** { *; }
-
-# Allows proguard to make private and protected methods and fields public as
-# part of optimization. This lets proguard inline trivial getter/setter methods.
--allowaccessmodification
-
-# Removes runtime checks added through Kotlin to JVM code genereration to
-# avoid linear growth as more Kotlin code is converted / added to the codebase.
-# These checks are generally applied to Java platform types (values returned
-# from Java code that don't have nullness annotations), but we remove them to
-# avoid code size increases.
-#
-# See also https://kotlinlang.org/docs/reference/java-interop.html
-#
-# TODO(b/199941987): Consider standardizing these rules in a central place as
-# Kotlin gains adoption with other platform targets.
--assumenosideeffects class kotlin.jvm.internal.Intrinsics {
-    # Remove check for method parameters being null
-    static void checkParameterIsNotNull(java.lang.Object, java.lang.String);
-
-    # When a Java platform type is returned and passed to Kotlin NonNull method,
-    # remove the null check
-    static void checkExpressionValueIsNotNull(java.lang.Object, java.lang.String);
-    static void checkNotNullExpressionValue(java.lang.Object, java.lang.String);
-
-    # Remove check that final value returned from method is null, if passing
-    # back Java platform type.
-    static void checkReturnedValueIsNotNull(java.lang.Object, java.lang.String, java.lang.String);
-    static void checkReturnedValueIsNotNull(java.lang.Object, java.lang.String);
-
-    # Null check for accessing a field from a parent class written in Java.
-    static void checkFieldIsNotNull(java.lang.Object, java.lang.String, java.lang.String);
-    static void checkFieldIsNotNull(java.lang.Object, java.lang.String);
-
-    # Removes code generated from !! operator which converts Nullable type to
-    # NonNull type. These would throw an NPE immediate after on access.
-    static void checkNotNull(java.lang.Object, java.lang.String);
-    static void checkNotNullParameter(java.lang.Object, java.lang.String);
-
-    # Removes lateinit var check being used before being set. Check is applied
-    # on every field access without this.
-    static void throwUninitializedPropertyAccessException(java.lang.String);
+-keep class com.android.systemui.tv.TvSystemUIInitializer {
+    *;
 }
-# Strip verbose logs.
--assumenosideeffects class android.util.Log {
-  static *** v(...);
-  static *** isLoggable(...);
-}
--assumenosideeffects class android.util.Slog {
-  static *** v(...);
-}
--maximumremovedandroidloglevel 2
+
+-keep,allowoptimization,allowaccessmodification class com.android.systemui.dagger.DaggerReferenceGlobalRootComponent** { !synthetic *; }
+-keep,allowoptimization,allowaccessmodification class com.android.systemui.tv.DaggerTvGlobalRootComponent** { !synthetic *; }
\ No newline at end of file
diff --git a/packages/SystemUI/proguard_common.flags b/packages/SystemUI/proguard_common.flags
new file mode 100644
index 0000000..1d008cf
--- /dev/null
+++ b/packages/SystemUI/proguard_common.flags
@@ -0,0 +1,141 @@
+# Preserve line number information for debugging stack traces.
+-keepattributes SourceFile,LineNumberTable
+
+-keep class com.android.systemui.VendorServices
+
+# the `#inject` methods are accessed via reflection to work on ContentProviders
+-keepclassmembers class * extends com.android.systemui.dagger.SysUIComponent { void inject(***); }
+
+# Needed for builds to properly initialize KeyFrames from xml scene
+-keepclassmembers class * extends androidx.constraintlayout.motion.widget.Key {
+  public <init>();
+}
+
+# Needed to ensure callback field references are kept in their respective
+# owning classes when the downstream callback registrars only store weak refs.
+# TODO(b/264686688): Handle these cases with more targeted annotations.
+-keepclassmembers,allowaccessmodification class com.android.systemui.**, com.android.keyguard.** {
+  private com.android.keyguard.KeyguardUpdateMonitorCallback *;
+  private com.android.systemui.privacy.PrivacyConfig$Callback *;
+  private com.android.systemui.privacy.PrivacyItemController$Callback *;
+  private com.android.systemui.settings.UserTracker$Callback *;
+  private com.android.systemui.statusbar.phone.StatusBarWindowCallback *;
+  private com.android.systemui.util.service.Observer$Callback *;
+  private com.android.systemui.util.service.ObservableServiceConnection$Callback *;
+}
+# Note that these rules are temporary companions to the above rules, required
+# for cases like Kotlin where fields with anonymous types use the anonymous type
+# rather than the supertype.
+-if class * extends com.android.keyguard.KeyguardUpdateMonitorCallback
+-keepclassmembers,allowaccessmodification class com.android.systemui.**, com.android.keyguard.** {
+  <1> *;
+}
+-if class * extends com.android.systemui.privacy.PrivacyConfig$Callback
+-keepclassmembers,allowaccessmodification class com.android.systemui.**, com.android.keyguard.** {
+  <1> *;
+}
+-if class * extends com.android.systemui.privacy.PrivacyItemController$Callback
+-keepclassmembers,allowaccessmodification class com.android.systemui.**, com.android.keyguard.** {
+  <1> *;
+}
+-if class * extends com.android.systemui.settings.UserTracker$Callback
+-keepclassmembers,allowaccessmodification class com.android.systemui.**, com.android.keyguard.** {
+  <1> *;
+}
+-if class * extends com.android.systemui.statusbar.phone.StatusBarWindowCallback
+-keepclassmembers,allowaccessmodification class com.android.systemui.**, com.android.keyguard.** {
+  <1> *;
+}
+-if class * extends com.android.systemui.util.service.Observer$Callback
+-keepclassmembers,allowaccessmodification class com.android.systemui.**, com.android.keyguard.** {
+  <1> *;
+}
+-if class * extends com.android.systemui.util.service.ObservableServiceConnection$Callback
+-keepclassmembers,allowaccessmodification class com.android.systemui.**, com.android.keyguard.** {
+  <1> *;
+}
+
+-keepclasseswithmembers class * {
+    public <init>(android.content.Context, android.util.AttributeSet);
+}
+
+-keep class ** extends androidx.preference.PreferenceFragment
+-keep class com.android.systemui.tuner.*
+
+# The plugins subpackage acts as a shared library that might be referenced in
+# dynamically-loaded plugin APKs.
+-keep class com.android.systemui.plugins.** {
+    *;
+}
+-keep class com.android.systemui.fragments.FragmentService$FragmentCreator {
+    *;
+}
+-keep class androidx.core.app.CoreComponentFactory
+
+# Keep the wm shell lib
+-keep class com.android.wm.shell.*
+# Keep the protolog group methods that are called by the generated code
+-keepclassmembers class com.android.wm.shell.protolog.ShellProtoLogGroup {
+    *;
+}
+
+# Prevent optimization or access modification of any referenced code that may
+# conflict with code in the bootclasspath.
+# TODO(b/222468116): Resolve such collisions in the build system.
+-keepnames class android.**.nano.** { *; }
+-keepnames class com.android.**.nano.** { *; }
+-keepnames class com.android.internal.protolog.** { *; }
+-keepnames class android.hardware.common.** { *; }
+
+# Allows proguard to make private and protected methods and fields public as
+# part of optimization. This lets proguard inline trivial getter/setter methods.
+-allowaccessmodification
+
+# Removes runtime checks added through Kotlin to JVM code genereration to
+# avoid linear growth as more Kotlin code is converted / added to the codebase.
+# These checks are generally applied to Java platform types (values returned
+# from Java code that don't have nullness annotations), but we remove them to
+# avoid code size increases.
+#
+# See also https://kotlinlang.org/docs/reference/java-interop.html
+#
+# TODO(b/199941987): Consider standardizing these rules in a central place as
+# Kotlin gains adoption with other platform targets.
+-assumenosideeffects class kotlin.jvm.internal.Intrinsics {
+    # Remove check for method parameters being null
+    static void checkParameterIsNotNull(java.lang.Object, java.lang.String);
+
+    # When a Java platform type is returned and passed to Kotlin NonNull method,
+    # remove the null check
+    static void checkExpressionValueIsNotNull(java.lang.Object, java.lang.String);
+    static void checkNotNullExpressionValue(java.lang.Object, java.lang.String);
+
+    # Remove check that final value returned from method is null, if passing
+    # back Java platform type.
+    static void checkReturnedValueIsNotNull(java.lang.Object, java.lang.String, java.lang.String);
+    static void checkReturnedValueIsNotNull(java.lang.Object, java.lang.String);
+
+    # Null check for accessing a field from a parent class written in Java.
+    static void checkFieldIsNotNull(java.lang.Object, java.lang.String, java.lang.String);
+    static void checkFieldIsNotNull(java.lang.Object, java.lang.String);
+
+    # Removes code generated from !! operator which converts Nullable type to
+    # NonNull type. These would throw an NPE immediate after on access.
+    static void checkNotNull(java.lang.Object, java.lang.String);
+    static void checkNotNullParameter(java.lang.Object, java.lang.String);
+
+    # Removes lateinit var check being used before being set. Check is applied
+    # on every field access without this.
+    static void throwUninitializedPropertyAccessException(java.lang.String);
+}
+
+
+# Strip verbose logs.
+-assumenosideeffects class android.util.Log {
+  static *** v(...);
+  static *** isLoggable(...);
+}
+-assumenosideeffects class android.util.Slog {
+  static *** v(...);
+}
+-maximumremovedandroidloglevel 2
diff --git a/packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt b/packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt
index 1661806..e3ca13e 100644
--- a/packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt
+++ b/packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt
@@ -663,7 +663,7 @@
                     "userId: $int1 " +
                     "old: $bool1, " +
                     "new: $bool2 " +
-                    "context: $context"
+                    "context: $str1"
             }
         )
     }
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/OWNERS b/packages/SystemUI/src/com/android/systemui/accessibility/OWNERS
new file mode 100644
index 0000000..1f66c91
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 44215
+
+include /core/java/android/view/accessibility/OWNERS
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
index 63a4fd2..3b38870 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
@@ -47,7 +47,6 @@
 import com.android.systemui.dump.DumpManager;
 import com.android.systemui.flags.FeatureFlags;
 import com.android.systemui.flags.FlagsModule;
-import com.android.systemui.fragments.FragmentService;
 import com.android.systemui.keyboard.KeyboardModule;
 import com.android.systemui.keyguard.data.BouncerViewModule;
 import com.android.systemui.log.dagger.LogModule;
@@ -63,6 +62,7 @@
 import com.android.systemui.qrcodescanner.dagger.QRCodeScannerModule;
 import com.android.systemui.qs.FgsManagerController;
 import com.android.systemui.qs.FgsManagerControllerImpl;
+import com.android.systemui.qs.QSFragmentStartableModule;
 import com.android.systemui.qs.footer.dagger.FooterActionsModule;
 import com.android.systemui.recents.Recents;
 import com.android.systemui.screenrecord.ScreenRecordModule;
@@ -116,16 +116,16 @@
 import com.android.systemui.wmshell.BubblesManager;
 import com.android.wm.shell.bubbles.Bubbles;
 
-import java.util.Optional;
-import java.util.concurrent.Executor;
-
-import javax.inject.Named;
-
 import dagger.Binds;
 import dagger.BindsOptionalOf;
 import dagger.Module;
 import dagger.Provides;
 
+import java.util.Optional;
+import java.util.concurrent.Executor;
+
+import javax.inject.Named;
+
 /**
  * A dagger module for injecting components of System UI that are required by System UI.
  *
@@ -165,6 +165,7 @@
             PolicyModule.class,
             PrivacyModule.class,
             QRCodeScannerModule.class,
+            QSFragmentStartableModule.class,
             ScreenshotModule.class,
             SensorModule.class,
             SecurityRepositoryModule.class,
@@ -194,8 +195,7 @@
             DozeComponent.class,
             ExpandableNotificationRowComponent.class,
             KeyguardBouncerComponent.class,
-            NotificationShelfComponent.class,
-            FragmentService.FragmentCreator.class
+            NotificationShelfComponent.class
         })
 public abstract class SystemUIModule {
 
diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
index 43221a7..3e4e84e 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
+++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
@@ -648,10 +648,11 @@
     // 2300 - stylus
     @JvmField val TRACK_STYLUS_EVER_USED = releasedFlag(2300, "track_stylus_ever_used")
     @JvmField
-    val ENABLE_STYLUS_CHARGING_UI = releasedFlag(2301, "enable_stylus_charging_ui")
+    val ENABLE_STYLUS_CHARGING_UI =
+        unreleasedFlag(2301, "enable_stylus_charging_ui", teamfood = true)
     @JvmField
     val ENABLE_USI_BATTERY_NOTIFICATIONS =
-        releasedFlag(2302, "enable_usi_battery_notifications")
+        unreleasedFlag(2302, "enable_usi_battery_notifications", teamfood = true)
     @JvmField val ENABLE_STYLUS_EDUCATION = unreleasedFlag(2303, "enable_stylus_education")
 
     // 2400 - performance tools and debugging info
diff --git a/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java b/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java
index 6a27ee7..81a5206 100644
--- a/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java
+++ b/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java
@@ -39,16 +39,17 @@
 import com.android.systemui.plugins.Plugin;
 import com.android.systemui.util.leak.LeakDetector;
 
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-import java.lang.reflect.InvocationTargetException;
-import java.util.ArrayList;
-import java.util.HashMap;
-
 import dagger.assisted.Assisted;
 import dagger.assisted.AssistedFactory;
 import dagger.assisted.AssistedInject;
 
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.HashMap;
+
+import javax.inject.Provider;
+
 public class FragmentHostManager {
 
     private final Handler mHandler = new Handler(Looper.getMainLooper());
@@ -322,25 +323,17 @@
             return instantiateWithInjections(context, className, arguments);
         }
 
-        private Fragment instantiateWithInjections(
-                Context context, String className, Bundle args) {
-            FragmentService.FragmentInstantiationInfo fragmentInstantiationInfo =
+        private Fragment instantiateWithInjections(Context context, String className, Bundle args) {
+            Provider<? extends Fragment> fragmentProvider =
                     mManager.getInjectionMap().get(className);
-            if (fragmentInstantiationInfo != null) {
-                try {
-                    Fragment f = (Fragment) fragmentInstantiationInfo
-                            .mMethod
-                            .invoke(fragmentInstantiationInfo.mDaggerComponent);
-                    // Setup the args, taken from Fragment#instantiate.
-                    if (args != null) {
-                        args.setClassLoader(f.getClass().getClassLoader());
-                        f.setArguments(args);
-                    }
-                    return f;
-                } catch (IllegalAccessException | InvocationTargetException e) {
-                    throw new Fragment.InstantiationException("Unable to instantiate " + className,
-                            e);
+            if (fragmentProvider != null) {
+                Fragment f = fragmentProvider.get();
+                // Setup the args, taken from Fragment#instantiate.
+                if (args != null) {
+                    args.setClassLoader(f.getClass().getClassLoader());
+                    f.setArguments(args);
                 }
+                return f;
             }
             return Fragment.instantiate(context, className, args);
         }
diff --git a/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java b/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java
index d302b13a..a75c056 100644
--- a/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java
+++ b/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java
@@ -24,16 +24,12 @@
 import com.android.systemui.Dumpable;
 import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.dump.DumpManager;
-import com.android.systemui.qs.QSFragment;
 import com.android.systemui.statusbar.policy.ConfigurationController;
 
 import java.io.PrintWriter;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
 
 import javax.inject.Inject;
-
-import dagger.Subcomponent;
+import javax.inject.Provider;
 
 /**
  * Holds a map of root views to FragmentHostStates and generates them as needed.
@@ -49,9 +45,9 @@
      * A map with the means to create fragments via Dagger injection.
      *
      * key: the fragment class name.
-     * value: see {@link FragmentInstantiationInfo}.
+     * value: A {@link Provider} for the Fragment
      */
-    private final ArrayMap<String, FragmentInstantiationInfo> mInjectionMap = new ArrayMap<>();
+    private final ArrayMap<String, Provider<? extends Fragment>> mInjectionMap = new ArrayMap<>();
     private final Handler mHandler = new Handler();
     private final FragmentHostManager.Factory mFragmentHostManagerFactory;
 
@@ -67,38 +63,31 @@
 
     @Inject
     public FragmentService(
-            FragmentCreator.Factory fragmentCreatorFactory,
             FragmentHostManager.Factory fragmentHostManagerFactory,
             ConfigurationController configurationController,
             DumpManager dumpManager) {
         mFragmentHostManagerFactory = fragmentHostManagerFactory;
-        addFragmentInstantiationProvider(fragmentCreatorFactory.build());
         configurationController.addCallback(mConfigurationListener);
 
-        dumpManager.registerDumpable(getClass().getSimpleName(), this);
+        dumpManager.registerNormalDumpable(this);
     }
 
-    ArrayMap<String, FragmentInstantiationInfo> getInjectionMap() {
+    ArrayMap<String, Provider<? extends Fragment>> getInjectionMap() {
         return mInjectionMap;
     }
 
     /**
      * Adds a new Dagger component object that provides method(s) to create fragments via injection.
      */
-    public void addFragmentInstantiationProvider(Object daggerComponent) {
-        for (Method method : daggerComponent.getClass().getDeclaredMethods()) {
-            if (Fragment.class.isAssignableFrom(method.getReturnType())
-                    && (method.getModifiers() & Modifier.PUBLIC) != 0) {
-                String fragmentName = method.getReturnType().getName();
-                if (mInjectionMap.containsKey(fragmentName)) {
-                    Log.w(TAG, "Fragment " + fragmentName + " is already provided by different"
-                            + " Dagger component; Not adding method");
-                    continue;
-                }
-                mInjectionMap.put(
-                        fragmentName, new FragmentInstantiationInfo(method, daggerComponent));
-            }
+    public void addFragmentInstantiationProvider(
+            Class<?> fragmentCls, Provider<? extends Fragment> provider) {
+        String fragmentName = fragmentCls.getName();
+        if (mInjectionMap.containsKey(fragmentName)) {
+            Log.w(TAG, "Fragment " + fragmentName + " is already provided by different"
+                    + " Dagger component; Not adding method");
+            return;
         }
+        mInjectionMap.put(fragmentName, provider);
     }
 
     public FragmentHostManager getFragmentHostManager(View view) {
@@ -132,22 +121,6 @@
         }
     }
 
-    /**
-     * The subcomponent of dagger that holds all fragments that need injection.
-     */
-    @Subcomponent
-    public interface FragmentCreator {
-        /** Factory for creating a FragmentCreator. */
-        @Subcomponent.Factory
-        interface Factory {
-            FragmentCreator build();
-        }
-        /**
-         * Inject a QSFragment.
-         */
-        QSFragment createQSFragment();
-    }
-
     private class FragmentHostState {
         private final View mView;
 
@@ -170,16 +143,4 @@
             mFragmentHostManager.onConfigurationChanged(newConfig);
         }
     }
-
-    /** An object containing the information needed to instantiate a fragment. */
-    static class FragmentInstantiationInfo {
-        /** The method that returns a newly-created fragment of the given class. */
-        final Method mMethod;
-        /** The Dagger component that the method should be invoked on. */
-        final Object mDaggerComponent;
-        FragmentInstantiationInfo(Method method, Object daggerComponent) {
-            this.mMethod = method;
-            this.mDaggerComponent = daggerComponent;
-        }
-    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index b1efdd7..ea5fc1a 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -39,9 +39,9 @@
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.ValueAnimator;
-import android.app.ActivityTaskManager;
 import android.app.AlarmManager;
 import android.app.BroadcastOptions;
+import android.app.IActivityTaskManager;
 import android.app.PendingIntent;
 import android.app.StatusBarManager;
 import android.app.WindowConfiguration;
@@ -1183,6 +1183,7 @@
 
     private Lazy<ActivityLaunchAnimator> mActivityLaunchAnimator;
     private Lazy<ScrimController> mScrimControllerLazy;
+    private IActivityTaskManager mActivityTaskManagerService;
 
     /**
      * Injected constructor. See {@link KeyguardModule}.
@@ -1214,7 +1215,8 @@
             Lazy<ShadeController> shadeControllerLazy,
             Lazy<NotificationShadeWindowController> notificationShadeWindowControllerLazy,
             Lazy<ActivityLaunchAnimator> activityLaunchAnimator,
-            Lazy<ScrimController> scrimControllerLazy) {
+            Lazy<ScrimController> scrimControllerLazy,
+            IActivityTaskManager activityTaskManagerService) {
         mContext = context;
         mUserTracker = userTracker;
         mFalsingCollector = falsingCollector;
@@ -1262,6 +1264,7 @@
 
         mActivityLaunchAnimator = activityLaunchAnimator;
         mScrimControllerLazy = scrimControllerLazy;
+        mActivityTaskManagerService = activityTaskManagerService;
 
         mPowerButtonY = context.getResources().getDimensionPixelSize(
                 R.dimen.physical_power_button_center_screen_location_y);
@@ -1805,12 +1808,17 @@
     }
 
     /**
-     * Is the keyguard currently showing and not being force hidden?
+     * Is the keyguard currently showing, and not occluded (no activity is drawing over the
+     * lockscreen).
      */
     public boolean isShowingAndNotOccluded() {
         return mShowing && !mOccluded;
     }
 
+    public boolean isShowing() {
+        return mShowing;
+    }
+
     public boolean isOccludeAnimationPlaying() {
         return mOccludeAnimationPlaying;
     }
@@ -2424,7 +2432,7 @@
                 Log.d(TAG, "updateActivityLockScreenState(" + showing + ", " + aodShowing + ")");
             }
             try {
-                ActivityTaskManager.getService().setLockScreenShown(showing, aodShowing);
+                mActivityTaskManagerService.setLockScreenShown(showing, aodShowing);
             } catch (RemoteException e) {
             }
         });
@@ -2540,7 +2548,7 @@
             final int keyguardFlag = flags;
             mUiBgExecutor.execute(() -> {
                 try {
-                    ActivityTaskManager.getService().keyguardGoingAway(keyguardFlag);
+                    mActivityTaskManagerService.keyguardGoingAway(keyguardFlag);
                 } catch (RemoteException e) {
                     Log.e(TAG, "Error while calling WindowManager", e);
                 }
@@ -2572,18 +2580,16 @@
         synchronized (KeyguardViewMediator.this) {
             if (DEBUG) Log.d(TAG, "handleHide");
 
-            mHiding = true;
-
             if (mShowing && !mOccluded) {
+                mHiding = true;
                 mKeyguardGoingAwayRunnable.run();
             } else {
-                // TODO(bc-unlock): Fill parameters
-                mNotificationShadeWindowControllerLazy.get().batchApplyWindowLayoutParams(() -> {
-                    handleStartKeyguardExitAnimation(
-                            SystemClock.uptimeMillis() + mHideAnimation.getStartOffset(),
-                            mHideAnimation.getDuration(), null /* apps */, null /* wallpapers */,
-                            null /* nonApps */, null /* finishedCallback */);
-                });
+                Log.d(TAG, "Hiding keyguard while occluded. Just hide the keyguard view and exit.");
+
+                mKeyguardViewControllerLazy.get().hide(
+                        SystemClock.uptimeMillis() + mHideAnimation.getStartOffset(),
+                        mHideAnimation.getDuration());
+                onKeyguardExitFinished();
             }
 
             // It's possible that the device was unlocked (via BOUNCER or Fingerprint) while
@@ -2886,7 +2892,7 @@
                 flags |= KEYGUARD_GOING_AWAY_FLAG_TO_LAUNCHER_CLEAR_SNAPSHOT;
             }
 
-            ActivityTaskManager.getService().keyguardGoingAway(flags);
+            mActivityTaskManagerService.keyguardGoingAway(flags);
             mKeyguardStateController.notifyKeyguardGoingAway(true);
         } catch (RemoteException e) {
             mSurfaceBehindRemoteAnimationRequested = false;
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
index 6ac51cd..8764f12 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
@@ -16,6 +16,7 @@
 
 package com.android.systemui.keyguard.dagger;
 
+import android.app.IActivityTaskManager;
 import android.app.trust.TrustManager;
 import android.content.Context;
 import android.os.PowerManager;
@@ -119,7 +120,8 @@
             Lazy<ShadeController> shadeController,
             Lazy<NotificationShadeWindowController> notificationShadeWindowController,
             Lazy<ActivityLaunchAnimator> activityLaunchAnimator,
-            Lazy<ScrimController> scrimControllerLazy) {
+            Lazy<ScrimController> scrimControllerLazy,
+            IActivityTaskManager activityTaskManagerService) {
         return new KeyguardViewMediator(
                 context,
                 userTracker,
@@ -149,7 +151,8 @@
                 shadeController,
                 notificationShadeWindowController,
                 activityLaunchAnimator,
-                scrimControllerLazy);
+                scrimControllerLazy,
+                activityTaskManagerService);
     }
 
     /** */
diff --git a/packages/SystemUI/src/com/android/systemui/media/OWNERS b/packages/SystemUI/src/com/android/systemui/media/OWNERS
index 69ea57b..b2d00df 100644
--- a/packages/SystemUI/src/com/android/systemui/media/OWNERS
+++ b/packages/SystemUI/src/com/android/systemui/media/OWNERS
@@ -1 +1,5 @@
 per-file MediaProjectionPermissionActivity.java = michaelwr@google.com
+
+# Haptics team also works on Ringtone
+per-file NotificationPlayer.java = file:/services/core/java/com/android/server/vibrator/OWNERS
+per-file RingtonePlayer.java = file:/services/core/java/com/android/server/vibrator/OWNERS
diff --git a/packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java b/packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java
index 2a8168b..d4b30d3 100644
--- a/packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java
+++ b/packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java
@@ -96,10 +96,11 @@
                 @Nullable VolumeShaper.Configuration volumeShaperConfig) {
             mToken = token;
 
-            mRingtone = new Ringtone(getContextForUser(user), false);
-            mRingtone.setAudioAttributesField(aa);
-            mRingtone.setUri(uri, volumeShaperConfig);
-            mRingtone.createLocalMediaPlayer();
+            mRingtone = new Ringtone.Builder(getContextForUser(user), Ringtone.MEDIA_SOUND, aa)
+                    .setUri(uri)
+                    .setLocalOnly()
+                    .setVolumeShaperConfig(volumeShaperConfig)
+                    .build();
         }
 
         @Override
@@ -116,11 +117,14 @@
         @Override
         public void play(IBinder token, Uri uri, AudioAttributes aa, float volume, boolean looping)
                 throws RemoteException {
-            playWithVolumeShaping(token, uri, aa, volume, looping, null);
+            playWithVolumeShaping(token, uri, aa, volume, looping, /* hapticGenerator= */ false,
+                    null);
         }
+
         @Override
         public void playWithVolumeShaping(IBinder token, Uri uri, AudioAttributes aa, float volume,
-                boolean looping, @Nullable VolumeShaper.Configuration volumeShaperConfig)
+                boolean looping, boolean isHapticGeneratorEnabled,
+                @Nullable VolumeShaper.Configuration volumeShaperConfig)
                 throws RemoteException {
             if (LOGD) {
                 Log.d(TAG, "play(token=" + token + ", uri=" + uri + ", uid="
@@ -138,6 +142,7 @@
             }
             client.mRingtone.setLooping(looping);
             client.mRingtone.setVolume(volume);
+            client.mRingtone.setHapticGeneratorEnabled(isHapticGeneratorEnabled);
             client.mRingtone.play();
         }
 
@@ -169,18 +174,36 @@
         }
 
         @Override
-        public void setPlaybackProperties(IBinder token, float volume, boolean looping,
-                boolean hapticGeneratorEnabled) {
+        public void setHapticGeneratorEnabled(IBinder token, boolean hapticGeneratorEnabled) {
+            Client client;
+            synchronized (mClients) {
+                client = mClients.get(token);
+            }
+            if (client != null) {
+                client.mRingtone.setHapticGeneratorEnabled(hapticGeneratorEnabled);
+            }
+        }
+
+        @Override
+        public void setLooping(IBinder token, boolean looping) {
+            Client client;
+            synchronized (mClients) {
+                client = mClients.get(token);
+            }
+            if (client != null) {
+                client.mRingtone.setLooping(looping);
+            }
+        }
+
+        @Override
+        public void setVolume(IBinder token, float volume) {
             Client client;
             synchronized (mClients) {
                 client = mClients.get(token);
             }
             if (client != null) {
                 client.mRingtone.setVolume(volume);
-                client.mRingtone.setLooping(looping);
-                client.mRingtone.setHapticGeneratorEnabled(hapticGeneratorEnabled);
             }
-            // else no client for token when setting playback properties but will be set at play()
         }
 
         @Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragmentStartable.kt b/packages/SystemUI/src/com/android/systemui/qs/QSFragmentStartable.kt
new file mode 100644
index 0000000..253560b
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragmentStartable.kt
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs
+
+import com.android.systemui.CoreStartable
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.fragments.FragmentService
+import dagger.Binds
+import dagger.Module
+import dagger.multibindings.ClassKey
+import dagger.multibindings.IntoMap
+import javax.inject.Inject
+import javax.inject.Provider
+
+@SysUISingleton
+class QSFragmentStartable
+@Inject
+constructor(
+    private val fragmentService: FragmentService,
+    private val qsFragmentProvider: Provider<QSFragment>
+) : CoreStartable {
+    override fun start() {
+        fragmentService.addFragmentInstantiationProvider(QSFragment::class.java, qsFragmentProvider)
+    }
+}
+
+@Module
+interface QSFragmentStartableModule {
+    @Binds
+    @IntoMap
+    @ClassKey(QSFragmentStartable::class)
+    fun bindsQSFragmentStartable(startable: QSFragmentStartable): CoreStartable
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
index aabe0cb..cfbe055 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
@@ -229,6 +229,7 @@
 import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController;
 import com.android.systemui.statusbar.phone.dagger.CentralSurfacesComponent;
 import com.android.systemui.statusbar.phone.dagger.StatusBarPhoneModule;
+import com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragment;
 import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallController;
 import com.android.systemui.statusbar.policy.BatteryController;
 import com.android.systemui.statusbar.policy.BrightnessMirrorController;
@@ -1627,7 +1628,9 @@
             }
         }
         mCentralSurfacesComponent = mCentralSurfacesComponentFactory.create();
-        mFragmentService.addFragmentInstantiationProvider(mCentralSurfacesComponent);
+        mFragmentService.addFragmentInstantiationProvider(
+                CollapsedStatusBarFragment.class,
+                mCentralSurfacesComponent::createCollapsedStatusBarFragment);
 
         mNotificationShadeWindowView = mCentralSurfacesComponent.getNotificationShadeWindowView();
         mNotificationShadeWindowViewController = mCentralSurfacesComponent
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/OWNERS b/packages/SystemUI/tests/src/com/android/systemui/accessibility/OWNERS
new file mode 100644
index 0000000..a2001e6
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/view/accessibility/OWNERS
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/fragments/FragmentServiceTest.kt b/packages/SystemUI/tests/src/com/android/systemui/fragments/FragmentServiceTest.kt
index a2dc1eb..4ba1bc6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/fragments/FragmentServiceTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/fragments/FragmentServiceTest.kt
@@ -5,7 +5,6 @@
 import android.test.suitebuilder.annotation.SmallTest
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.dump.DumpManager
-import com.android.systemui.qs.QSFragment
 import com.android.systemui.util.mockito.mock
 import com.google.common.truth.Truth.assertThat
 import org.junit.Before
@@ -13,9 +12,7 @@
 
 @SmallTest
 class FragmentServiceTest : SysuiTestCase() {
-    private val fragmentCreator = TestFragmentCreator()
-    private val fragmenetHostManagerFactory: FragmentHostManager.Factory = mock()
-    private val fragmentCreatorFactory = FragmentService.FragmentCreator.Factory { fragmentCreator }
+    private val fragmentHostManagerFactory: FragmentHostManager.Factory = mock()
 
     private lateinit var fragmentService: FragmentService
 
@@ -25,65 +22,29 @@
             Looper.prepare()
         }
 
-        fragmentService =
-            FragmentService(
-                fragmentCreatorFactory,
-                fragmenetHostManagerFactory,
-                mock(),
-                DumpManager()
-            )
-    }
-
-    @Test
-    fun constructor_addsFragmentCreatorMethodsToMap() {
-        val map = fragmentService.injectionMap
-        assertThat(map).hasSize(2)
-        assertThat(map.keys).contains(QSFragment::class.java.name)
-        assertThat(map.keys).contains(TestFragmentInCreator::class.java.name)
+        fragmentService = FragmentService(fragmentHostManagerFactory, mock(), DumpManager())
     }
 
     @Test
     fun addFragmentInstantiationProvider_objectHasNoFragmentMethods_nothingAdded() {
-        fragmentService.addFragmentInstantiationProvider(Object())
+        fragmentService.addFragmentInstantiationProvider(TestFragment::class.java) {
+            TestFragment()
+        }
 
-        assertThat(fragmentService.injectionMap).hasSize(2)
-    }
-
-    @Test
-    fun addFragmentInstantiationProvider_objectHasFragmentMethods_methodsAdded() {
-        fragmentService.addFragmentInstantiationProvider(
-            @Suppress("unused")
-            object : Any() {
-                fun createTestFragment2() = TestFragment2()
-                fun createTestFragment3() = TestFragment3()
-            }
-        )
-
-        val map = fragmentService.injectionMap
-        assertThat(map).hasSize(4)
-        assertThat(map.keys).contains(TestFragment2::class.java.name)
-        assertThat(map.keys).contains(TestFragment3::class.java.name)
+        assertThat(fragmentService.injectionMap).hasSize(1)
     }
 
     @Test
     fun addFragmentInstantiationProvider_objectFragmentMethodsAlreadyProvided_nothingAdded() {
-        fragmentService.addFragmentInstantiationProvider(
-            @Suppress("unused")
-            object : Any() {
-                fun createTestFragment() = TestFragmentInCreator()
-            }
-        )
+        fragmentService.addFragmentInstantiationProvider(TestFragment::class.java) {
+            TestFragment()
+        }
+        fragmentService.addFragmentInstantiationProvider(TestFragment::class.java) {
+            TestFragment()
+        }
 
-        assertThat(fragmentService.injectionMap).hasSize(2)
+        assertThat(fragmentService.injectionMap).hasSize(1)
     }
 
-    class TestFragmentCreator : FragmentService.FragmentCreator {
-        override fun createQSFragment(): QSFragment = mock()
-        @Suppress("unused")
-        fun createTestFragment(): TestFragmentInCreator = TestFragmentInCreator()
-    }
-
-    class TestFragmentInCreator : Fragment()
-    class TestFragment2 : Fragment()
-    class TestFragment3 : Fragment()
+    class TestFragment : Fragment()
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
index c93e677..b00b273 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
@@ -25,21 +25,28 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.Mockito.atLeast;
+import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.inOrder;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 import android.app.IActivityManager;
+import android.app.IActivityTaskManager;
 import android.app.admin.DevicePolicyManager;
 import android.app.trust.TrustManager;
 import android.os.PowerManager;
 import android.os.PowerManager.WakeLock;
+import android.os.RemoteException;
 import android.telephony.TelephonyManager;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
@@ -89,9 +96,12 @@
 import com.android.systemui.util.concurrency.FakeExecutor;
 import com.android.systemui.util.time.FakeSystemClock;
 
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.InOrder;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
@@ -131,6 +141,7 @@
     private @Mock DreamOverlayStateController mDreamOverlayStateController;
     private @Mock ActivityLaunchAnimator mActivityLaunchAnimator;
     private @Mock ScrimController mScrimController;
+    private @Mock IActivityTaskManager mActivityTaskManagerService;
     private @Mock SysuiColorExtractor mColorExtractor;
     private @Mock AuthController mAuthController;
     private @Mock ShadeExpansionStateManager mShadeExpansionStateManager;
@@ -142,6 +153,9 @@
 
     private @Mock CentralSurfaces mCentralSurfaces;
 
+    /** Most recent value passed to {@link KeyguardStateController#notifyKeyguardGoingAway}. */
+    private boolean mKeyguardGoingAway = false;
+
     @Before
     public void setUp() throws Exception {
         MockitoAnnotations.initMocks(this);
@@ -163,9 +177,38 @@
 
         DejankUtils.setImmediate(true);
 
+        // Keep track of what we told KeyguardStateController about whether we're going away or
+        // not.
+        mKeyguardGoingAway = false;
+        doAnswer(invocation -> {
+            mKeyguardGoingAway = invocation.getArgument(0);
+            return null;
+        }).when(mKeyguardStateController).notifyKeyguardGoingAway(anyBoolean());
+
         createAndStartViewMediator();
     }
 
+    /**
+     * After each test, verify that System UI's going away/showing state matches the most recent
+     * calls we made to ATMS.
+     *
+     * This will help us catch showing and going away state mismatch issues.
+     */
+    @After
+    public void assertATMSAndKeyguardViewMediatorStatesMatch() {
+        try {
+            if (mKeyguardGoingAway) {
+                assertATMSKeyguardGoingAway();
+            } else {
+                assertATMSLockScreenShowing(mViewMediator.isShowing());
+            }
+
+        } catch (Exception e) {
+            // Just so we don't have to add the exception signature to every test.
+            fail();
+        }
+    }
+
     @Test
     public void testOnGoingToSleep_UpdatesKeyguardGoingAway() {
         mViewMediator.onStartedGoingToSleep(OFF_BECAUSE_OF_USER);
@@ -410,38 +453,7 @@
     public void testStartKeyguardExitAnimation_expectSurfaceBehindRemoteAnimation() {
         startMockKeyguardExitAnimation();
         assertTrue(mViewMediator.isAnimatingBetweenKeyguardAndSurfaceBehind());
-    }
 
-    /**
-     * Configures mocks appropriately, then starts the keyguard exit animation.
-     */
-    private void startMockKeyguardExitAnimation() {
-        mViewMediator.onSystemReady();
-        TestableLooper.get(this).processAllMessages();
-
-        mViewMediator.setShowingLocked(true);
-
-        RemoteAnimationTarget[] apps = new RemoteAnimationTarget[]{
-                mock(RemoteAnimationTarget.class)
-        };
-        RemoteAnimationTarget[] wallpapers = new RemoteAnimationTarget[]{
-                mock(RemoteAnimationTarget.class)
-        };
-        IRemoteAnimationFinishedCallback callback = mock(IRemoteAnimationFinishedCallback.class);
-
-        when(mKeyguardStateController.isKeyguardGoingAway()).thenReturn(true);
-        mViewMediator.startKeyguardExitAnimation(TRANSIT_OLD_KEYGUARD_GOING_AWAY, apps, wallpapers,
-                null, callback);
-        TestableLooper.get(this).processAllMessages();
-    }
-
-    /**
-     * Configures mocks appropriately, then cancels the keyguard exit animation.
-     */
-    private void cancelMockKeyguardExitAnimation() {
-        when(mKeyguardStateController.isKeyguardGoingAway()).thenReturn(false);
-        mViewMediator.cancelKeyguardExitAnimation();
-        TestableLooper.get(this).processAllMessages();
     }
 
     @Test
@@ -515,6 +527,107 @@
         verify(mStatusBarKeyguardViewManager, never()).reset(anyBoolean());
     }
 
+    @Test
+    @TestableLooper.RunWithLooper(setAsMainLooper = true)
+    public void testStartKeyguardExitAnimation_thenCancelImmediately_doesNotResetAndUpdatesWM() {
+        startMockKeyguardExitAnimation();
+        cancelMockKeyguardExitAnimation();
+
+        // This will trigger doKeyguardLocked and we can verify that we ask ATMS to show the
+        // keyguard explicitly, even though we're already showing, because we cancelled immediately.
+        mViewMediator.onSystemReady();
+        reset(mActivityTaskManagerService);
+        processAllMessagesAndBgExecutorMessages();
+
+        verify(mStatusBarKeyguardViewManager, never()).reset(anyBoolean());
+        assertATMSAndKeyguardViewMediatorStatesMatch();
+    }
+
+    /**
+     * Interactions with the ActivityTaskManagerService and others are posted to an executor that
+     * doesn't use the testable looper. Use this method to ensure those are run as well.
+     */
+    private void processAllMessagesAndBgExecutorMessages() {
+        TestableLooper.get(this).processAllMessages();
+        mUiBgExecutor.runAllReady();
+    }
+
+    /**
+     * Configures mocks appropriately, then starts the keyguard exit animation.
+     */
+    private void startMockKeyguardExitAnimation() {
+        mViewMediator.onSystemReady();
+        processAllMessagesAndBgExecutorMessages();
+
+        mViewMediator.setShowingLocked(true);
+
+        RemoteAnimationTarget[] apps = new RemoteAnimationTarget[]{
+                mock(RemoteAnimationTarget.class)
+        };
+        RemoteAnimationTarget[] wallpapers = new RemoteAnimationTarget[]{
+                mock(RemoteAnimationTarget.class)
+        };
+        IRemoteAnimationFinishedCallback callback = mock(IRemoteAnimationFinishedCallback.class);
+
+        when(mKeyguardStateController.isKeyguardGoingAway()).thenReturn(true);
+        mViewMediator.startKeyguardExitAnimation(TRANSIT_OLD_KEYGUARD_GOING_AWAY, apps, wallpapers,
+                null, callback);
+        processAllMessagesAndBgExecutorMessages();
+    }
+
+    /**
+     * Configures mocks appropriately, then cancels the keyguard exit animation.
+     */
+    private void cancelMockKeyguardExitAnimation() {
+        when(mKeyguardStateController.isKeyguardGoingAway()).thenReturn(false);
+        mViewMediator.cancelKeyguardExitAnimation();
+        processAllMessagesAndBgExecutorMessages();
+    }
+    /**
+     * Asserts the last value passed to ATMS#setLockScreenShown. This should be confirmed alongside
+     * {@link KeyguardViewMediator#isShowingAndNotOccluded()} to verify that state is not mismatched
+     * between SysUI and WM.
+     */
+    private void assertATMSLockScreenShowing(boolean showing)
+            throws RemoteException {
+        // ATMS is called via bgExecutor, so make sure to run all of those calls first.
+        processAllMessagesAndBgExecutorMessages();
+
+        final InOrder orderedSetLockScreenShownCalls = inOrder(mActivityTaskManagerService);
+        final ArgumentCaptor<Boolean> showingCaptor = ArgumentCaptor.forClass(Boolean.class);
+        orderedSetLockScreenShownCalls
+                .verify(mActivityTaskManagerService, atLeastOnce())
+                .setLockScreenShown(showingCaptor.capture(), anyBoolean());
+
+        // The captor will have the most recent setLockScreenShown call's value.
+        assertEquals(showing, showingCaptor.getValue());
+
+        // We're now just after the last setLockScreenShown call. If we expect the lockscreen to be
+        // showing, ensure that we didn't subsequently ask for it to go away.
+        if (showing) {
+            orderedSetLockScreenShownCalls.verify(mActivityTaskManagerService, never())
+                    .keyguardGoingAway(anyInt());
+        }
+    }
+
+    /**
+     * Asserts that we eventually called ATMS#keyguardGoingAway and did not subsequently call
+     * ATMS#setLockScreenShown(true) which would cancel the going away.
+     */
+    private void assertATMSKeyguardGoingAway() throws RemoteException {
+        // ATMS is called via bgExecutor, so make sure to run all of those calls first.
+        processAllMessagesAndBgExecutorMessages();
+
+        final InOrder orderedGoingAwayCalls = inOrder(mActivityTaskManagerService);
+        orderedGoingAwayCalls.verify(mActivityTaskManagerService, atLeastOnce())
+                .keyguardGoingAway(anyInt());
+
+        // Advance the inOrder to just past the last goingAway call. Let's make sure we didn't
+        // re-show the lockscreen, which would cancel going away.
+        orderedGoingAwayCalls.verify(mActivityTaskManagerService, never())
+                .setLockScreenShown(eq(true), anyBoolean());
+    }
+
     private void createAndStartViewMediator() {
         mViewMediator = new KeyguardViewMediator(
                 mContext,
@@ -545,7 +658,8 @@
                 () -> mShadeController,
                 () -> mNotificationShadeWindowController,
                 () -> mActivityLaunchAnimator,
-                () -> mScrimController);
+                () -> mScrimController,
+                mActivityTaskManagerService);
         mViewMediator.start();
 
         mViewMediator.registerCentralSurfaces(mCentralSurfaces, null, null, null, null, null);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/OWNERS b/packages/SystemUI/tests/src/com/android/systemui/media/OWNERS
new file mode 100644
index 0000000..142862d
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/OWNERS
@@ -0,0 +1,2 @@
+# Haptics team also works on Ringtones (RingtonePlayer/NotificationPlayer)
+file:/services/core/java/com/android/server/vibrator/OWNERS
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 5417009..8473ab7 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -637,6 +637,37 @@
         }
     }
 
+    private void onPackageRemovedLocked(String packageName) {
+        final AccessibilityUserState userState = getCurrentUserState();
+        final Predicate<ComponentName> filter =
+                component -> component != null && component.getPackageName().equals(
+                        packageName);
+        userState.mBindingServices.removeIf(filter);
+        userState.mCrashedServices.removeIf(filter);
+        final Iterator<ComponentName> it = userState.mEnabledServices.iterator();
+        boolean anyServiceRemoved = false;
+        while (it.hasNext()) {
+            final ComponentName comp = it.next();
+            final String compPkg = comp.getPackageName();
+            if (compPkg.equals(packageName)) {
+                it.remove();
+                userState.mTouchExplorationGrantedServices.remove(comp);
+                anyServiceRemoved = true;
+            }
+        }
+        if (anyServiceRemoved) {
+            // Update the enabled services setting.
+            persistComponentNamesToSettingLocked(
+                    Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
+                    userState.mEnabledServices, mCurrentUserId);
+            // Update the touch exploration granted services setting.
+            persistComponentNamesToSettingLocked(
+                    Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES,
+                    userState.mTouchExplorationGrantedServices, mCurrentUserId);
+            onUserStateChangedLocked(userState);
+        }
+    }
+
     private void registerBroadcastReceivers() {
         PackageMonitor monitor = new PackageMonitor() {
             @Override
@@ -709,34 +740,7 @@
                     if (userId != mCurrentUserId) {
                         return;
                     }
-                    final AccessibilityUserState userState = getUserStateLocked(userId);
-                    final Predicate<ComponentName> filter =
-                            component -> component != null && component.getPackageName().equals(
-                                    packageName);
-                    userState.mBindingServices.removeIf(filter);
-                    userState.mCrashedServices.removeIf(filter);
-                    final Iterator<ComponentName> it = userState.mEnabledServices.iterator();
-                    boolean anyServiceRemoved = false;
-                    while (it.hasNext()) {
-                        final ComponentName comp = it.next();
-                        final String compPkg = comp.getPackageName();
-                        if (compPkg.equals(packageName)) {
-                            it.remove();
-                            userState.mTouchExplorationGrantedServices.remove(comp);
-                            anyServiceRemoved = true;
-                        }
-                    }
-                    if (anyServiceRemoved) {
-                        // Update the enabled services setting.
-                        persistComponentNamesToSettingLocked(
-                                Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
-                                userState.mEnabledServices, userId);
-                        // Update the touch exploration granted services setting.
-                        persistComponentNamesToSettingLocked(
-                                Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES,
-                                userState.mTouchExplorationGrantedServices, userId);
-                        onUserStateChangedLocked(userState);
-                    }
+                    onPackageRemovedLocked(packageName);
                 }
             }
 
@@ -799,6 +803,16 @@
                         }
                     }
                 }
+
+                @Override
+                public void onPackageRemoved(String packageName, int uid) {
+                    final int userId = UserHandle.getUserId(uid);
+                    synchronized (mLock) {
+                        if (userId == mCurrentUserId) {
+                            onPackageRemovedLocked(packageName);
+                        }
+                    }
+                }
             });
         }
 
diff --git a/services/backup/OWNERS b/services/backup/OWNERS
index 79709a3..1176178 100644
--- a/services/backup/OWNERS
+++ b/services/backup/OWNERS
@@ -2,7 +2,6 @@
 
 set noparent
 
-bryanmawhinney@google.com
 jstemmer@google.com
 martinoh@google.com
 millmore@google.com
diff --git a/services/backup/java/com/android/server/backup/FullBackupJob.java b/services/backup/java/com/android/server/backup/FullBackupJob.java
index fe0e1c6..de33698 100644
--- a/services/backup/java/com/android/server/backup/FullBackupJob.java
+++ b/services/backup/java/com/android/server/backup/FullBackupJob.java
@@ -24,6 +24,7 @@
 import android.app.job.JobService;
 import android.content.ComponentName;
 import android.content.Context;
+import android.content.pm.PackageManager;
 import android.os.Bundle;
 import android.util.SparseArray;
 
@@ -52,13 +53,15 @@
         JobInfo.Builder builder = new JobInfo.Builder(getJobIdForUserId(userId), sIdleService);
         final BackupManagerConstants constants = userBackupManagerService.getConstants();
         synchronized (constants) {
-            builder.setRequiresDeviceIdle(true)
-                    .setRequiredNetworkType(constants.getFullBackupRequiredNetworkType())
+            builder.setRequiredNetworkType(constants.getFullBackupRequiredNetworkType())
                     .setRequiresCharging(constants.getFullBackupRequireCharging());
         }
         if (minDelay > 0) {
             builder.setMinimumLatency(minDelay);
         }
+        if (!ctx.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH)) {
+            builder.setRequiresDeviceIdle(true);
+        }
 
         Bundle extraInfo = new Bundle();
         extraInfo.putInt(USER_ID_EXTRA_KEY, userId);
diff --git a/services/backup/java/com/android/server/backup/UserBackupManagerService.java b/services/backup/java/com/android/server/backup/UserBackupManagerService.java
index 7261709..287d713 100644
--- a/services/backup/java/com/android/server/backup/UserBackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/UserBackupManagerService.java
@@ -36,6 +36,7 @@
 import static com.android.server.backup.internal.BackupHandler.MSG_RUN_RESTORE;
 import static com.android.server.backup.internal.BackupHandler.MSG_SCHEDULE_BACKUP_PACKAGE;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.UserIdInt;
 import android.app.ActivityManager;
@@ -973,6 +974,7 @@
                 /* scheduler */ null);
     }
 
+    @NonNull
     private ArrayList<FullBackupEntry> readFullBackupSchedule() {
         boolean changed = false;
         ArrayList<FullBackupEntry> schedule = null;
@@ -986,11 +988,11 @@
                  DataInputStream in = new DataInputStream(bufStream)) {
                 int version = in.readInt();
                 if (version != SCHEDULE_FILE_VERSION) {
-                    Slog.e(
-                            TAG,
-                            addUserIdToLogMessage(
-                                    mUserId, "Unknown backup schedule version " + version));
-                    return null;
+                    // The file version doesn't match the expected value.
+                    // Since this is within a "try" block, this exception will be treated like
+                    // any other exception, and caught below.
+                    throw new IllegalArgumentException("Unknown backup schedule version "
+                            + version);
                 }
 
                 final int numPackages = in.readInt();
diff --git a/services/companion/java/com/android/server/companion/CompanionDeviceShellCommand.java b/services/companion/java/com/android/server/companion/CompanionDeviceShellCommand.java
index 6889bcd..4013514 100644
--- a/services/companion/java/com/android/server/companion/CompanionDeviceShellCommand.java
+++ b/services/companion/java/com/android/server/companion/CompanionDeviceShellCommand.java
@@ -163,7 +163,7 @@
         pw.println("  remove-inactive-associations");
         pw.println("      Remove self-managed associations that have not been active ");
         pw.println("      for a long time (90 days or as configured via ");
-        pw.println("      \"debug.cdm.cdmservice.cleanup_time_window\" system property). ");
+        pw.println("      \"debug.cdm.cdmservice.removal_time_window\" system property). ");
         pw.println("      USE FOR DEBUGGING AND/OR TESTING PURPOSES ONLY.");
     }
 }
diff --git a/services/core/Android.bp b/services/core/Android.bp
index c8caab9..14247c5 100644
--- a/services/core/Android.bp
+++ b/services/core/Android.bp
@@ -74,8 +74,8 @@
         "{ ! (diff $(out) $(location :services.core.protolog.json) | grep -q '^<') || " +
         "{ echo -e '\\n\\n################################################################\\n#\\n" +
         "#  ERROR: ProtoLog viewer config is stale.  To update it, run:\\n#\\n" +
-        "#  cp $(location :generate-protolog.json) " +
-        "$(location :services.core.protolog.json)\\n#\\n" +
+        "#  cp $${ANDROID_BUILD_TOP}/$(location :generate-protolog.json) " +
+        "$${ANDROID_BUILD_TOP}/$(location :services.core.protolog.json)\\n#\\n" +
         "################################################################\\n\\n' >&2 && false; } }",
     out: ["services.core.protolog.json"],
 }
@@ -201,9 +201,9 @@
     srcs: [":services.core.unboosted"],
     tools: ["lockedregioncodeinjection"],
     cmd: "$(location lockedregioncodeinjection) " +
-        "  --targets \"Lcom/android/server/am/ActivityManagerService;,Lcom/android/server/am/ActivityManagerGlobalLock;,Lcom/android/server/wm/WindowManagerGlobalLock;\" " +
-        "  --pre \"com/android/server/am/ActivityManagerService.boostPriorityForLockedSection,com/android/server/am/ActivityManagerService.boostPriorityForProcLockedSection,com/android/server/wm/WindowManagerService.boostPriorityForLockedSection\" " +
-        "  --post \"com/android/server/am/ActivityManagerService.resetPriorityAfterLockedSection,com/android/server/am/ActivityManagerService.resetPriorityAfterProcLockedSection,com/android/server/wm/WindowManagerService.resetPriorityAfterLockedSection\" " +
+        "  --targets \"Lcom/android/server/am/ActivityManagerService;,Lcom/android/server/am/ActivityManagerGlobalLock;,Lcom/android/server/wm/WindowManagerGlobalLock;,Lcom/android/server/pm/PackageManagerTracedLock;\" " +
+        "  --pre \"com/android/server/am/ActivityManagerService.boostPriorityForLockedSection,com/android/server/am/ActivityManagerService.boostPriorityForProcLockedSection,com/android/server/wm/WindowManagerService.boostPriorityForLockedSection,com/android/server/pm/PackageManagerService.boostPriorityForPackageManagerTracedLockedSection\" " +
+        "  --post \"com/android/server/am/ActivityManagerService.resetPriorityAfterLockedSection,com/android/server/am/ActivityManagerService.resetPriorityAfterProcLockedSection,com/android/server/wm/WindowManagerService.resetPriorityAfterLockedSection,com/android/server/pm/PackageManagerService.resetPriorityAfterPackageManagerTracedLockedSection\" " +
         "  -o $(out) " +
         "  -i $(in)",
     out: ["services.core.priorityboosted.jar"],
diff --git a/services/core/java/android/content/pm/PackageManagerInternal.java b/services/core/java/android/content/pm/PackageManagerInternal.java
index 22ac22d..cbf6724 100644
--- a/services/core/java/android/content/pm/PackageManagerInternal.java
+++ b/services/core/java/android/content/pm/PackageManagerInternal.java
@@ -44,11 +44,13 @@
 import android.util.SparseArray;
 
 import com.android.internal.util.function.pooled.PooledLambda;
+import com.android.permission.persistence.RuntimePermissionsState;
 import com.android.server.pm.Installer.LegacyDexoptDisabledException;
 import com.android.server.pm.KnownPackages;
 import com.android.server.pm.PackageList;
 import com.android.server.pm.PackageSetting;
 import com.android.server.pm.dex.DynamicCodeLogger;
+import com.android.server.pm.permission.LegacyPermissionSettings;
 import com.android.server.pm.pkg.AndroidPackage;
 import com.android.server.pm.pkg.PackageStateInternal;
 import com.android.server.pm.pkg.SharedUserApi;
@@ -1075,6 +1077,23 @@
     public abstract void writePermissionSettings(@NonNull @UserIdInt int[] userIds, boolean async);
 
     /**
+     * Read legacy permission definitions for permissions migration to new permission subsystem.
+     * Note that this api is supposed to be used for permissions migration only.
+     */
+    public abstract LegacyPermissionSettings getLegacyPermissions();
+
+    /**
+     * Read legacy permission states for permissions migration to new permission subsystem.
+     * Note that this api is supposed to be used for permissions state migration only.
+     */
+    public abstract RuntimePermissionsState getLegacyPermissionsState(@UserIdInt int userId);
+
+    /**
+     * @return permissions file version for the given user.
+     */
+    public abstract int getLegacyPermissionsVersion(@UserIdInt int userId);
+
+    /**
      * Returns {@code true} if the caller is the installer of record for the given package.
      * Otherwise, {@code false}.
      */
diff --git a/services/core/java/com/android/server/DockObserver.java b/services/core/java/com/android/server/DockObserver.java
index 3487613..b3f7523 100644
--- a/services/core/java/com/android/server/DockObserver.java
+++ b/services/core/java/com/android/server/DockObserver.java
@@ -20,9 +20,8 @@
 import android.content.Context;
 import android.content.Intent;
 import android.database.ContentObserver;
-import android.media.AudioManager;
+import android.media.AudioAttributes;
 import android.media.Ringtone;
-import android.media.RingtoneManager;
 import android.net.Uri;
 import android.os.Binder;
 import android.os.Handler;
@@ -304,11 +303,16 @@
                     if (soundPath != null) {
                         final Uri soundUri = Uri.parse("file://" + soundPath);
                         if (soundUri != null) {
-                            final Ringtone sfx = RingtoneManager.getRingtone(
-                                    getContext(), soundUri);
+                            AudioAttributes audioAttributes = new AudioAttributes.Builder()
+                                    .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
+                                    .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
+                                    .build();
+                            final Ringtone sfx = new Ringtone.Builder(getContext(),
+                                    Ringtone.MEDIA_SOUND, audioAttributes)
+                                    .setUri(soundUri)
+                                    .setPreferBuiltinDevice()
+                                    .build();
                             if (sfx != null) {
-                                sfx.setStreamType(AudioManager.STREAM_SYSTEM);
-                                sfx.preferBuiltinDevice(true);
                                 sfx.play();
                             }
                         }
diff --git a/services/core/java/com/android/server/PackageWatchdog.java b/services/core/java/com/android/server/PackageWatchdog.java
index 92889c0..d256aea 100644
--- a/services/core/java/com/android/server/PackageWatchdog.java
+++ b/services/core/java/com/android/server/PackageWatchdog.java
@@ -426,7 +426,7 @@
                                 }
                                 int impact = registeredObserver.onHealthCheckFailed(
                                         versionedPackage, failureReason, mitigationCount);
-                                if (impact != PackageHealthObserverImpact.USER_IMPACT_NONE
+                                if (impact != PackageHealthObserverImpact.USER_IMPACT_LEVEL_0
                                         && impact < currentObserverImpact) {
                                     currentObserverToNotify = registeredObserver;
                                     currentObserverImpact = impact;
@@ -466,7 +466,7 @@
             if (registeredObserver != null) {
                 int impact = registeredObserver.onHealthCheckFailed(
                         failingPackage, failureReason, 1);
-                if (impact != PackageHealthObserverImpact.USER_IMPACT_NONE
+                if (impact != PackageHealthObserverImpact.USER_IMPACT_LEVEL_0
                         && impact < currentObserverImpact) {
                     currentObserverToNotify = registeredObserver;
                     currentObserverImpact = impact;
@@ -494,7 +494,7 @@
                     PackageHealthObserver registeredObserver = observer.registeredObserver;
                     if (registeredObserver != null) {
                         int impact = registeredObserver.onBootLoop(mitigationCount);
-                        if (impact != PackageHealthObserverImpact.USER_IMPACT_NONE
+                        if (impact != PackageHealthObserverImpact.USER_IMPACT_LEVEL_0
                                 && impact < currentObserverImpact) {
                             currentObserverToNotify = registeredObserver;
                             currentObserverImpact = impact;
@@ -576,19 +576,23 @@
 
     /** Possible severity values of the user impact of a {@link PackageHealthObserver#execute}. */
     @Retention(SOURCE)
-    @IntDef(value = {PackageHealthObserverImpact.USER_IMPACT_NONE,
-                     PackageHealthObserverImpact.USER_IMPACT_LOW,
-                     PackageHealthObserverImpact.USER_IMPACT_MEDIUM,
-                     PackageHealthObserverImpact.USER_IMPACT_HIGH})
+    @IntDef(value = {PackageHealthObserverImpact.USER_IMPACT_LEVEL_0,
+                     PackageHealthObserverImpact.USER_IMPACT_LEVEL_10,
+                     PackageHealthObserverImpact.USER_IMPACT_LEVEL_30,
+                     PackageHealthObserverImpact.USER_IMPACT_LEVEL_50,
+                     PackageHealthObserverImpact.USER_IMPACT_LEVEL_70,
+                     PackageHealthObserverImpact.USER_IMPACT_LEVEL_100})
     public @interface PackageHealthObserverImpact {
         /** No action to take. */
-        int USER_IMPACT_NONE = 0;
+        int USER_IMPACT_LEVEL_0 = 0;
         /* Action has low user impact, user of a device will barely notice. */
-        int USER_IMPACT_LOW = 1;
-        /* Action has medium user impact, user of a device will likely notice. */
-        int USER_IMPACT_MEDIUM = 3;
+        int USER_IMPACT_LEVEL_10 = 10;
+        /* Actions having medium user impact, user of a device will likely notice. */
+        int USER_IMPACT_LEVEL_30 = 30;
+        int USER_IMPACT_LEVEL_50 = 50;
+        int USER_IMPACT_LEVEL_70 = 70;
         /* Action has high user impact, a last resort, user of a device will be very frustrated. */
-        int USER_IMPACT_HIGH = 5;
+        int USER_IMPACT_LEVEL_100 = 100;
     }
 
     /** Register instances of this interface to receive notifications on package failure. */
@@ -633,7 +637,7 @@
          *                        boot loop (including this time).
          */
         default @PackageHealthObserverImpact int onBootLoop(int mitigationCount) {
-            return PackageHealthObserverImpact.USER_IMPACT_NONE;
+            return PackageHealthObserverImpact.USER_IMPACT_LEVEL_0;
         }
 
         /**
diff --git a/services/core/java/com/android/server/RescueParty.java b/services/core/java/com/android/server/RescueParty.java
index 3de65f9..46d019b 100644
--- a/services/core/java/com/android/server/RescueParty.java
+++ b/services/core/java/com/android/server/RescueParty.java
@@ -489,13 +489,14 @@
         switch(rescueLevel) {
             case LEVEL_RESET_SETTINGS_UNTRUSTED_DEFAULTS:
             case LEVEL_RESET_SETTINGS_UNTRUSTED_CHANGES:
-                return PackageHealthObserverImpact.USER_IMPACT_LOW;
+                return PackageHealthObserverImpact.USER_IMPACT_LEVEL_10;
             case LEVEL_RESET_SETTINGS_TRUSTED_DEFAULTS:
             case LEVEL_WARM_REBOOT:
+                return PackageHealthObserverImpact.USER_IMPACT_LEVEL_50;
             case LEVEL_FACTORY_RESET:
-                return PackageHealthObserverImpact.USER_IMPACT_HIGH;
+                return PackageHealthObserverImpact.USER_IMPACT_LEVEL_100;
             default:
-                return PackageHealthObserverImpact.USER_IMPACT_NONE;
+                return PackageHealthObserverImpact.USER_IMPACT_LEVEL_0;
         }
     }
 
@@ -633,7 +634,7 @@
                 return mapRescueLevelToUserImpact(getRescueLevel(mitigationCount,
                         mayPerformReboot(failedPackage)));
             } else {
-                return PackageHealthObserverImpact.USER_IMPACT_NONE;
+                return PackageHealthObserverImpact.USER_IMPACT_LEVEL_0;
             }
         }
 
@@ -677,7 +678,7 @@
         @Override
         public int onBootLoop(int mitigationCount) {
             if (isDisabled()) {
-                return PackageHealthObserverImpact.USER_IMPACT_NONE;
+                return PackageHealthObserverImpact.USER_IMPACT_LEVEL_0;
             }
             return mapRescueLevelToUserImpact(getRescueLevel(mitigationCount, true));
         }
diff --git a/services/core/java/com/android/server/SystemUpdateManagerService.java b/services/core/java/com/android/server/SystemUpdateManagerService.java
index 811a780..d5e7be5 100644
--- a/services/core/java/com/android/server/SystemUpdateManagerService.java
+++ b/services/core/java/com/android/server/SystemUpdateManagerService.java
@@ -86,9 +86,10 @@
         }
     }
 
+    @android.annotation.EnforcePermission(android.Manifest.permission.RECOVERY)
     @Override
     public void updateSystemUpdateInfo(PersistableBundle infoBundle) {
-        mContext.enforceCallingOrSelfPermission(Manifest.permission.RECOVERY, TAG);
+        updateSystemUpdateInfo_enforcePermission();
 
         int status = infoBundle.getInt(KEY_STATUS, STATUS_UNKNOWN);
         if (status == STATUS_UNKNOWN) {
diff --git a/services/core/java/com/android/server/TEST_MAPPING b/services/core/java/com/android/server/TEST_MAPPING
index c3dda71..cb4f561 100644
--- a/services/core/java/com/android/server/TEST_MAPPING
+++ b/services/core/java/com/android/server/TEST_MAPPING
@@ -54,23 +54,7 @@
         },
         {
             "name": "BinaryTransparencyHostTest",
-            "file_patterns": [
-                "BinaryTransparencyService\\.java"
-            ]
-        },
-        {
-            "name": "CtsMediaProjectionTestCases",
-            "options": [
-                {
-                    "exclude-annotation": "android.platform.test.annotations.FlakyTest"
-                },
-                {
-                    "exclude-annotation": "androidx.test.filters.FlakyTest"
-                },
-                {
-                    "exclude-annotation": "org.junit.Ignore"
-                }
-            ]
+            "file_patterns": ["BinaryTransparencyService\\.java"]
         }
     ],
     "presubmit-large": [
diff --git a/services/core/java/com/android/server/am/ActiveInstrumentation.java b/services/core/java/com/android/server/am/ActiveInstrumentation.java
index 61ccf11..49685b95 100644
--- a/services/core/java/com/android/server/am/ActiveInstrumentation.java
+++ b/services/core/java/com/android/server/am/ActiveInstrumentation.java
@@ -40,6 +40,9 @@
     // The application being instrumented
     ApplicationInfo mTargetInfo;
 
+    // Whether the application is instrumented as an sdk running in the sdk_sandbox.
+    boolean mIsSdkInSandbox;
+
     // Where to save profiling
     String mProfileFile;
 
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 20eed98..17ea152 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -4655,6 +4655,7 @@
             } else if (instr2 != null) {
                 thread.bindApplication(processName, appInfo,
                         app.sdkSandboxClientAppVolumeUuid, app.sdkSandboxClientAppPackage,
+                        instr2.mIsSdkInSandbox,
                         providerList,
                         instr2.mClass,
                         profilerInfo, instr2.mArguments,
@@ -4671,6 +4672,7 @@
             } else {
                 thread.bindApplication(processName, appInfo,
                         app.sdkSandboxClientAppVolumeUuid, app.sdkSandboxClientAppPackage,
+                        /* isSdkInSandbox= */ false,
                         providerList, null, profilerInfo, null, null, null, testMode,
                         mBinderTransactionTrackingEnabled, enableTrackAllocation,
                         isRestrictedBackupMode || !normalMode, app.isPersistent(),
@@ -15314,7 +15316,8 @@
                         ai,
                         noRestart,
                         disableHiddenApiChecks,
-                        disableTestApiChecks);
+                        disableTestApiChecks,
+                        (flags & ActivityManager.INSTR_FLAG_INSTRUMENT_SDK_IN_SANDBOX) != 0);
             }
 
             ActiveInstrumentation activeInstr = new ActiveInstrumentation(this);
@@ -15411,7 +15414,8 @@
             ApplicationInfo sdkSandboxClientAppInfo,
             boolean noRestart,
             boolean disableHiddenApiChecks,
-            boolean disableTestApiChecks) {
+            boolean disableTestApiChecks,
+            boolean isSdkInSandbox) {
 
         if (noRestart) {
             reportStartInstrumentationFailureLocked(
@@ -15421,16 +15425,6 @@
             return false;
         }
 
-        final ApplicationInfo sdkSandboxInfo;
-        try {
-            final PackageManager pm = mContext.getPackageManager();
-            sdkSandboxInfo = pm.getApplicationInfoAsUser(pm.getSdkSandboxPackageName(), 0, userId);
-        } catch (NameNotFoundException e) {
-            reportStartInstrumentationFailureLocked(
-                    watcher, className, "Can't find SdkSandbox package");
-            return false;
-        }
-
         final SdkSandboxManagerLocal sandboxManagerLocal =
                 LocalManagerRegistry.getManager(SdkSandboxManagerLocal.class);
         if (sandboxManagerLocal == null) {
@@ -15439,13 +15433,22 @@
             return false;
         }
 
-        final String processName = sandboxManagerLocal.getSdkSandboxProcessNameForInstrumentation(
-                sdkSandboxClientAppInfo);
+        final ApplicationInfo sdkSandboxInfo;
+        try {
+            sdkSandboxInfo =
+                    sandboxManagerLocal.getSdkSandboxApplicationInfoForInstrumentation(
+                            sdkSandboxClientAppInfo, userId, isSdkInSandbox);
+        } catch (NameNotFoundException e) {
+            reportStartInstrumentationFailureLocked(
+                    watcher, className, "Can't find SdkSandbox package");
+            return false;
+        }
 
         ActiveInstrumentation activeInstr = new ActiveInstrumentation(this);
         activeInstr.mClass = className;
-        activeInstr.mTargetProcesses = new String[]{processName};
+        activeInstr.mTargetProcesses = new String[]{sdkSandboxInfo.processName};
         activeInstr.mTargetInfo = sdkSandboxInfo;
+        activeInstr.mIsSdkInSandbox = isSdkInSandbox;
         activeInstr.mProfileFile = profileFile;
         activeInstr.mArguments = arguments;
         activeInstr.mWatcher = watcher;
@@ -15462,7 +15465,6 @@
             sandboxManagerLocal.notifyInstrumentationStarted(
                     sdkSandboxClientAppInfo.packageName, sdkSandboxClientAppInfo.uid);
             synchronized (mProcLock) {
-                int sdkSandboxUid = Process.toSdkSandboxUid(sdkSandboxClientAppInfo.uid);
                 // Kill the package sdk sandbox process belong to. At this point sdk sandbox is
                 // already killed.
                 forceStopPackageLocked(
@@ -15478,10 +15480,10 @@
 
                 ProcessRecord app = addAppLocked(
                         sdkSandboxInfo,
-                        processName,
+                        sdkSandboxInfo.processName,
                         /* isolated= */ false,
                         /* isSdkSandbox= */ true,
-                        sdkSandboxUid,
+                        sdkSandboxInfo.uid,
                         sdkSandboxClientAppInfo.packageName,
                         disableHiddenApiChecks,
                         disableTestApiChecks,
diff --git a/services/core/java/com/android/server/am/AnrHelper.java b/services/core/java/com/android/server/am/AnrHelper.java
index 16219cd..7d98443 100644
--- a/services/core/java/com/android/server/am/AnrHelper.java
+++ b/services/core/java/com/android/server/am/AnrHelper.java
@@ -22,6 +22,7 @@
 import android.content.pm.ApplicationInfo;
 import android.os.SystemClock;
 import android.os.Trace;
+import android.util.ArraySet;
 import android.util.Slog;
 
 import com.android.internal.annotations.GuardedBy;
@@ -29,8 +30,12 @@
 import com.android.internal.os.TimeoutRecord;
 import com.android.server.wm.WindowProcessController;
 
+import java.io.File;
 import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Set;
 import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Future;
 import java.util.concurrent.LinkedBlockingQueue;
 import java.util.concurrent.ThreadFactory;
 import java.util.concurrent.ThreadPoolExecutor;
@@ -59,13 +64,19 @@
     /**
      * The keep alive time for the threads in the helper threadpool executor
     */
-    private static final int AUX_THREAD_KEEP_ALIVE_SECOND = 10;
+    private static final int DEFAULT_THREAD_KEEP_ALIVE_SECOND = 10;
 
     private static final ThreadFactory sDefaultThreadFactory =  r ->
             new Thread(r, "AnrAuxiliaryTaskExecutor");
+    private static final ThreadFactory sMainProcessDumpThreadFactory =  r ->
+            new Thread(r, "AnrMainProcessDumpThread");
 
     @GuardedBy("mAnrRecords")
     private final ArrayList<AnrRecord> mAnrRecords = new ArrayList<>();
+
+    private final Set<Integer> mTempDumpedPids =
+            Collections.synchronizedSet(new ArraySet<Integer>());
+
     private final AtomicBoolean mRunning = new AtomicBoolean(false);
 
     private final ActivityManagerService mService;
@@ -80,17 +91,21 @@
     private int mProcessingPid = -1;
 
     private final ExecutorService mAuxiliaryTaskExecutor;
+    private final ExecutorService mEarlyDumpExecutor;
 
     AnrHelper(final ActivityManagerService service) {
-        this(service, new ThreadPoolExecutor(/* corePoolSize= */ 0, /* maximumPoolSize= */ 1,
-                /* keepAliveTime= */ AUX_THREAD_KEEP_ALIVE_SECOND, TimeUnit.SECONDS,
-                new LinkedBlockingQueue<>(), sDefaultThreadFactory));
+        // All the ANR threads need to expire after a period of inactivity, given the
+        // ephemeral nature of ANRs and how infrequent they are.
+        this(service, makeExpiringThreadPoolWithSize(1, sDefaultThreadFactory),
+                makeExpiringThreadPoolWithSize(2, sMainProcessDumpThreadFactory));
     }
 
     @VisibleForTesting
-    AnrHelper(ActivityManagerService service, ExecutorService auxExecutor) {
+    AnrHelper(ActivityManagerService service, ExecutorService auxExecutor,
+            ExecutorService earlyDumpExecutor) {
         mService = service;
         mAuxiliaryTaskExecutor = auxExecutor;
+        mEarlyDumpExecutor = earlyDumpExecutor;
     }
 
     void appNotResponding(ProcessRecord anrProcess, TimeoutRecord timeoutRecord) {
@@ -121,6 +136,12 @@
                             + timeoutRecord.mReason);
                     return;
                 }
+                if (!mTempDumpedPids.add(incomingPid)) {
+                    Slog.i(TAG,
+                            "Skip ANR being predumped, pid=" + incomingPid + " "
+                            + timeoutRecord.mReason);
+                    return;
+                }
                 for (int i = mAnrRecords.size() - 1; i >= 0; i--) {
                     if (mAnrRecords.get(i).mPid == incomingPid) {
                         Slog.i(TAG,
@@ -129,10 +150,24 @@
                         return;
                     }
                 }
+                // We dump the main process as soon as we can on a different thread,
+                // this is done as the main process's dump can go stale in a few hundred
+                // milliseconds and the average full ANR dump takes a few seconds.
+                timeoutRecord.mLatencyTracker.earlyDumpRequestSubmittedWithSize(
+                        mTempDumpedPids.size());
+                Future<File> firstPidDumpPromise = mEarlyDumpExecutor.submit(() -> {
+                    // the class AnrLatencyTracker is not generally thread safe but the values
+                    // recorded/touched by the Temporary dump thread(s) are all volatile/atomic.
+                    File tracesFile = StackTracesDumpHelper.dumpStackTracesTempFile(incomingPid,
+                            timeoutRecord.mLatencyTracker);
+                    mTempDumpedPids.remove(incomingPid);
+                    return tracesFile;
+                });
+
                 timeoutRecord.mLatencyTracker.anrRecordPlacingOnQueueWithSize(mAnrRecords.size());
                 mAnrRecords.add(new AnrRecord(anrProcess, activityShortComponentName, aInfo,
-                        parentShortComponentName, parentProcess, aboveSystem,
-                        mAuxiliaryTaskExecutor, timeoutRecord, isContinuousAnr));
+                        parentShortComponentName, parentProcess, aboveSystem, timeoutRecord,
+                        isContinuousAnr, firstPidDumpPromise));
             }
             startAnrConsumerIfNeeded();
         } finally {
@@ -147,6 +182,16 @@
         }
     }
 
+    private static ThreadPoolExecutor makeExpiringThreadPoolWithSize(int size,
+            ThreadFactory factory) {
+        ThreadPoolExecutor pool = new ThreadPoolExecutor(/* corePoolSize= */ size,
+                /* maximumPoolSize= */ size, /* keepAliveTime= */ DEFAULT_THREAD_KEEP_ALIVE_SECOND,
+                TimeUnit.SECONDS, new LinkedBlockingQueue<>(), factory);
+        // We allow the core threads to expire after the keepAliveTime.
+        pool.allowCoreThreadTimeOut(true);
+        return pool;
+    }
+
     /**
      * The thread to execute {@link ProcessErrorStateRecord#appNotResponding}. It will terminate if
      * all records are handled.
@@ -219,7 +264,7 @@
         }
     }
 
-    private static class AnrRecord {
+    private class AnrRecord {
         final ProcessRecord mApp;
         final int mPid;
         final String mActivityShortComponentName;
@@ -228,14 +273,14 @@
         final ApplicationInfo mAppInfo;
         final WindowProcessController mParentProcess;
         final boolean mAboveSystem;
-        final ExecutorService mAuxiliaryTaskExecutor;
         final long mTimestamp = SystemClock.uptimeMillis();
         final boolean mIsContinuousAnr;
+        final Future<File> mFirstPidFilePromise;
         AnrRecord(ProcessRecord anrProcess, String activityShortComponentName,
                 ApplicationInfo aInfo, String parentShortComponentName,
                 WindowProcessController parentProcess, boolean aboveSystem,
-                ExecutorService auxiliaryTaskExecutor, TimeoutRecord timeoutRecord,
-                boolean isContinuousAnr) {
+                TimeoutRecord timeoutRecord, boolean isContinuousAnr,
+                Future<File> firstPidFilePromise) {
             mApp = anrProcess;
             mPid = anrProcess.mPid;
             mActivityShortComponentName = activityShortComponentName;
@@ -244,8 +289,8 @@
             mAppInfo = aInfo;
             mParentProcess = parentProcess;
             mAboveSystem = aboveSystem;
-            mAuxiliaryTaskExecutor = auxiliaryTaskExecutor;
             mIsContinuousAnr = isContinuousAnr;
+            mFirstPidFilePromise = firstPidFilePromise;
         }
 
         void appNotResponding(boolean onlyDumpSelf) {
@@ -254,7 +299,7 @@
                 mApp.mErrorState.appNotResponding(mActivityShortComponentName, mAppInfo,
                         mParentShortComponentName, mParentProcess, mAboveSystem,
                         mTimeoutRecord, mAuxiliaryTaskExecutor, onlyDumpSelf,
-                        mIsContinuousAnr);
+                        mIsContinuousAnr, mFirstPidFilePromise);
             } finally {
                 mTimeoutRecord.mLatencyTracker.anrProcessingEnded();
             }
diff --git a/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java b/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java
index f31c017..55158f8 100644
--- a/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java
+++ b/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java
@@ -1463,13 +1463,15 @@
 
     @Override
     public boolean isDelayBehindServices() {
-        // TODO: implement
+        // Modern queue does not alter the broadcasts delivery behavior based on background
+        // services, so ignore.
         return false;
     }
 
     @Override
     public void backgroundServicesFinishedLocked(int userId) {
-        // TODO: implement
+        // Modern queue does not alter the broadcasts delivery behavior based on background
+        // services, so ignore.
     }
 
     /**
diff --git a/services/core/java/com/android/server/am/ContentProviderHelper.java b/services/core/java/com/android/server/am/ContentProviderHelper.java
index a1fcd42..824509a 100644
--- a/services/core/java/com/android/server/am/ContentProviderHelper.java
+++ b/services/core/java/com/android/server/am/ContentProviderHelper.java
@@ -250,7 +250,6 @@
                 if (r != null && cpr.canRunHere(r)) {
                     checkAssociationAndPermissionLocked(r, cpi, callingUid, userId, checkCrossUser,
                             cpr.name.flattenToShortString(), startTime);
-                    enforceContentProviderRestrictionsForSdkSandbox(cpi);
 
                     // This provider has been published or is in the process
                     // of being published...  but it is also allowed to run
@@ -447,7 +446,6 @@
                     // info and allow the caller to instantiate it.  Only do
                     // this if the provider is the same user as the caller's
                     // process, or can run as root (so can be in any process).
-                    enforceContentProviderRestrictionsForSdkSandbox(cpi);
                     return cpr.newHolder(null, true);
                 }
 
@@ -597,8 +595,6 @@
                 // Return a holder instance even if we are waiting for the publishing of the
                 // provider, client will check for the holder.provider to see if it needs to wait
                 // for it.
-                //todo(b/265965249) Need to perform cleanup before calling enforce method here
-                enforceContentProviderRestrictionsForSdkSandbox(cpi);
                 return cpr.newHolder(conn, false);
             }
         }
@@ -660,7 +656,6 @@
                     + " caller=" + callerName + "/" + Binder.getCallingUid());
             return null;
         }
-        enforceContentProviderRestrictionsForSdkSandbox(cpi);
         return cpr.newHolder(conn, false);
     }
 
@@ -1139,7 +1134,6 @@
             appName = r.toString();
         }
 
-        enforceContentProviderRestrictionsForSdkSandbox(cpi);
         return checkContentProviderPermission(cpi, callingPid, Binder.getCallingUid(),
                 userId, checkUser, appName);
     }
@@ -1514,11 +1508,17 @@
 
     /**
      * Check if {@link ProcessRecord} has a possible chance at accessing the
-     * given {@link ProviderInfo}. Final permission checking is always done
+     * given {@link ProviderInfo}. First permission checking is for enforcing
+     * ContentProvider Restrictions from SdkSandboxManager.
+     * Final permission checking is always done
      * in {@link ContentProvider}.
      */
     private String checkContentProviderPermission(ProviderInfo cpi, int callingPid, int callingUid,
             int userId, boolean checkUser, String appName) {
+        if (!canAccessContentProviderFromSdkSandbox(cpi, callingUid)) {
+            return "ContentProvider access not allowed from sdk sandbox UID. "
+                    + "ProviderInfo: " + cpi.toString();
+        }
         boolean checkedGrants = false;
         if (checkUser) {
             // Looking for cross-user grants before enforcing the typical cross-users permissions
@@ -1908,11 +1908,10 @@
         }
     }
 
-    // Binder.clearCallingIdentity() shouldn't be called before this method
-    // as Binder should have its original callingUid for the check
-    private void enforceContentProviderRestrictionsForSdkSandbox(ProviderInfo cpi) {
-        if (!Process.isSdkSandboxUid(Binder.getCallingUid())) {
-            return;
+    private boolean canAccessContentProviderFromSdkSandbox(ProviderInfo cpi,
+                                                                    int callingUid) {
+        if (!Process.isSdkSandboxUid(callingUid)) {
+            return true;
         }
         final SdkSandboxManagerLocal sdkSandboxManagerLocal =
                 LocalManagerRegistry.getManager(SdkSandboxManagerLocal.class);
@@ -1921,11 +1920,7 @@
                     + "when checking whether SDK sandbox uid may "
                     + "access the contentprovider.");
         }
-        if (!sdkSandboxManagerLocal
-                .canAccessContentProviderFromSdkSandbox(cpi)) {
-            throw new SecurityException(
-                    "SDK sandbox uid may not access contentprovider " + cpi.name);
-        }
+        return sdkSandboxManagerLocal.canAccessContentProviderFromSdkSandbox(cpi);
     }
 
     /**
diff --git a/services/core/java/com/android/server/am/OomAdjuster.md b/services/core/java/com/android/server/am/OomAdjuster.md
index febc37b..16091d1 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.md
+++ b/services/core/java/com/android/server/am/OomAdjuster.md
@@ -17,10 +17,10 @@
 
 ## Purpose of Oom Adjuster
 
-The Android OS runs with limited hardware resources, i.e. CPU/RAM/Power. To strive for the better performance, Oom Ajuster is introduced to tweak the following 3 major factors:
+The Android OS runs with limited hardware resources, i.e. CPU/RAM/Power. To strive for the better performance, Oom Adjuster is introduced to tweak the following 3 major factors:
 
  * Process State
-   * Wildly used by the System Server, i.e., determine if it's foreground or not, change the GC behavior, etc.
+   * Widely used by the System Server, i.e., determine if it's foreground or not, change the GC behavior, etc.
    * Defined in `ActivityManager#PROCESS_STATE_*`
  * Oom Adj score
    * Used by the lmkd to determine which process should be expunged on memory pressure.
@@ -31,36 +31,36 @@
 
 ## Process Capabilities
 
-Besides the above 3 major factors, Android R introduced the Process Capabilities `ActivityManager#PROCESS_CAPABILITY_*`.  It's a new attribute to process record, mainly designed for supporting the "while-in-use" permission model - in additional to the traditional Android permissions, wheather or not a process has access to a given API, will be guarded by its current process state as well. The OomAdjuster will compute the process capabilities during updating the oom adj. Meanwhile, the flag `ActivityManager#BIND_INCLUDE_CAPABILITIES` enables to possiblity to "transfer" the capability from a client process to the service process it binds to.
+Besides the above 3 major factors, Android R introduced the Process Capabilities `ActivityManager#PROCESS_CAPABILITY_*`.  It's a new attribute to process record, mainly designed for supporting the "while-in-use" permission model - in addition to the traditional Android permissions, whether or not a process has access to a given API, will be guarded by its current process state as well. The OomAdjuster will compute the process capabilities during updating the oom adj. Meanwhile, the flag `ActivityManager#BIND_INCLUDE_CAPABILITIES` enables the possibility to "transfer" the capability from a client process to the service process it binds to.
 
 ## Rationale of Oom Adjuster
 
-System server keeps a list of recent used app processes. Given the 4 types of entities that an Android processes could have: Activity, Service, Content Provider and Broadcast Receiver, the System Server has to adjust the above 3 factors to give the users the best performance according to the states of the entities. A typical case would be that: foreground app A binds into a background service B in order to serve the user, in the case of memory pressure, the background service B should be avoided from being expunged since it would result user-perceptible interruption of service. The Oom Adjuster is to tweak the aforementioned 3 factors for those app processes.
+System server keeps a list of recent used app processes. Given the 4 types of entities that an Android processes could have: Activity, Service, Content Provider and Broadcast Receiver, the System Server has to adjust the above 3 factors to give the users the best performance according to the states of the entities. A typical case would be that: foreground app A binds into a background service B in order to serve the user, in the case of memory pressure, the background service B should be avoided from being expunged since it would result in user-perceptible interruption of service. The Oom Adjuster is to tweak the aforementioned 3 factors for those app processes.
 
 The timing of updating the Oom Adj score is vital: assume a camera process in background gets launched into foreground, launching camera typically incurs high memory pressure, which could incur low memory kills - if the camera process isn't moved out of the background adj group, it could get killed by lmkd. Therefore the updates have to be called pretty frequently: in case there is an activity start, service binding, etc.
 
 The update procedure basically consists of 3 parts:
   * Find out the process record to be updated
-    * There are two categories of updateOomAdjLocked: one with the target process record to be updated, while the other one is to update all process record.
+    * There are two categories of updateOomAdjLocked: one with the target process record to be updated, while the other one is to update all process records.
     * Besides that, while computing the Oom Aj score, the clients of service connections or content providers of the present process record, which forms a process dependency graph actually, will be evaluated as well.
-    * Starting from Android R, when updating for a specific process record, an optimization is made that, only the reachable process records starting from this process record in the process dependency graph, will be re-evaluated.
+    * Starting from Android R, when updating a specific process record, an optimization is made that only the reachable process records starting from this process record in the process dependency graph will be re-evaluated.
     * The `cached` Oom Adj scores are grouped in `bucket`, which is used in the isolated processes: they could be correlated - assume one isolated Chrome process is at Oom Adj score 920 and another one is 980; the later one could get expunged much earlier than the former one, which doesn't make sense; grouping them would be a big relief for this case.
   * Compute Oom Adj score
     * This procedure returns true if there is a score change, false if there is no.
     * The curAdj field in the process record is used as an intermediate value during the computation.
     * Initialize the Process State to `PROCESS_STATE_CACHED_EMPTY`, which is the lowest importance.
     * Calculate the scores based on various factors:
-      * If it's not allowed to be lower than `ProcessList#FOREGROUND_APP_ADJ`, meaning it's propbably a persistent process, there is no too much to do here.
+      * If it's not allowed to be lower than `ProcessList#FOREGROUND_APP_ADJ`, meaning it's probably a persistent process, there is no too much to do here.
       * Exame if the process is the top app, running remote animation, running instrumentation, receiving broadcast, executing services, running on top but sleeping (screen off), update the intermediate values.
       * Ask Window Manager (yes, ActivityTaskManager is with WindowManager now) to tell each activity's visibility information.
-      * Check if the process has recent tasks, check if it's hosting a foreground service, overlay UI, toast etc. Note for the foreground service, if it was in foreground status, allow it to stay in higher rank in memory for a while: Assuming a camera captureing case, where the camera app is still processing the picture while being switched out of foreground - keep it stay in higher rank in memory would ensure the pictures are persisted correctly.
-      * Check if the process is the heavy weight process, whose launching/exiting would be slow and it's better to keep it in the memory. Note there should be only one heavy weight process across the system.
+      * Check if the process has recent tasks, check if it's hosting a foreground service, overlay UI, toast etc. Note for the foreground service, if it was in foreground status, allow it to stay in higher rank in memory for a while: Assuming a camera capturing case, where the camera app is still processing the picture while being switched out of foreground - keep it stay in higher rank in memory would ensure the pictures are persisted correctly.
+      * Check if the process is the heavyweight process, whose launching/exiting would be slow and it's better to keep it in the memory. Note there should be only one heavyweight process across the system.
       * For sure the Home process shouldn't be expunged frequently as well.
       * The next two factors are either it was the previous process with visible UI to the user, or it's a backup agent.
       * And then it goes to the massive searches against the service connections and the content providers, each of the clients will be evaluated, and the Oom Adj score could get updated according to its clients' scores. However there are a bunch of service binding flags which could impact the result:
         * Below table captures the results with given various service binding states:
 
-        | Conditon #1                     | Condition #2                                               | Condition #3                                 | Condition #4                                      | Result                   |
+        | Condition #1                    | Condition #2                                               | Condition #3                                 | Condition #4                                      | Result                   |
         |---------------------------------|------------------------------------------------------------|----------------------------------------------|---------------------------------------------------|--------------------------|
         | `BIND_WAIVE_PRIORITY` not set   | `BIND_ALLOW_OOM_MANAGEMENT` set                            | Shown UI && Not Home                         |                                                   | Use the app's own Adj    |
         |                                 |                                                            | Inactive for a while                         |                                                   | Use the app's own Adj    |
@@ -85,7 +85,7 @@
         |                                 |                                                            |                                              | `BIND_IMPORTANT` is NOT set                       | Sched = default          |
         * Below table captures the results with given various content provider binding states:
 
-        | Conditon #1                     | Condition #2                                               | Condition #3                                 | Result                   |
+        | Condition #1                    | Condition #2                                               | Condition #3                                 | Result                   |
         |---------------------------------|------------------------------------------------------------|----------------------------------------------|--------------------------|
         | Client's process state >= cached|                                                            |                                              | Client ProcState = empty |
         | Adj > Client Adj                | Not shown UI or is Home, or Client's Adj <= perceptible    | Client's Adj <= foreground Adj               | Try foreground Adj       |
@@ -94,11 +94,11 @@
         |                                 | Client's process state is NOT top                          |                                              | ProcState = bound fg svc |
         | Has external dependencies       | Adj > fg app                                               |                                              | adj = fg app             |
         |                                 | Process state > important foreground                       |                                              | ProcState = important fg |
-        | Still within retain time        | Adj > previous app Adj                                     |                                              | adj = previuos app adj   |
+        | Still within retain time        | Adj > previous app Adj                                     |                                              | adj = previous app adj   |
         |                                 | Process state > last activity                              |                                              | ProcState = last activity|
         * Some additional tweaks after the above ones:
 
-        | Conditon #1                     | Condition #2                                               | Condition #3                                 | Result                             |
+        | Condition #1                    | Condition #2                                               | Condition #3                                 | Result                             |
         |---------------------------------|------------------------------------------------------------|----------------------------------------------|------------------------------------|
         | Process state >= cached empty   | Has client activities                                      |                                              | ProcState = cached activity client |
         |                                 | treat like activity (IME)                                  |                                              | ProcState = cached activity        |
@@ -108,7 +108,7 @@
 
 ## Cycles, Cycles, Cycles
 
-Another interesting aspect of the Oom Adjuster is the cycles of the dependencies. A simple example would be like below illustration, process A is hosting a service which is bound by process B; meanwhile the process B is hosting a service which is bound by process A.
+Another interesting aspect of the Oom Adjuster is the cycles of the dependencies. A simple example would be like the illustration below, process A is hosting a service which is bound by process B; meanwhile process B is hosting a service which is bound by process A.
 <pre>
   +-------------+           +-------------+
   |  Process A  | <-------- |  Process B  |
@@ -116,7 +116,7 @@
   +-------------+           +-------------+
 </pre>
 
-There could be very complicated cases, which could involve multiple cycles, and in the dependency graph, each of the process record node could have different importance.
+There could be very complicated cases, which could involve multiple cycles, and in the dependency graph, each of the process record nodes could have different importance.
 <pre>
   +-------------+           +-------------+           +-------------+           +-------------+           +-------------+
   |  Process D  | --------> |  Process A  | <-------- |  Process B  | <-------- |  Process C  | <-------- |  Process A  |
@@ -124,9 +124,9 @@
   +-------------+           +-------------+           +-------------+           +-------------+           +-------------+
 </pre>
 
-The Oom Adjuster maintains a global sequence ID `mAdjSeq` to track the current Oom Adjuster calling. And each of the process record has a field to track in which sequence the process record is evaluated. If during the Oom Adj computation, a process record with sequence ID as same as the current global sequence ID, this would mean that a cycle is detected; in this case:
+The Oom Adjuster maintains a global sequence ID `mAdjSeq` to track the current Oom Adjuster calling. And each of the process records has a field to track in which sequence the process record is evaluated. If during the Oom Adj computation, a process record with sequence ID as same as the current global sequence ID, this would mean that a cycle is detected; in this case:
   * Decrement the sequence ID of each process if there is a cycle.
-  * Re-evaluate each of the process record within the cycle until nothing was promoted.
+  * Re-evaluate each of the process records within the cycle until nothing was promoted.
   * Iterate the processes from least important to most important ones.
   * A maximum retries of 10 is enforced, while in practice, the maximum retries could reach only 2 to 3.
 
diff --git a/services/core/java/com/android/server/am/ProcessErrorStateRecord.java b/services/core/java/com/android/server/am/ProcessErrorStateRecord.java
index e66894b..2208b79 100644
--- a/services/core/java/com/android/server/am/ProcessErrorStateRecord.java
+++ b/services/core/java/com/android/server/am/ProcessErrorStateRecord.java
@@ -290,7 +290,7 @@
             String parentShortComponentName, WindowProcessController parentProcess,
             boolean aboveSystem, TimeoutRecord timeoutRecord,
             ExecutorService auxiliaryTaskExecutor, boolean onlyDumpSelf,
-            boolean isContinuousAnr) {
+            boolean isContinuousAnr, Future<File> firstPidFilePromise) {
         String annotation = timeoutRecord.mReason;
         AnrLatencyTracker latencyTracker = timeoutRecord.mLatencyTracker;
         Future<?> updateCpuStatsNowFirstCall = null;
@@ -321,11 +321,13 @@
         }
 
         final boolean isSilentAnr;
-        final int pid = mApp.getPid();
+        final int pid;
         final UUID errorId;
         latencyTracker.waitingOnAMSLockStarted();
         synchronized (mService) {
             latencyTracker.waitingOnAMSLockEnded();
+            // Get the process's pid after obtaining the global lock.
+            pid = mApp.getPid();
             // Store annotation here as instance above will not be hit on all paths.
             setAnrAnnotation(annotation);
 
@@ -335,7 +337,6 @@
                 Counter.logIncrement("stability_anr.value_skipped_anrs");
                 return;
             }
-
             // In case we come through here for the same app before completing
             // this one, mark as anring now so we will bail out.
             latencyTracker.waitingOnProcLockStarted();
@@ -369,6 +370,9 @@
             firstPids.add(pid);
 
             // Don't dump other PIDs if it's a background ANR or is requested to only dump self.
+            // Note that the primary pid is added here just in case, as it should normally be
+            // dumped on the early dump thread, and would only be dumped on the Anr consumer thread
+            // as a fallback.
             isSilentAnr = isSilentAnr();
             if (!isSilentAnr && !onlyDumpSelf) {
                 int parentPid = pid;
@@ -501,7 +505,8 @@
         File tracesFile = StackTracesDumpHelper.dumpStackTraces(firstPids,
                 isSilentAnr ? null : processCpuTracker, isSilentAnr ? null : lastPids,
                 nativePidsFuture, tracesFileException, firstPidEndOffset, annotation,
-                criticalEventLog, memoryHeaders, auxiliaryTaskExecutor, latencyTracker);
+                criticalEventLog, memoryHeaders, auxiliaryTaskExecutor, firstPidFilePromise,
+                latencyTracker);
 
         if (isMonitorCpuUsage()) {
             // Wait for the first call to finish
diff --git a/services/core/java/com/android/server/am/StackTracesDumpHelper.java b/services/core/java/com/android/server/am/StackTracesDumpHelper.java
index 10ddc2f..d9553a3 100644
--- a/services/core/java/com/android/server/am/StackTracesDumpHelper.java
+++ b/services/core/java/com/android/server/am/StackTracesDumpHelper.java
@@ -41,6 +41,7 @@
 import java.io.PrintWriter;
 import java.io.StringWriter;
 import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
 import java.text.SimpleDateFormat;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -50,6 +51,8 @@
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Executor;
 import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
 import java.util.concurrent.atomic.AtomicLong;
 import java.util.function.Supplier;
 
@@ -65,11 +68,16 @@
             new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss-SSS");
 
     static final String ANR_FILE_PREFIX = "anr_";
-    public static final String ANR_TRACE_DIR = "/data/anr";
+    static final String ANR_TEMP_FILE_PREFIX = "temp_anr_";
 
+    public static final String ANR_TRACE_DIR = "/data/anr";
     private static final int NATIVE_DUMP_TIMEOUT_MS =
             2000 * Build.HW_TIMEOUT_MULTIPLIER; // 2 seconds;
     private static final int JAVA_DUMP_MINIMUM_SIZE = 100; // 100 bytes.
+    // The time limit for a single process's dump
+    private static final int TEMP_DUMP_TIME_LIMIT =
+            10 * 1000 * Build.HW_TIMEOUT_MULTIPLIER; // 10 seconds
+
 
     /**
      * If a stack trace dump file is configured, dump process stack traces.
@@ -85,7 +93,7 @@
             Future<ArrayList<Integer>> nativePidsFuture, StringWriter logExceptionCreatingFile,
             @NonNull Executor auxiliaryTaskExecutor, AnrLatencyTracker latencyTracker) {
         return dumpStackTraces(firstPids, processCpuTracker, lastPids, nativePidsFuture,
-                logExceptionCreatingFile, null, null, null, null, auxiliaryTaskExecutor,
+                logExceptionCreatingFile, null, null, null, null, auxiliaryTaskExecutor, null,
                 latencyTracker);
     }
 
@@ -100,7 +108,7 @@
             AnrLatencyTracker latencyTracker) {
         return dumpStackTraces(firstPids, processCpuTracker, lastPids, nativePidsFuture,
                 logExceptionCreatingFile, null, subject, criticalEventSection,
-                /* memoryHeaders= */ null, auxiliaryTaskExecutor, latencyTracker);
+                /* memoryHeaders= */ null, auxiliaryTaskExecutor, null, latencyTracker);
     }
 
     /**
@@ -112,7 +120,7 @@
             Future<ArrayList<Integer>> nativePidsFuture, StringWriter logExceptionCreatingFile,
             AtomicLong firstPidEndOffset, String subject, String criticalEventSection,
             String memoryHeaders, @NonNull Executor auxiliaryTaskExecutor,
-            AnrLatencyTracker latencyTracker) {
+           Future<File> firstPidFilePromise, AnrLatencyTracker latencyTracker) {
         try {
 
             if (latencyTracker != null) {
@@ -161,7 +169,7 @@
 
             long firstPidEndPos = dumpStackTraces(
                     tracesFile.getAbsolutePath(), firstPids, nativePidsFuture,
-                    extraPidsFuture, latencyTracker);
+                    extraPidsFuture, firstPidFilePromise, latencyTracker);
             if (firstPidEndOffset != null) {
                 firstPidEndOffset.set(firstPidEndPos);
             }
@@ -175,7 +183,6 @@
                 latencyTracker.dumpStackTracesEnded();
             }
         }
-
     }
 
     /**
@@ -183,7 +190,8 @@
      */
     public static long dumpStackTraces(String tracesFile,
             ArrayList<Integer> firstPids, Future<ArrayList<Integer>> nativePidsFuture,
-            Future<ArrayList<Integer>> extraPidsFuture, AnrLatencyTracker latencyTracker) {
+            Future<ArrayList<Integer>> extraPidsFuture, Future<File> firstPidFilePromise,
+            AnrLatencyTracker latencyTracker) {
 
         Slog.i(TAG, "Dumping to " + tracesFile);
 
@@ -194,33 +202,52 @@
         // We must complete all stack dumps within 20 seconds.
         long remainingTime = 20 * 1000 * Build.HW_TIMEOUT_MULTIPLIER;
 
-        // As applications are usually interested with the ANR stack traces, but we can't share with
-        // them the stack traces other than their own stacks. So after the very first PID is
+        // As applications are usually interested with the ANR stack traces, but we can't share
+        // with them the stack traces other than their own stacks. So after the very first PID is
         // dumped, remember the current file size.
         long firstPidEnd = -1;
 
-        // First collect all of the stacks of the most important pids.
-        if (firstPids != null) {
+        // Was the first pid copied from the temporary file that was created in the predump phase?
+        boolean firstPidTempDumpCopied = false;
+
+        // First copy the first pid's dump from the temporary file it was dumped into earlier,
+        // The first pid should always exist in firstPids but we check the size just in case.
+        if (firstPidFilePromise != null && firstPids != null && firstPids.size() > 0) {
+            final int primaryPid = firstPids.get(0);
+            final long start = SystemClock.elapsedRealtime();
+            firstPidTempDumpCopied = copyFirstPidTempDump(tracesFile, firstPidFilePromise,
+                    remainingTime, latencyTracker);
+            final long timeTaken = SystemClock.elapsedRealtime() - start;
+            remainingTime -= timeTaken;
+            if (remainingTime <= 0) {
+                Slog.e(TAG, "Aborting stack trace dump (currently copying primary pid" + primaryPid
+                        + "); deadline exceeded.");
+                return firstPidEnd;
+            }
+             // We don't copy ANR traces from the system_server intentionally.
+            if (firstPidTempDumpCopied && primaryPid != ActivityManagerService.MY_PID) {
+                firstPidEnd = new File(tracesFile).length();
+            }
+            // Append the Durations/latency comma separated array after the first PID.
+            if (latencyTracker != null) {
+                appendtoANRFile(tracesFile,
+                        latencyTracker.dumpAsCommaSeparatedArrayWithHeader());
+            }
+        }
+        // Next collect all of the stacks of the most important pids.
+        if (firstPids != null)  {
             if (latencyTracker != null) {
                 latencyTracker.dumpingFirstPidsStarted();
             }
 
             int num = firstPids.size();
-            for (int i = 0; i < num; i++) {
+            for (int i = firstPidTempDumpCopied ? 1 : 0; i < num; i++) {
                 final int pid = firstPids.get(i);
                 // We don't copy ANR traces from the system_server intentionally.
                 final boolean firstPid = i == 0 && ActivityManagerService.MY_PID != pid;
-                if (latencyTracker != null) {
-                    latencyTracker.dumpingPidStarted(pid);
-                }
-
                 Slog.i(TAG, "Collecting stacks for pid " + pid);
-                final long timeTaken = dumpJavaTracesTombstoned(pid, tracesFile,
-                                                                remainingTime);
-                if (latencyTracker != null) {
-                    latencyTracker.dumpingPidEnded();
-                }
-
+                final long timeTaken = dumpJavaTracesTombstoned(pid, tracesFile, remainingTime,
+                        latencyTracker);
                 remainingTime -= timeTaken;
                 if (remainingTime <= 0) {
                     Slog.e(TAG, "Aborting stack trace dump (current firstPid=" + pid
@@ -304,13 +331,8 @@
             }
             for (int pid : extraPids) {
                 Slog.i(TAG, "Collecting stacks for extra pid " + pid);
-                if (latencyTracker != null) {
-                    latencyTracker.dumpingPidStarted(pid);
-                }
-                final long timeTaken = dumpJavaTracesTombstoned(pid, tracesFile, remainingTime);
-                if (latencyTracker != null) {
-                    latencyTracker.dumpingPidEnded();
-                }
+                final long timeTaken = dumpJavaTracesTombstoned(pid, tracesFile, remainingTime,
+                        latencyTracker);
                 remainingTime -= timeTaken;
                 if (remainingTime <= 0) {
                     Slog.e(TAG, "Aborting stack trace dump (current extra pid=" + pid
@@ -333,6 +355,99 @@
         return firstPidEnd;
     }
 
+    /**
+     * Dumps the supplied pid to a temporary file.
+     * @param pid the PID to be dumped
+     * @param latencyTracker the latency tracker instance of the current ANR.
+     */
+    public static File dumpStackTracesTempFile(int pid, AnrLatencyTracker latencyTracker) {
+        try {
+            if (latencyTracker != null) {
+                latencyTracker.dumpStackTracesTempFileStarted();
+            }
+
+            File tmpTracesFile;
+            try {
+                tmpTracesFile = File.createTempFile(ANR_TEMP_FILE_PREFIX, ".txt",
+                        new File(ANR_TRACE_DIR));
+                Slog.d(TAG, "created ANR temporary file:" + tmpTracesFile.getAbsolutePath());
+            } catch (IOException e) {
+                Slog.w(TAG, "Exception creating temporary ANR dump file:", e);
+                if (latencyTracker != null) {
+                    latencyTracker.dumpStackTracesTempFileCreationFailed();
+                }
+                return null;
+            }
+
+            Slog.i(TAG, "Collecting stacks for pid " + pid + " into temporary file "
+                    + tmpTracesFile.getName());
+            if (latencyTracker != null) {
+                latencyTracker.dumpingPidStarted(pid);
+            }
+            final long timeTaken = dumpJavaTracesTombstoned(pid, tmpTracesFile.getAbsolutePath(),
+                    TEMP_DUMP_TIME_LIMIT);
+            if (latencyTracker != null) {
+                latencyTracker.dumpingPidEnded();
+            }
+            if (TEMP_DUMP_TIME_LIMIT <= timeTaken) {
+                Slog.e(TAG, "Aborted stack trace dump (current primary pid=" + pid
+                        + "); deadline exceeded.");
+                tmpTracesFile.delete();
+                if (latencyTracker != null) {
+                    latencyTracker.dumpStackTracesTempFileTimedOut();
+                }
+                return null;
+            }
+            if (DEBUG_ANR) {
+                Slog.d(TAG, "Done with primary pid " + pid + " in " + timeTaken + "ms"
+                        + " dumped into temporary file " + tmpTracesFile.getName());
+            }
+            return tmpTracesFile;
+        } finally {
+            if (latencyTracker != null) {
+                latencyTracker.dumpStackTracesTempFileEnded();
+            }
+        }
+    }
+
+    private static boolean copyFirstPidTempDump(String tracesFile, Future<File> firstPidFilePromise,
+            long timeLimitMs, AnrLatencyTracker latencyTracker) {
+
+        boolean copySucceeded = false;
+        try (FileOutputStream fos = new FileOutputStream(tracesFile, true))  {
+            if (latencyTracker != null) {
+                latencyTracker.copyingFirstPidStarted();
+            }
+            final File tempfile = firstPidFilePromise.get(timeLimitMs, TimeUnit.MILLISECONDS);
+            if (tempfile != null) {
+                Files.copy(tempfile.toPath(), fos);
+                // Delete the temporary first pid dump file
+                tempfile.delete();
+                copySucceeded = true;
+                return copySucceeded;
+            }
+            return false;
+        } catch (ExecutionException e) {
+            Slog.w(TAG, "Failed to collect the first pid's predump to the main ANR file",
+                    e.getCause());
+            return false;
+        } catch (InterruptedException e) {
+            Slog.w(TAG, "Interrupted while collecting the first pid's predump"
+                    + " to the main ANR file", e);
+            return false;
+        } catch (IOException e) {
+            Slog.w(TAG, "Failed to read the first pid's predump file", e);
+            return false;
+        } catch (TimeoutException e) {
+            Slog.w(TAG, "Copying the first pid timed out", e);
+            return false;
+        } finally {
+            if (latencyTracker != null) {
+                latencyTracker.copyingFirstPidEnded(copySucceeded);
+            }
+        }
+    }
+
     private static synchronized File createAnrDumpFile(File tracesDir) throws IOException {
         final String formattedDate = ANR_FILE_DATE_FORMAT.format(new Date());
         final File anrFile = new File(tracesDir, ANR_FILE_PREFIX + formattedDate);
@@ -409,6 +524,21 @@
             Slog.w(TAG, "tombstone modification times changed while sorting; not pruning", e);
         }
     }
+
+    private static long dumpJavaTracesTombstoned(int pid, String fileName, long timeoutMs,
+            AnrLatencyTracker latencyTracker) {
+        try {
+            if (latencyTracker != null) {
+                latencyTracker.dumpingPidStarted(pid);
+            }
+            return dumpJavaTracesTombstoned(pid, fileName, timeoutMs);
+        } finally {
+            if (latencyTracker != null) {
+                latencyTracker.dumpingPidEnded();
+            }
+        }
+    }
+
     /**
      * Dump java traces for process {@code pid} to the specified file. If java trace dumping
      * fails, a native backtrace is attempted. Note that the timeout {@code timeoutMs} only applies
diff --git a/services/core/java/com/android/server/ambientcontext/AmbientContextManagerService.java b/services/core/java/com/android/server/ambientcontext/AmbientContextManagerService.java
index a9a77bf..46e6001 100644
--- a/services/core/java/com/android/server/ambientcontext/AmbientContextManagerService.java
+++ b/services/core/java/com/android/server/ambientcontext/AmbientContextManagerService.java
@@ -56,6 +56,7 @@
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.concurrent.ConcurrentHashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Objects;
@@ -128,7 +129,7 @@
                 PACKAGE_UPDATE_POLICY_REFRESH_EAGER
                         | /*To avoid high latency*/ PACKAGE_RESTART_POLICY_REFRESH_EAGER);
         mContext = context;
-        mExistingClientRequests = new ArraySet<>();
+        mExistingClientRequests = ConcurrentHashMap.newKeySet();
     }
 
     @Override
@@ -157,18 +158,22 @@
             String callingPackage, IAmbientContextObserver observer) {
         Slog.d(TAG, "New client added: " + callingPackage);
 
-        // Remove any existing ClientRequest for this user and package.
-        mExistingClientRequests.removeAll(
-                findExistingRequests(userId, callingPackage));
+        synchronized (mExistingClientRequests) {
+            // Remove any existing ClientRequest for this user and package.
+            mExistingClientRequests.removeAll(
+                    findExistingRequests(userId, callingPackage));
 
-        // Add to existing ClientRequests
-        mExistingClientRequests.add(
-                new ClientRequest(userId, request, callingPackage, observer));
+            // Add to existing ClientRequests
+            mExistingClientRequests.add(
+                    new ClientRequest(userId, request, callingPackage, observer));
+        }
     }
 
     void clientRemoved(int userId, String packageName) {
         Slog.d(TAG, "Remove client: " + packageName);
-        mExistingClientRequests.removeAll(findExistingRequests(userId, packageName));
+        synchronized (mExistingClientRequests) {
+            mExistingClientRequests.removeAll(findExistingRequests(userId, packageName));
+        }
     }
 
     private Set<ClientRequest> findExistingRequests(int userId, String packageName) {
@@ -183,9 +188,11 @@
 
     @Nullable
     IAmbientContextObserver getClientRequestObserver(int userId, String packageName) {
-        for (ClientRequest clientRequest : mExistingClientRequests) {
-            if (clientRequest.hasUserIdAndPackageName(userId, packageName)) {
-                return clientRequest.getObserver();
+        synchronized (mExistingClientRequests) {
+            for (ClientRequest clientRequest : mExistingClientRequests) {
+                if (clientRequest.hasUserIdAndPackageName(userId, packageName)) {
+                    return clientRequest.getObserver();
+                }
             }
         }
         return null;
@@ -587,10 +594,10 @@
             }
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.ACCESS_AMBIENT_CONTEXT_EVENT)
         @Override
         public void unregisterObserver(String callingPackage) {
-            mContext.enforceCallingOrSelfPermission(
-                    Manifest.permission.ACCESS_AMBIENT_CONTEXT_EVENT, TAG);
+            unregisterObserver_enforcePermission();
             assertCalledByPackageOwner(callingPackage);
 
             synchronized (mLock) {
diff --git a/services/core/java/com/android/server/appop/AppOpMigrationHelper.java b/services/core/java/com/android/server/appop/AppOpMigrationHelper.java
new file mode 100644
index 0000000..bc59dd6
--- /dev/null
+++ b/services/core/java/com/android/server/appop/AppOpMigrationHelper.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.appop;
+
+import android.annotation.NonNull;
+
+import java.util.Map;
+
+/**
+ * In-process api for app-ops migration.
+ *
+ * @hide
+ */
+public interface AppOpMigrationHelper {
+
+    /**
+     * @return a map of app ID to app-op modes (op name -> mode) for a given user.
+     */
+    @NonNull
+    Map<Integer, Map<String, Integer>> getLegacyAppIdAppOpModes(int userId);
+
+    /**
+     * @return a map of package name to app-op modes (op name -> mode) for a given user.
+     */
+    @NonNull
+    Map<String, Map<String, Integer>> getLegacyPackageAppOpModes(int userId);
+
+    /**
+     * @return AppOps file version, the version is same for all the user.
+     */
+    int getLegacyAppOpVersion();
+}
diff --git a/services/core/java/com/android/server/appop/AppOpMigrationHelperImpl.java b/services/core/java/com/android/server/appop/AppOpMigrationHelperImpl.java
new file mode 100644
index 0000000..d81a13f
--- /dev/null
+++ b/services/core/java/com/android/server/appop/AppOpMigrationHelperImpl.java
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.appop;
+
+import android.annotation.NonNull;
+import android.app.AppOpsManager;
+import android.os.UserHandle;
+import android.util.ArrayMap;
+import android.util.AtomicFile;
+import android.util.SparseArray;
+import android.util.SparseIntArray;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.server.SystemServiceManager;
+
+import java.io.File;
+import java.util.Collections;
+import java.util.Map;
+
+/**
+ * Provider of legacy app-ops data for new permission subsystem.
+ *
+ * @hide
+ */
+public class AppOpMigrationHelperImpl implements AppOpMigrationHelper {
+    private SparseArray<Map<Integer, Map<String, Integer>>> mAppIdAppOpModes = null;
+    private SparseArray<Map<String, Map<String, Integer>>> mPackageAppOpModes = null;
+    private int mVersionAtBoot;
+
+    private final Object mLock = new Object();
+
+    @Override
+    @GuardedBy("mLock")
+    @NonNull
+    public Map<Integer, Map<String, Integer>> getLegacyAppIdAppOpModes(int userId) {
+        synchronized (mLock) {
+            if (mAppIdAppOpModes == null) {
+                readLegacyAppOpState();
+            }
+        }
+        return mAppIdAppOpModes.get(userId, Collections.emptyMap());
+    }
+
+    @Override
+    @GuardedBy("mLock")
+    @NonNull
+    public Map<String, Map<String, Integer>> getLegacyPackageAppOpModes(int userId) {
+        synchronized (mLock) {
+            if (mPackageAppOpModes == null) {
+                readLegacyAppOpState();
+            }
+        }
+        return mPackageAppOpModes.get(userId, Collections.emptyMap());
+    }
+
+    @GuardedBy("mLock")
+    private void readLegacyAppOpState() {
+        final File systemDir = SystemServiceManager.ensureSystemDir();
+        AtomicFile appOpFile = new AtomicFile(new File(systemDir, "appops.xml"));
+
+        final SparseArray<SparseIntArray> uidAppOpModes = new SparseArray<>();
+        final SparseArray<ArrayMap<String, SparseIntArray>> packageAppOpModes =
+                new SparseArray<>();
+
+        LegacyAppOpStateParser parser = new LegacyAppOpStateParser();
+        mVersionAtBoot = parser.readState(appOpFile, uidAppOpModes, packageAppOpModes);
+        mAppIdAppOpModes = getAppIdAppOpModes(uidAppOpModes);
+        mPackageAppOpModes = getPackageAppOpModes(packageAppOpModes);
+    }
+
+    private SparseArray<Map<Integer, Map<String, Integer>>> getAppIdAppOpModes(
+            SparseArray<SparseIntArray> uidAppOpModes) {
+        SparseArray<Map<Integer, Map<String, Integer>>> userAppIdAppOpModes = new SparseArray<>();
+
+        int size = uidAppOpModes.size();
+        for (int uidIndex = 0; uidIndex < size; uidIndex++) {
+            int uid = uidAppOpModes.keyAt(uidIndex);
+            int userId = UserHandle.getUserId(uid);
+            Map<Integer, Map<String, Integer>> appIdAppOpModes = userAppIdAppOpModes.get(userId);
+            if (appIdAppOpModes == null) {
+                appIdAppOpModes = new ArrayMap<>();
+                userAppIdAppOpModes.put(userId, appIdAppOpModes);
+            }
+
+            SparseIntArray appOpModes = uidAppOpModes.valueAt(uidIndex);
+            appIdAppOpModes.put(UserHandle.getAppId(uid), getAppOpModesForOpName(appOpModes));
+        }
+        return userAppIdAppOpModes;
+    }
+
+    private SparseArray<Map<String, Map<String, Integer>>> getPackageAppOpModes(
+            SparseArray<ArrayMap<String, SparseIntArray>> legacyPackageAppOpModes) {
+        SparseArray<Map<String, Map<String, Integer>>> userPackageAppOpModes = new SparseArray<>();
+
+        int usersSize = legacyPackageAppOpModes.size();
+        for (int userIndex = 0; userIndex < usersSize; userIndex++) {
+            int userId = legacyPackageAppOpModes.keyAt(userIndex);
+            Map<String, Map<String, Integer>> packageAppOpModes = userPackageAppOpModes.get(userId);
+            if (packageAppOpModes == null) {
+                packageAppOpModes = new ArrayMap<>();
+                userPackageAppOpModes.put(userId, packageAppOpModes);
+            }
+
+            ArrayMap<String, SparseIntArray> legacyPackagesModes =
+                    legacyPackageAppOpModes.valueAt(userIndex);
+
+            int packagesSize = legacyPackagesModes.size();
+            for (int packageIndex = 0; packageIndex < packagesSize; packageIndex++) {
+                String packageName = legacyPackagesModes.keyAt(packageIndex);
+                SparseIntArray modes = legacyPackagesModes.valueAt(packageIndex);
+                packageAppOpModes.put(packageName, getAppOpModesForOpName(modes));
+            }
+        }
+        return userPackageAppOpModes;
+    }
+
+    /**
+     * Converts the map from op code -> mode to op name -> mode.
+     */
+    private Map<String, Integer> getAppOpModesForOpName(SparseIntArray appOpCodeModes) {
+        int modesSize = appOpCodeModes.size();
+        Map<String, Integer> appOpNameModes = new ArrayMap<>(modesSize);
+
+        for (int modeIndex = 0; modeIndex < modesSize; modeIndex++) {
+            int opCode = appOpCodeModes.keyAt(modeIndex);
+            int opMode = appOpCodeModes.valueAt(modeIndex);
+            appOpNameModes.put(AppOpsManager.opToName(opCode), opMode);
+        }
+        return appOpNameModes;
+    }
+
+    @Override
+    public int getLegacyAppOpVersion() {
+        synchronized (mLock) {
+            if (mAppIdAppOpModes == null || mPackageAppOpModes == null) {
+                readLegacyAppOpState();
+            }
+        }
+        return mVersionAtBoot;
+    }
+}
diff --git a/services/core/java/com/android/server/appop/AppOpsCheckingServiceImpl.java b/services/core/java/com/android/server/appop/AppOpsCheckingServiceImpl.java
index f520f6a..886add3 100644
--- a/services/core/java/com/android/server/appop/AppOpsCheckingServiceImpl.java
+++ b/services/core/java/com/android/server/appop/AppOpsCheckingServiceImpl.java
@@ -17,32 +17,19 @@
 package com.android.server.appop;
 
 import static android.app.AppOpsManager.MODE_ALLOWED;
-import static android.app.AppOpsManager.OP_NONE;
+import static android.app.AppOpsManager.MODE_FOREGROUND;
 import static android.app.AppOpsManager.OP_SCHEDULE_EXACT_ALARM;
-import static android.app.AppOpsManager.WATCH_FOREGROUND_CHANGES;
-import static android.app.AppOpsManager.opRestrictsRead;
-import static android.app.AppOpsManager.opToDefaultMode;
 
-import static com.android.server.appop.AppOpsService.ModeCallback.ALL_OPS;
-
-import android.Manifest;
 import android.annotation.NonNull;
-import android.annotation.Nullable;
 import android.annotation.UserIdInt;
-import android.app.AppGlobals;
 import android.app.AppOpsManager;
 import android.app.AppOpsManager.Mode;
 import android.content.Context;
-import android.content.pm.PackageManager;
 import android.content.pm.PackageManagerInternal;
 import android.content.pm.UserPackage;
 import android.os.AsyncTask;
-import android.os.Binder;
 import android.os.Handler;
-import android.os.RemoteException;
-import android.os.UserHandle;
 import android.util.ArrayMap;
-import android.util.ArraySet;
 import android.util.AtomicFile;
 import android.util.Slog;
 import android.util.SparseArray;
@@ -52,30 +39,16 @@
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.XmlUtils;
-import com.android.internal.util.function.pooled.PooledLambda;
-import com.android.modules.utils.TypedXmlPullParser;
 import com.android.modules.utils.TypedXmlSerializer;
 import com.android.server.LocalServices;
 import com.android.server.pm.UserManagerInternal;
 import com.android.server.pm.permission.PermissionManagerServiceInternal;
 
-import libcore.util.EmptyArray;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
 import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
 import java.io.IOException;
-import java.io.PrintWriter;
 import java.util.ArrayList;
-import java.util.Collections;
 import java.util.List;
-import java.util.Objects;
-
 
 /**
  * Legacy implementation for App-ops service's app-op mode (uid and package) storage and access.
@@ -128,9 +101,7 @@
     @GuardedBy("mLock")
     final SparseArray<ArrayMap<String, SparseIntArray>> mUserPackageModes = new SparseArray<>();
 
-    final SparseArray<ArraySet<OnOpModeChangedListener>> mOpModeWatchers = new SparseArray<>();
-    final ArrayMap<String, ArraySet<OnOpModeChangedListener>> mPackageModeWatchers =
-            new ArrayMap<>();
+    private final LegacyAppOpStateParser mAppOpsStateParser = new LegacyAppOpStateParser();
 
     final AtomicFile mFile;
     final Runnable mWriteRunner = new Runnable() {
@@ -153,10 +124,6 @@
     boolean mWriteScheduled;
     boolean mFastWriteScheduled;
 
-
-    // Constant meaning that any UID should be matched when dispatching callbacks
-    private static final int UID_ANY = -2;
-
     AppOpsCheckingServiceImpl(File storageFile,
             @NonNull Object lock, Handler handler, Context context,
             SparseArray<int[]> switchedOps) {
@@ -351,348 +318,43 @@
     }
 
     @Override
-    public void startWatchingOpModeChanged(@NonNull OnOpModeChangedListener changedListener,
-            int op) {
-        Objects.requireNonNull(changedListener);
+    public SparseBooleanArray getForegroundOps(int uid) {
+        SparseBooleanArray result = new SparseBooleanArray();
         synchronized (mLock) {
-            ArraySet<OnOpModeChangedListener> modeWatcherSet = mOpModeWatchers.get(op);
-            if (modeWatcherSet == null) {
-                modeWatcherSet = new ArraySet<>();
-                mOpModeWatchers.put(op, modeWatcherSet);
+            SparseIntArray modes = mUidModes.get(uid);
+            if (modes == null) {
+                return result;
             }
-            modeWatcherSet.add(changedListener);
+            for (int i = 0; i < modes.size(); i++) {
+                if (modes.valueAt(i) == MODE_FOREGROUND) {
+                    result.put(modes.keyAt(i), true);
+                }
+            }
         }
+
+        return result;
     }
 
     @Override
-    public void startWatchingPackageModeChanged(@NonNull OnOpModeChangedListener changedListener,
-            @NonNull String packageName) {
-        Objects.requireNonNull(changedListener);
-        Objects.requireNonNull(packageName);
+    public SparseBooleanArray getForegroundOps(String packageName, int userId) {
+        SparseBooleanArray result = new SparseBooleanArray();
         synchronized (mLock) {
-            ArraySet<OnOpModeChangedListener> modeWatcherSet =
-                    mPackageModeWatchers.get(packageName);
-            if (modeWatcherSet == null) {
-                modeWatcherSet = new ArraySet<>();
-                mPackageModeWatchers.put(packageName, modeWatcherSet);
+            ArrayMap<String, SparseIntArray> packageModes = mUserPackageModes.get(userId);
+            if (packageModes == null) {
+                return result;
             }
-            modeWatcherSet.add(changedListener);
-        }
-    }
-
-    @Override
-    public void removeListener(@NonNull OnOpModeChangedListener changedListener) {
-        Objects.requireNonNull(changedListener);
-
-        synchronized (mLock) {
-            for (int i = mOpModeWatchers.size() - 1; i >= 0; i--) {
-                ArraySet<OnOpModeChangedListener> cbs = mOpModeWatchers.valueAt(i);
-                cbs.remove(changedListener);
-                if (cbs.size() <= 0) {
-                    mOpModeWatchers.removeAt(i);
-                }
+            SparseIntArray modes = packageModes.get(packageName);
+            if (modes == null) {
+                return result;
             }
-
-            for (int i = mPackageModeWatchers.size() - 1; i >= 0; i--) {
-                ArraySet<OnOpModeChangedListener> cbs = mPackageModeWatchers.valueAt(i);
-                cbs.remove(changedListener);
-                if (cbs.size() <= 0) {
-                    mPackageModeWatchers.removeAt(i);
-                }
-            }
-        }
-    }
-
-    @Override
-    public ArraySet<OnOpModeChangedListener> getOpModeChangedListeners(int op) {
-        synchronized (mLock) {
-            ArraySet<OnOpModeChangedListener> modeChangedListenersSet = mOpModeWatchers.get(op);
-            if (modeChangedListenersSet == null) {
-                return new ArraySet<>();
-            }
-            return new ArraySet<>(modeChangedListenersSet);
-        }
-    }
-
-    @Override
-    public ArraySet<OnOpModeChangedListener> getPackageModeChangedListeners(
-            @NonNull String packageName) {
-        Objects.requireNonNull(packageName);
-
-        synchronized (mLock) {
-            ArraySet<OnOpModeChangedListener> modeChangedListenersSet =
-                    mPackageModeWatchers.get(packageName);
-            if (modeChangedListenersSet == null) {
-                return new ArraySet<>();
-            }
-            return new ArraySet<>(modeChangedListenersSet);
-        }
-    }
-
-    @Override
-    public void notifyWatchersOfChange(int code, int uid) {
-        ArraySet<OnOpModeChangedListener> listenerSet = getOpModeChangedListeners(code);
-        if (listenerSet == null) {
-            return;
-        }
-        for (int i = 0; i < listenerSet.size(); i++) {
-            final OnOpModeChangedListener listener = listenerSet.valueAt(i);
-            notifyOpChanged(listener, code, uid, null);
-        }
-    }
-
-    @Override
-    public void notifyOpChanged(@NonNull OnOpModeChangedListener onModeChangedListener, int code,
-            int uid, @Nullable String packageName) {
-        Objects.requireNonNull(onModeChangedListener);
-
-        if (uid != UID_ANY && onModeChangedListener.getWatchingUid() >= 0
-                && onModeChangedListener.getWatchingUid() != uid) {
-            return;
-        }
-
-        // See CALL_BACK_ON_CHANGED_LISTENER_WITH_SWITCHED_OP_CHANGE
-        int[] switchedCodes;
-        if (onModeChangedListener.getWatchedOpCode() == ALL_OPS) {
-            switchedCodes = mSwitchedOps.get(code);
-        } else if (onModeChangedListener.getWatchedOpCode() == OP_NONE) {
-            switchedCodes = new int[]{code};
-        } else {
-            switchedCodes = new int[]{onModeChangedListener.getWatchedOpCode()};
-        }
-
-        for (int switchedCode : switchedCodes) {
-            // There are features watching for mode changes such as window manager
-            // and location manager which are in our process. The callbacks in these
-            // features may require permissions our remote caller does not have.
-            final long identity = Binder.clearCallingIdentity();
-            try {
-                if (shouldIgnoreCallback(switchedCode, onModeChangedListener.getCallingPid(),
-                        onModeChangedListener.getCallingUid())) {
-                    continue;
-                }
-                onModeChangedListener.onOpModeChanged(switchedCode, uid, packageName);
-            } catch (RemoteException e) {
-                /* ignore */
-            } finally {
-                Binder.restoreCallingIdentity(identity);
-            }
-        }
-    }
-
-    private boolean shouldIgnoreCallback(int op, int watcherPid, int watcherUid) {
-        // If it's a restricted read op, ignore it if watcher doesn't have manage ops permission,
-        // as watcher should not use this to signal if the value is changed.
-        return opRestrictsRead(op) && mContext.checkPermission(Manifest.permission.MANAGE_APPOPS,
-                watcherPid, watcherUid) != PackageManager.PERMISSION_GRANTED;
-    }
-
-    @Override
-    public void notifyOpChangedForAllPkgsInUid(int code, int uid, boolean onlyForeground,
-            @Nullable OnOpModeChangedListener callbackToIgnore) {
-        String[] uidPackageNames = getPackagesForUid(uid);
-        ArrayMap<OnOpModeChangedListener, ArraySet<String>> callbackSpecs = null;
-
-        synchronized (mLock) {
-            ArraySet<OnOpModeChangedListener> callbacks = mOpModeWatchers.get(code);
-            if (callbacks != null) {
-                final int callbackCount = callbacks.size();
-                for (int i = 0; i < callbackCount; i++) {
-                    OnOpModeChangedListener callback = callbacks.valueAt(i);
-
-                    if (onlyForeground && (callback.getFlags()
-                            & WATCH_FOREGROUND_CHANGES) == 0) {
-                        continue;
-                    }
-
-                    ArraySet<String> changedPackages = new ArraySet<>();
-                    Collections.addAll(changedPackages, uidPackageNames);
-                    if (callbackSpecs == null) {
-                        callbackSpecs = new ArrayMap<>();
-                    }
-                    callbackSpecs.put(callback, changedPackages);
-                }
-            }
-
-            for (String uidPackageName : uidPackageNames) {
-                callbacks = mPackageModeWatchers.get(uidPackageName);
-                if (callbacks != null) {
-                    if (callbackSpecs == null) {
-                        callbackSpecs = new ArrayMap<>();
-                    }
-                    final int callbackCount = callbacks.size();
-                    for (int i = 0; i < callbackCount; i++) {
-                        OnOpModeChangedListener callback = callbacks.valueAt(i);
-
-                        if (onlyForeground && (callback.getFlags()
-                                & WATCH_FOREGROUND_CHANGES) == 0) {
-                            continue;
-                        }
-
-                        ArraySet<String> changedPackages = callbackSpecs.get(callback);
-                        if (changedPackages == null) {
-                            changedPackages = new ArraySet<>();
-                            callbackSpecs.put(callback, changedPackages);
-                        }
-                        changedPackages.add(uidPackageName);
-                    }
-                }
-            }
-
-            if (callbackSpecs != null && callbackToIgnore != null) {
-                callbackSpecs.remove(callbackToIgnore);
-            }
-        }
-
-        if (callbackSpecs == null) {
-            return;
-        }
-
-        for (int i = 0; i < callbackSpecs.size(); i++) {
-            final OnOpModeChangedListener callback = callbackSpecs.keyAt(i);
-            final ArraySet<String> reportedPackageNames = callbackSpecs.valueAt(i);
-            if (reportedPackageNames == null) {
-                mHandler.sendMessage(PooledLambda.obtainMessage(
-                        AppOpsCheckingServiceImpl::notifyOpChanged,
-                        this, callback, code, uid, (String) null));
-
-            } else {
-                final int reportedPackageCount = reportedPackageNames.size();
-                for (int j = 0; j < reportedPackageCount; j++) {
-                    final String reportedPackageName = reportedPackageNames.valueAt(j);
-                    mHandler.sendMessage(PooledLambda.obtainMessage(
-                            AppOpsCheckingServiceImpl::notifyOpChanged,
-                            this, callback, code, uid, reportedPackageName));
-                }
-            }
-        }
-    }
-
-    private static String[] getPackagesForUid(int uid) {
-        String[] packageNames = null;
-
-        // Very early during boot the package manager is not yet or not yet fully started. At this
-        // time there are no packages yet.
-        if (AppGlobals.getPackageManager() != null) {
-            try {
-                packageNames = AppGlobals.getPackageManager().getPackagesForUid(uid);
-            } catch (RemoteException e) {
-                /* ignore - local call */
-            }
-        }
-        if (packageNames == null) {
-            return EmptyArray.STRING;
-        }
-        return packageNames;
-    }
-
-    @Override
-    public SparseBooleanArray evalForegroundUidOps(int uid, SparseBooleanArray foregroundOps) {
-        synchronized (mLock) {
-            return evalForegroundOps(mUidModes.get(uid), foregroundOps);
-        }
-    }
-
-    @Override
-    public SparseBooleanArray evalForegroundPackageOps(String packageName,
-            SparseBooleanArray foregroundOps, @UserIdInt int userId) {
-        synchronized (mLock) {
-            ArrayMap<String, SparseIntArray> packageModes = mUserPackageModes.get(userId, null);
-            return evalForegroundOps(packageModes == null ? null : packageModes.get(packageName),
-                    foregroundOps);
-        }
-    }
-
-    private SparseBooleanArray evalForegroundOps(SparseIntArray opModes,
-            SparseBooleanArray foregroundOps) {
-        SparseBooleanArray tempForegroundOps = foregroundOps;
-        if (opModes != null) {
-            for (int i = opModes.size() - 1; i >= 0; i--) {
-                if (opModes.valueAt(i) == AppOpsManager.MODE_FOREGROUND) {
-                    if (tempForegroundOps == null) {
-                        tempForegroundOps = new SparseBooleanArray();
-                    }
-                    evalForegroundWatchers(opModes.keyAt(i), tempForegroundOps);
-                }
-            }
-        }
-        return tempForegroundOps;
-    }
-
-    private void evalForegroundWatchers(int op, SparseBooleanArray foregroundOps) {
-        boolean curValue = foregroundOps.get(op, false);
-        ArraySet<OnOpModeChangedListener> listenerSet = mOpModeWatchers.get(op);
-        if (listenerSet != null) {
-            for (int cbi = listenerSet.size() - 1; !curValue && cbi >= 0; cbi--) {
-                if ((listenerSet.valueAt(cbi).getFlags()
-                        & AppOpsManager.WATCH_FOREGROUND_CHANGES) != 0) {
-                    curValue = true;
-                }
-            }
-        }
-        foregroundOps.put(op, curValue);
-    }
-
-    @Override
-    public boolean dumpListeners(int dumpOp, int dumpUid, String dumpPackage,
-            PrintWriter printWriter) {
-        boolean needSep = false;
-        if (mOpModeWatchers.size() > 0) {
-            boolean printedHeader = false;
-            for (int i = 0; i < mOpModeWatchers.size(); i++) {
-                if (dumpOp >= 0 && dumpOp != mOpModeWatchers.keyAt(i)) {
-                    continue;
-                }
-                boolean printedOpHeader = false;
-                ArraySet<OnOpModeChangedListener> modeChangedListenerSet =
-                        mOpModeWatchers.valueAt(i);
-                for (int j = 0; j < modeChangedListenerSet.size(); j++) {
-                    final OnOpModeChangedListener listener = modeChangedListenerSet.valueAt(j);
-                    if (dumpPackage != null
-                            && dumpUid != UserHandle.getAppId(listener.getWatchingUid())) {
-                        continue;
-                    }
-                    needSep = true;
-                    if (!printedHeader) {
-                        printWriter.println("  Op mode watchers:");
-                        printedHeader = true;
-                    }
-                    if (!printedOpHeader) {
-                        printWriter.print("    Op ");
-                        printWriter.print(AppOpsManager.opToName(mOpModeWatchers.keyAt(i)));
-                        printWriter.println(":");
-                        printedOpHeader = true;
-                    }
-                    printWriter.print("      #"); printWriter.print(j); printWriter.print(": ");
-                    printWriter.println(listener.toString());
+            for (int i = 0; i < modes.size(); i++) {
+                if (modes.valueAt(i) == MODE_FOREGROUND) {
+                    result.put(modes.keyAt(i), true);
                 }
             }
         }
 
-        if (mPackageModeWatchers.size() > 0 && dumpOp < 0) {
-            boolean printedHeader = false;
-            for (int i = 0; i < mPackageModeWatchers.size(); i++) {
-                if (dumpPackage != null
-                        && !dumpPackage.equals(mPackageModeWatchers.keyAt(i))) {
-                    continue;
-                }
-                needSep = true;
-                if (!printedHeader) {
-                    printWriter.println("  Package mode watchers:");
-                    printedHeader = true;
-                }
-                printWriter.print("    Pkg "); printWriter.print(mPackageModeWatchers.keyAt(i));
-                printWriter.println(":");
-                ArraySet<OnOpModeChangedListener> modeChangedListenerSet =
-                        mPackageModeWatchers.valueAt(i);
-
-                for (int j = 0; j < modeChangedListenerSet.size(); j++) {
-                    printWriter.print("      #"); printWriter.print(j); printWriter.print(": ");
-                    printWriter.println(modeChangedListenerSet.valueAt(j).toString());
-                }
-            }
-        }
-        return needSep;
+        return result;
     }
 
     private void scheduleWriteLocked() {
@@ -832,58 +494,7 @@
     public void readState() {
         synchronized (mFile) {
             synchronized (mLock) {
-                FileInputStream stream;
-                try {
-                    stream = mFile.openRead();
-                } catch (FileNotFoundException e) {
-                    Slog.i(TAG, "No existing app ops " + mFile.getBaseFile() + "; starting empty");
-                    mVersionAtBoot = NO_FILE_VERSION;
-                    return;
-                }
-
-                try {
-                    TypedXmlPullParser parser = Xml.resolvePullParser(stream);
-                    int type;
-                    while ((type = parser.next()) != XmlPullParser.START_TAG
-                            && type != XmlPullParser.END_DOCUMENT) {
-                        // Parse next until we reach the start or end
-                    }
-
-                    if (type != XmlPullParser.START_TAG) {
-                        throw new IllegalStateException("no start tag found");
-                    }
-
-                    mVersionAtBoot = parser.getAttributeInt(null, "v", NO_VERSION);
-
-                    int outerDepth = parser.getDepth();
-                    while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
-                            && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
-                        if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
-                            continue;
-                        }
-
-                        String tagName = parser.getName();
-                        if (tagName.equals("pkg")) {
-                            // version 2 has the structure pkg -> uid -> op ->
-                            // in version 3, since pkg and uid states are kept completely
-                            // independent we switch to user -> pkg -> op
-                            readPackage(parser);
-                        } else if (tagName.equals("uid")) {
-                            readUidOps(parser);
-                        } else if (tagName.equals("user")) {
-                            readUser(parser);
-                        } else {
-                            Slog.w(TAG, "Unknown element under <app-ops>: "
-                                    + parser.getName());
-                            XmlUtils.skipCurrentTag(parser);
-                        }
-                    }
-                    return;
-                } catch (XmlPullParserException e) {
-                    throw new RuntimeException(e);
-                } catch (IOException e) {
-                    throw new RuntimeException(e);
-                }
+                mVersionAtBoot = mAppOpsStateParser.readState(mFile, mUidModes, mUserPackageModes);
             }
         }
     }
@@ -905,162 +516,6 @@
     }
 
     @GuardedBy("mLock")
-    private void readUidOps(TypedXmlPullParser parser) throws NumberFormatException,
-            XmlPullParserException, IOException {
-        final int uid = parser.getAttributeInt(null, "n");
-        SparseIntArray modes = mUidModes.get(uid);
-        if (modes == null) {
-            modes = new SparseIntArray();
-            mUidModes.put(uid, modes);
-        }
-
-        int outerDepth = parser.getDepth();
-        int type;
-        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
-                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
-            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
-                continue;
-            }
-
-            String tagName = parser.getName();
-            if (tagName.equals("op")) {
-                final int code = parser.getAttributeInt(null, "n");
-                final int mode = parser.getAttributeInt(null, "m");
-
-                if (mode != opToDefaultMode(code)) {
-                    modes.put(code, mode);
-                }
-            } else {
-                Slog.w(TAG, "Unknown element under <uid>: "
-                        + parser.getName());
-                XmlUtils.skipCurrentTag(parser);
-            }
-        }
-    }
-
-    /*
-     * Used for migration when pkg is the depth=1 tag
-     */
-    @GuardedBy("mLock")
-    private void readPackage(TypedXmlPullParser parser)
-            throws NumberFormatException, XmlPullParserException, IOException {
-        String pkgName = parser.getAttributeValue(null, "n");
-        int outerDepth = parser.getDepth();
-        int type;
-        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
-                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
-            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
-                continue;
-            }
-
-            String tagName = parser.getName();
-            if (tagName.equals("uid")) {
-                readUid(parser, pkgName);
-            } else {
-                Slog.w(TAG, "Unknown element under <pkg>: "
-                        + parser.getName());
-                XmlUtils.skipCurrentTag(parser);
-            }
-        }
-    }
-
-    /*
-     * Used for migration when uid is the depth=2 tag
-     */
-    @GuardedBy("mLock")
-    private void readUid(TypedXmlPullParser parser, String pkgName)
-            throws NumberFormatException, XmlPullParserException, IOException {
-        int userId = UserHandle.getUserId(parser.getAttributeInt(null, "n"));
-        int outerDepth = parser.getDepth();
-        int type;
-        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
-                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
-            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
-                continue;
-            }
-
-            String tagName = parser.getName();
-            if (tagName.equals("op")) {
-                readOp(parser, userId, pkgName);
-            } else {
-                Slog.w(TAG, "Unknown element under <pkg>: "
-                        + parser.getName());
-                XmlUtils.skipCurrentTag(parser);
-            }
-        }
-    }
-
-    @GuardedBy("mLock")
-    private void readUser(TypedXmlPullParser parser)
-            throws NumberFormatException, XmlPullParserException, IOException {
-        int userId = parser.getAttributeInt(null, "n");
-        int outerDepth = parser.getDepth();
-        int type;
-        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
-                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
-            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
-                continue;
-            }
-
-            String tagName = parser.getName();
-            if (tagName.equals("pkg")) {
-                readPackage(parser, userId);
-            } else {
-                Slog.w(TAG, "Unknown element under <user>: "
-                        + parser.getName());
-                XmlUtils.skipCurrentTag(parser);
-            }
-        }
-    }
-
-    @GuardedBy("mLock")
-    private void readPackage(TypedXmlPullParser parser, int userId)
-            throws NumberFormatException, XmlPullParserException, IOException {
-        String pkgName = parser.getAttributeValue(null, "n");
-        int outerDepth = parser.getDepth();
-        int type;
-        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
-                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
-            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
-                continue;
-            }
-
-            String tagName = parser.getName();
-            if (tagName.equals("op")) {
-                readOp(parser, userId, pkgName);
-            } else {
-                Slog.w(TAG, "Unknown element under <pkg>: "
-                        + parser.getName());
-                XmlUtils.skipCurrentTag(parser);
-            }
-        }
-    }
-
-    @GuardedBy("mLock")
-    private void readOp(TypedXmlPullParser parser, int userId, @NonNull String pkgName)
-            throws NumberFormatException, XmlPullParserException {
-        final int opCode = parser.getAttributeInt(null, "n");
-        final int defaultMode = AppOpsManager.opToDefaultMode(opCode);
-        final int mode = parser.getAttributeInt(null, "m", defaultMode);
-
-        if (mode != defaultMode) {
-            ArrayMap<String, SparseIntArray> packageModes = mUserPackageModes.get(userId);
-            if (packageModes == null) {
-                packageModes = new ArrayMap<>();
-                mUserPackageModes.put(userId, packageModes);
-            }
-
-            SparseIntArray modes = packageModes.get(pkgName);
-            if (modes == null) {
-                modes = new SparseIntArray();
-                packageModes.put(pkgName, modes);
-            }
-
-            modes.put(opCode, mode);
-        }
-    }
-
-    @GuardedBy("mLock")
     private void upgradeLocked(int oldVersion) {
         if (oldVersion == NO_FILE_VERSION || oldVersion >= CURRENT_VERSION) {
             return;
diff --git a/services/core/java/com/android/server/appop/AppOpsCheckingServiceInterface.java b/services/core/java/com/android/server/appop/AppOpsCheckingServiceInterface.java
index 9096898..76f1f8a 100644
--- a/services/core/java/com/android/server/appop/AppOpsCheckingServiceInterface.java
+++ b/services/core/java/com/android/server/appop/AppOpsCheckingServiceInterface.java
@@ -16,17 +16,13 @@
 package com.android.server.appop;
 
 import android.annotation.NonNull;
-import android.annotation.Nullable;
 import android.annotation.UserIdInt;
 import android.app.AppOpsManager.Mode;
-import android.util.ArraySet;
 import android.util.SparseBooleanArray;
 import android.util.SparseIntArray;
 
 import com.android.internal.annotations.VisibleForTesting;
 
-import java.io.PrintWriter;
-
 /**
  * Interface for accessing and modifying modes for app-ops i.e. package and uid modes.
  * This interface also includes functions for added and removing op mode watchers.
@@ -148,99 +144,18 @@
     void clearAllModes();
 
     /**
-     * Registers changedListener to listen to op's mode change.
-     * @param changedListener the listener that must be trigger on the op's mode change.
-     * @param op op representing the app-op whose mode change needs to be listened to.
+     * @param uid UID to query foreground ops for.
+     * @return SparseBooleanArray where the keys are the op codes for which their modes are
+     * MODE_FOREGROUND for the passed UID.
      */
-    void startWatchingOpModeChanged(@NonNull OnOpModeChangedListener changedListener, int op);
+    SparseBooleanArray getForegroundOps(int uid);
 
     /**
-     * Registers changedListener to listen to package's app-op's mode change.
-     * @param changedListener the listener that must be trigger on the mode change.
-     * @param packageName of the package whose app-op's mode change needs to be listened to.
+     *
+     * @param packageName Package name to check for.
+     * @param userId User ID to check for.
+     * @return SparseBooleanArray where the keys are the op codes for which their modes are
+     * MODE_FOREGROUND for the passed package name and user ID.
      */
-    void startWatchingPackageModeChanged(@NonNull OnOpModeChangedListener changedListener,
-            @NonNull String packageName);
-
-    /**
-     * Stop the changedListener from triggering on any mode change.
-     * @param changedListener the listener that needs to be removed.
-     */
-    void removeListener(@NonNull OnOpModeChangedListener changedListener);
-
-    /**
-     * Temporary API which will be removed once we can safely untangle the methods that use this.
-     * Returns a set of OnOpModeChangedListener that are listening for op's mode changes.
-     * @param op app-op whose mode change is being listened to.
-     */
-    ArraySet<OnOpModeChangedListener> getOpModeChangedListeners(int op);
-
-    /**
-     * Temporary API which will be removed once we can safely untangle the methods that use this.
-     * Returns a set of OnOpModeChangedListener that are listening for package's op's mode changes.
-     * @param packageName of package whose app-op's mode change is being listened to.
-     */
-    ArraySet<OnOpModeChangedListener> getPackageModeChangedListeners(@NonNull String packageName);
-
-    /**
-     * Temporary API which will be removed once we can safely untangle the methods that use this.
-     * Notify that the app-op's mode is changed by triggering the change listener.
-     * @param op App-op whose mode has changed
-     * @param uid user id associated with the app-op (or, if UID_ANY, notifies all users)
-     */
-    void notifyWatchersOfChange(int op, int uid);
-
-    /**
-     * Temporary API which will be removed once we can safely untangle the methods that use this.
-     * Notify that the app-op's mode is changed by triggering the change listener.
-     * @param changedListener the change listener.
-     * @param op App-op whose mode has changed
-     * @param uid user id associated with the app-op
-     * @param packageName package name that is associated with the app-op
-     */
-    void notifyOpChanged(@NonNull OnOpModeChangedListener changedListener, int op, int uid,
-            @Nullable String packageName);
-
-    /**
-     * Temporary API which will be removed once we can safely untangle the methods that use this.
-     * Notify that the app-op's mode is changed to all packages associated with the uid by
-     * triggering the appropriate change listener.
-     * @param op App-op whose mode has changed
-     * @param uid user id associated with the app-op
-     * @param onlyForeground true if only watchers that
-     * @param callbackToIgnore callback that should be ignored.
-     */
-    void notifyOpChangedForAllPkgsInUid(int op, int uid, boolean onlyForeground,
-            @Nullable OnOpModeChangedListener callbackToIgnore);
-
-    /**
-     * TODO: Move hasForegroundWatchers and foregroundOps into this.
-     * Go over the list of app-ops for the uid and mark app-ops with MODE_FOREGROUND in
-     * foregroundOps.
-     * @param uid for which the app-op's mode needs to be marked.
-     * @param foregroundOps boolean array where app-ops that have MODE_FOREGROUND are marked true.
-     * @return  foregroundOps.
-     */
-    SparseBooleanArray evalForegroundUidOps(int uid, SparseBooleanArray foregroundOps);
-
-    /**
-     * Go over the list of app-ops for the package name and mark app-ops with MODE_FOREGROUND in
-     * foregroundOps.
-     * @param packageName for which the app-op's mode needs to be marked.
-     * @param foregroundOps boolean array where app-ops that have MODE_FOREGROUND are marked true.
-     * @param userId user id associated with the package.
-     * @return foregroundOps.
-     */
-    SparseBooleanArray evalForegroundPackageOps(String packageName,
-            SparseBooleanArray foregroundOps, @UserIdInt int userId);
-
-    /**
-     * Dump op mode and package mode listeners and their details.
-     * @param dumpOp if -1 then op mode listeners for all app-ops are dumped. If it's set to an
-     *               app-op, only the watchers for that app-op are dumped.
-     * @param dumpUid uid for which we want to dump op mode watchers.
-     * @param dumpPackage if not null and if dumpOp is -1, dumps watchers for the package name.
-     * @param printWriter writer to dump to.
-     */
-    boolean dumpListeners(int dumpOp, int dumpUid, String dumpPackage, PrintWriter printWriter);
+    SparseBooleanArray getForegroundOps(String packageName, int userId);
 }
diff --git a/services/core/java/com/android/server/appop/AppOpsCheckingServiceLoggingDecorator.java b/services/core/java/com/android/server/appop/AppOpsCheckingServiceLoggingDecorator.java
index 0094b86..32dcb5a 100644
--- a/services/core/java/com/android/server/appop/AppOpsCheckingServiceLoggingDecorator.java
+++ b/services/core/java/com/android/server/appop/AppOpsCheckingServiceLoggingDecorator.java
@@ -17,14 +17,10 @@
 package com.android.server.appop;
 
 import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.util.ArraySet;
 import android.util.Log;
 import android.util.SparseBooleanArray;
 import android.util.SparseIntArray;
 
-import java.io.PrintWriter;
-
 /**
  * Logging decorator for {@link AppOpsCheckingServiceInterface}.
  */
@@ -134,83 +130,15 @@
     }
 
     @Override
-    public void startWatchingOpModeChanged(@NonNull OnOpModeChangedListener changedListener,
-            int op) {
-        Log.i(LOG_TAG, "startWatchingOpModeChanged(changedListener = " + changedListener + ", op = "
-                + op + ")");
-        mService.startWatchingOpModeChanged(changedListener, op);
+    public SparseBooleanArray getForegroundOps(int uid) {
+        Log.i(LOG_TAG, "getForegroundOps(uid = " + uid + ")");
+        return mService.getForegroundOps(uid);
     }
 
     @Override
-    public void startWatchingPackageModeChanged(@NonNull OnOpModeChangedListener changedListener,
-            @NonNull String packageName) {
-        Log.i(LOG_TAG, "startWatchingPackageModeChanged(changedListener = " + changedListener
-                + ", packageName = " + packageName + ")");
-        mService.startWatchingPackageModeChanged(changedListener, packageName);
-    }
-
-    @Override
-    public void removeListener(@NonNull OnOpModeChangedListener changedListener) {
-        Log.i(LOG_TAG, "removeListener(changedListener = " + changedListener + ")");
-        mService.removeListener(changedListener);
-    }
-
-    @Override
-    public ArraySet<OnOpModeChangedListener> getOpModeChangedListeners(int op) {
-        Log.i(LOG_TAG, "getOpModeChangedListeners(op = " + op + ")");
-        return mService.getOpModeChangedListeners(op);
-    }
-
-    @Override
-    public ArraySet<OnOpModeChangedListener> getPackageModeChangedListeners(
-            @NonNull String packageName) {
-        Log.i(LOG_TAG, "getPackageModeChangedListeners(packageName = " + packageName + ")");
-        return mService.getPackageModeChangedListeners(packageName);
-    }
-
-    @Override
-    public void notifyWatchersOfChange(int op, int uid) {
-        Log.i(LOG_TAG, "notifyWatchersOfChange(op = " + op + ", uid = " + uid + ")");
-        mService.notifyWatchersOfChange(op, uid);
-    }
-
-    @Override
-    public void notifyOpChanged(@NonNull OnOpModeChangedListener changedListener, int op, int uid,
-            @Nullable String packageName) {
-        Log.i(LOG_TAG, "notifyOpChanged(changedListener = " + changedListener + ", op = " + op
-                + ", uid = " + uid + ", packageName = " + packageName + ")");
-        mService.notifyOpChanged(changedListener, op, uid, packageName);
-    }
-
-    @Override
-    public void notifyOpChangedForAllPkgsInUid(int op, int uid, boolean onlyForeground,
-            @Nullable OnOpModeChangedListener callbackToIgnore) {
-        Log.i(LOG_TAG, "notifyOpChangedForAllPkgsInUid(op = " + op + ", uid = " + uid
-                + ", onlyForeground = " + onlyForeground + ", callbackToIgnore = "
-                + callbackToIgnore + ")");
-        mService.notifyOpChangedForAllPkgsInUid(op, uid, onlyForeground, callbackToIgnore);
-    }
-
-    @Override
-    public SparseBooleanArray evalForegroundUidOps(int uid, SparseBooleanArray foregroundOps) {
-        Log.i(LOG_TAG, "evalForegroundUidOps(uid = " + uid + ", foregroundOps = " + foregroundOps
+    public SparseBooleanArray getForegroundOps(String packageName, int userId) {
+        Log.i(LOG_TAG, "getForegroundOps(packageName = " + packageName + ", userId = " + userId
                 + ")");
-        return mService.evalForegroundUidOps(uid, foregroundOps);
-    }
-
-    @Override
-    public SparseBooleanArray evalForegroundPackageOps(String packageName,
-            SparseBooleanArray foregroundOps, int userId) {
-        Log.i(LOG_TAG, "evalForegroundPackageOps(packageName = " + packageName
-                + ", foregroundOps = " + foregroundOps + ", userId = " + userId + ")");
-        return mService.evalForegroundPackageOps(packageName, foregroundOps, userId);
-    }
-
-    @Override
-    public boolean dumpListeners(int dumpOp, int dumpUid, String dumpPackage,
-            PrintWriter printWriter) {
-        Log.i(LOG_TAG, "dumpListeners(dumpOp = " + dumpOp + ", dumpUid = " + dumpUid
-                + ", dumpPackage = " + dumpPackage + ", printWriter = " + printWriter + ")");
-        return mService.dumpListeners(dumpOp, dumpUid, dumpPackage, printWriter);
+        return mService.getForegroundOps(packageName, userId);
     }
 }
diff --git a/services/core/java/com/android/server/appop/AppOpsCheckingServiceTracingDecorator.java b/services/core/java/com/android/server/appop/AppOpsCheckingServiceTracingDecorator.java
index a028ae1..91dbc23 100644
--- a/services/core/java/com/android/server/appop/AppOpsCheckingServiceTracingDecorator.java
+++ b/services/core/java/com/android/server/appop/AppOpsCheckingServiceTracingDecorator.java
@@ -17,16 +17,12 @@
 package com.android.server.appop;
 
 import android.annotation.NonNull;
-import android.annotation.Nullable;
 import android.annotation.UserIdInt;
 import android.app.AppOpsManager;
 import android.os.Trace;
-import android.util.ArraySet;
 import android.util.SparseBooleanArray;
 import android.util.SparseIntArray;
 
-import java.io.PrintWriter;
-
 /**
  * Surrounds all AppOpsCheckingServiceInterface method calls with Trace.traceBegin and
  * Trace.traceEnd. These traces are used for performance testing.
@@ -205,128 +201,22 @@
     }
 
     @Override
-    public void startWatchingOpModeChanged(@NonNull OnOpModeChangedListener changedListener,
-            int op) {
+    public SparseBooleanArray getForegroundOps(int uid) {
         Trace.traceBegin(TRACE_TAG,
-                "TaggedTracingAppOpsCheckingServiceInterfaceImpl#startWatchingOpModeChanged");
+                "TaggedTracingAppOpsCheckingServiceInterfaceImpl#getForegroundOps");
         try {
-            mService.startWatchingOpModeChanged(changedListener, op);
+            return mService.getForegroundOps(uid);
         } finally {
             Trace.traceEnd(TRACE_TAG);
         }
     }
 
     @Override
-    public void startWatchingPackageModeChanged(@NonNull OnOpModeChangedListener changedListener,
-            @NonNull String packageName) {
+    public SparseBooleanArray getForegroundOps(String packageName, int userId) {
         Trace.traceBegin(TRACE_TAG,
-                "TaggedTracingAppOpsCheckingServiceInterfaceImpl#startWatchingPackageModeChanged");
+                "TaggedTracingAppOpsCheckingServiceInterfaceImpl#getForegroundOps");
         try {
-            mService.startWatchingPackageModeChanged(changedListener, packageName);
-        } finally {
-            Trace.traceEnd(TRACE_TAG);
-        }
-    }
-
-    @Override
-    public void removeListener(@NonNull OnOpModeChangedListener changedListener) {
-        Trace.traceBegin(TRACE_TAG,
-                "TaggedTracingAppOpsCheckingServiceInterfaceImpl#removeListener");
-        try {
-            mService.removeListener(changedListener);
-        } finally {
-            Trace.traceEnd(TRACE_TAG);
-        }
-    }
-
-    @Override
-    public ArraySet<OnOpModeChangedListener> getOpModeChangedListeners(int op) {
-        Trace.traceBegin(TRACE_TAG,
-                "TaggedTracingAppOpsCheckingServiceInterfaceImpl#getOpModeChangedListeners");
-        try {
-            return mService.getOpModeChangedListeners(op);
-        } finally {
-            Trace.traceEnd(TRACE_TAG);
-        }
-    }
-
-    @Override
-    public ArraySet<OnOpModeChangedListener> getPackageModeChangedListeners(
-            @NonNull String packageName) {
-        Trace.traceBegin(TRACE_TAG,
-                "TaggedTracingAppOpsCheckingServiceInterfaceImpl#getPackageModeChangedListeners");
-        try {
-            return mService.getPackageModeChangedListeners(packageName);
-        } finally {
-            Trace.traceEnd(TRACE_TAG);
-        }
-    }
-
-    @Override
-    public void notifyWatchersOfChange(int op, int uid) {
-        Trace.traceBegin(TRACE_TAG,
-                "TaggedTracingAppOpsCheckingServiceInterfaceImpl#notifyWatchersOfChange");
-        try {
-            mService.notifyWatchersOfChange(op, uid);
-        } finally {
-            Trace.traceEnd(TRACE_TAG);
-        }
-    }
-
-    @Override
-    public void notifyOpChanged(@NonNull OnOpModeChangedListener changedListener, int op, int uid,
-            @Nullable String packageName) {
-        Trace.traceBegin(TRACE_TAG,
-                "TaggedTracingAppOpsCheckingServiceInterfaceImpl#notifyOpChanged");
-        try {
-            mService.notifyOpChanged(changedListener, op, uid, packageName);
-        } finally {
-            Trace.traceEnd(TRACE_TAG);
-        }
-    }
-
-    @Override
-    public void notifyOpChangedForAllPkgsInUid(int op, int uid, boolean onlyForeground,
-            @Nullable OnOpModeChangedListener callbackToIgnore) {
-        Trace.traceBegin(TRACE_TAG,
-                "TaggedTracingAppOpsCheckingServiceInterfaceImpl#notifyOpChangedForAllPkgsInUid");
-        try {
-            mService.notifyOpChangedForAllPkgsInUid(op, uid, onlyForeground, callbackToIgnore);
-        } finally {
-            Trace.traceEnd(TRACE_TAG);
-        }
-    }
-
-    @Override
-    public SparseBooleanArray evalForegroundUidOps(int uid, SparseBooleanArray foregroundOps) {
-        Trace.traceBegin(TRACE_TAG,
-                "TaggedTracingAppOpsCheckingServiceInterfaceImpl#evalForegroundUidOps");
-        try {
-            return mService.evalForegroundUidOps(uid, foregroundOps);
-        } finally {
-            Trace.traceEnd(TRACE_TAG);
-        }
-    }
-
-    @Override
-    public SparseBooleanArray evalForegroundPackageOps(String packageName,
-            SparseBooleanArray foregroundOps, @UserIdInt int userId) {
-        Trace.traceBegin(TRACE_TAG,
-                "TaggedTracingAppOpsCheckingServiceInterfaceImpl#evalForegroundPackageOps");
-        try {
-            return mService.evalForegroundPackageOps(packageName, foregroundOps, userId);
-        } finally {
-            Trace.traceEnd(TRACE_TAG);
-        }
-    }
-
-    @Override
-    public boolean dumpListeners(int dumpOp, int dumpUid, String dumpPackage,
-            PrintWriter printWriter) {
-        Trace.traceBegin(TRACE_TAG,
-                "TaggedTracingAppOpsCheckingServiceInterfaceImpl#dumpListeners");
-        try {
-            return mService.dumpListeners(dumpOp, dumpUid, dumpPackage, printWriter);
+            return mService.getForegroundOps(packageName, userId);
         } finally {
             Trace.traceEnd(TRACE_TAG);
         }
diff --git a/services/core/java/com/android/server/appop/AppOpsRestrictions.java b/services/core/java/com/android/server/appop/AppOpsRestrictions.java
index f7ccd34..0241d02 100644
--- a/services/core/java/com/android/server/appop/AppOpsRestrictions.java
+++ b/services/core/java/com/android/server/appop/AppOpsRestrictions.java
@@ -144,4 +144,11 @@
      */
     void dumpRestrictions(PrintWriter printWriter, int dumpOp, String dumpPackage,
             boolean showUserRestrictions);
+
+    /**
+     * Listener for when an appop restriction is removed.
+     */
+    interface AppOpsRestrictionRemovedListener {
+        void onAppOpsRestrictionRemoved(int code);
+    }
 }
diff --git a/services/core/java/com/android/server/appop/AppOpsRestrictionsImpl.java b/services/core/java/com/android/server/appop/AppOpsRestrictionsImpl.java
index f51200f2..ae93991 100644
--- a/services/core/java/com/android/server/appop/AppOpsRestrictionsImpl.java
+++ b/services/core/java/com/android/server/appop/AppOpsRestrictionsImpl.java
@@ -42,7 +42,8 @@
 
     private Context mContext;
     private Handler mHandler;
-    private AppOpsCheckingServiceInterface mAppOpsCheckingServiceInterface;
+
+    private AppOpsRestrictionRemovedListener mAppOpsRestrictionRemovedListener;
 
     // Map from (Object token) to (int code) to (boolean restricted)
     private final ArrayMap<Object, SparseBooleanArray> mGlobalRestrictions = new ArrayMap<>();
@@ -56,10 +57,10 @@
             mUserRestrictionExcludedPackageTags = new ArrayMap<>();
 
     public AppOpsRestrictionsImpl(Context context, Handler handler,
-            AppOpsCheckingServiceInterface appOpsCheckingServiceInterface) {
+            AppOpsRestrictionRemovedListener appOpsRestrictionRemovedListener) {
         mContext = context;
         mHandler = handler;
-        mAppOpsCheckingServiceInterface = appOpsCheckingServiceInterface;
+        mAppOpsRestrictionRemovedListener = appOpsRestrictionRemovedListener;
     }
 
     @Override
@@ -211,15 +212,11 @@
         return allRestrictedCodes;
     }
 
-    // TODO: For clearUserRestrictions, we are calling notifyOpChanged from within the
-    //  LegacyAppOpsServiceInterfaceImpl class. But, for all other changes to restrictions, we're
-    //  calling it from within AppOpsService. This is awkward, and we should probably do it one
-    //  way or the other.
     private void notifyAllUserRestrictions(SparseBooleanArray allUserRestrictedCodes) {
         int restrictedCodesSize = allUserRestrictedCodes.size();
         for (int j = 0; j < restrictedCodesSize; j++) {
             int code = allUserRestrictedCodes.keyAt(j);
-            mHandler.post(() -> mAppOpsCheckingServiceInterface.notifyWatchersOfChange(code, UID_ANY));
+            mHandler.post(() -> mAppOpsRestrictionRemovedListener.onAppOpsRestrictionRemoved(code));
         }
     }
 
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index 81ba4b8..0be69ce 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -52,6 +52,7 @@
 import static android.app.AppOpsManager.SAMPLING_STRATEGY_UNIFORM;
 import static android.app.AppOpsManager.SAMPLING_STRATEGY_UNIFORM_OPS;
 import static android.app.AppOpsManager.SECURITY_EXCEPTION_ON_INVALID_ATTRIBUTION_TAG_CHANGE;
+import static android.app.AppOpsManager.WATCH_FOREGROUND_CHANGES;
 import static android.app.AppOpsManager._NUM_OP;
 import static android.app.AppOpsManager.extractFlagsFromKey;
 import static android.app.AppOpsManager.extractUidStateFromKey;
@@ -230,6 +231,15 @@
     private static final int MAX_UNUSED_POOLED_OBJECTS = 3;
     private static final int RARELY_USED_PACKAGES_INITIALIZATION_DELAY_MILLIS = 300000;
 
+    /* Temporary solution before Uidstate class is removed. These uids get their modes set. */
+    private static final int[] NON_PACKAGE_UIDS = new int[]{
+            Process.ROOT_UID,
+            Process.PHONE_UID,
+            Process.BLUETOOTH_UID,
+            Process.NFC_UID,
+            Process.NETWORK_STACK_UID,
+            Process.SHELL_UID};
+
     final Context mContext;
     final AtomicFile mStorageFile;
     final AtomicFile mRecentAccessesFile;
@@ -284,6 +294,11 @@
     private final ArrayMap<Pair<String, Integer>, ArrayList<AsyncNotedAppOp>>
             mUnforwardedAsyncNotedOps = new ArrayMap<>();
 
+    private final SparseArray<ArraySet<OnOpModeChangedListener>> mOpModeWatchers =
+            new SparseArray<>();
+    private final ArrayMap<String, ArraySet<OnOpModeChangedListener>> mPackageModeWatchers =
+            new ArrayMap<>();
+
     boolean mWriteNoteOpsScheduled;
 
     boolean mWriteScheduled;
@@ -307,6 +322,8 @@
     @GuardedBy("this")
     @VisibleForTesting
     final SparseArray<UidState> mUidStates = new SparseArray<>();
+    @GuardedBy("this")
+    private boolean mUidStatesInitialized;
 
     volatile @NonNull HistoricalRegistry mHistoricalRegistry = new HistoricalRegistry(this);
 
@@ -333,8 +350,6 @@
       */
     private final SparseArray<int[]> mSwitchedOps = new SparseArray<>();
 
-    private ActivityManagerInternal mActivityManagerInternal;
-
     /** Package sampled for message collection in the current session */
     @GuardedBy("this")
     private String mSampledPackage = null;
@@ -497,11 +512,6 @@
         @NonNull
         public final ArrayMap<String, Ops> pkgOps = new ArrayMap<>();
 
-        // true indicates there is an interested observer, false there isn't but it has such an op
-        //TODO: Move foregroundOps and hasForegroundWatchers into the AppOpsServiceInterface.
-        public SparseBooleanArray foregroundOps;
-        public boolean hasForegroundWatchers;
-
         public UidState(int uid) {
             this.uid = uid;
         }
@@ -532,25 +542,6 @@
             return getUidStateTracker().evalMode(uid, op, mode);
         }
 
-        public void evalForegroundOps() {
-            foregroundOps = null;
-            foregroundOps = mAppOpsCheckingService.evalForegroundUidOps(uid, foregroundOps);
-            for (int i = pkgOps.size() - 1; i >= 0; i--) {
-                foregroundOps = mAppOpsCheckingService
-                        .evalForegroundPackageOps(pkgOps.valueAt(i).packageName, foregroundOps,
-                                UserHandle.getUserId(uid));
-            }
-            hasForegroundWatchers = false;
-            if (foregroundOps != null) {
-                for (int i = 0;  i < foregroundOps.size(); i++) {
-                    if (foregroundOps.valueAt(i)) {
-                        hasForegroundWatchers = true;
-                        break;
-                    }
-                }
-            }
-        }
-
         @SuppressWarnings("GuardedBy")
         public int getState() {
             return getUidStateTracker().getUidState(uid);
@@ -932,7 +923,8 @@
                         storageFile, this, handler, context,  mSwitchedOps));
         //mAppOpsCheckingService = new AppOpsCheckingServiceLoggingDecorator(
         //        LocalServices.getService(AppOpsCheckingServiceInterface.class));
-        mAppOpsRestrictions = new AppOpsRestrictionsImpl(context, handler, mAppOpsCheckingService);
+        mAppOpsRestrictions = new AppOpsRestrictionsImpl(context, handler,
+                code -> notifyWatchersOfChange(code, UID_ANY));
 
         LockGuard.installLock(this, LockGuard.INDEX_APP_OPS);
         mStorageFile = new AtomicFile(storageFile, "appops_legacy");
@@ -1057,7 +1049,7 @@
                 UidState uidState = mUidStates.valueAt(uidNum);
 
                 String[] pkgsInUid = getPackagesForUid(uidState.uid);
-                if (ArrayUtils.isEmpty(pkgsInUid)) {
+                if (ArrayUtils.isEmpty(pkgsInUid) && uid >= Process.FIRST_APPLICATION_UID) {
                     uidState.clear();
                     mUidStates.removeAt(uidNum);
                     scheduleFastWriteLocked();
@@ -1086,6 +1078,64 @@
             }
         }
 
+        prepareInternalCallbacks();
+
+        final IntentFilter packageSuspendFilter = new IntentFilter();
+        packageSuspendFilter.addAction(Intent.ACTION_PACKAGES_UNSUSPENDED);
+        packageSuspendFilter.addAction(Intent.ACTION_PACKAGES_SUSPENDED);
+        mContext.registerReceiverAsUser(new BroadcastReceiver() {
+            @Override
+            public void onReceive(Context context, Intent intent) {
+                final int[] changedUids = intent.getIntArrayExtra(Intent.EXTRA_CHANGED_UID_LIST);
+                final String[] changedPkgs = intent.getStringArrayExtra(
+                        Intent.EXTRA_CHANGED_PACKAGE_LIST);
+                for (int code : OPS_RESTRICTED_ON_SUSPEND) {
+                    ArraySet<OnOpModeChangedListener> onModeChangedListeners;
+                    synchronized (AppOpsService.this) {
+                        onModeChangedListeners = mOpModeWatchers.get(code);
+                        if (onModeChangedListeners == null) {
+                            continue;
+                        }
+                    }
+                    for (int i = 0; i < changedUids.length; i++) {
+                        final int changedUid = changedUids[i];
+                        final String changedPkg = changedPkgs[i];
+                        // We trust packagemanager to insert matching uid and packageNames in the
+                        // extras
+                        notifyOpChanged(onModeChangedListeners, code, changedUid, changedPkg);
+                    }
+                }
+            }
+        }, UserHandle.ALL, packageSuspendFilter, null, null);
+
+        mHandler.postDelayed(new Runnable() {
+            @Override
+            public void run() {
+                List<String> packageNames = getPackageListAndResample();
+                initializeRarelyUsedPackagesList(new ArraySet<>(packageNames));
+            }
+        }, RARELY_USED_PACKAGES_INITIALIZATION_DELAY_MILLIS);
+
+        getPackageManagerInternal().setExternalSourcesPolicy(
+                new PackageManagerInternal.ExternalSourcesPolicy() {
+                    @Override
+                    public int getPackageTrustedToInstallApps(String packageName, int uid) {
+                        int appOpMode = checkOperation(AppOpsManager.OP_REQUEST_INSTALL_PACKAGES,
+                                uid, packageName);
+                        switch (appOpMode) {
+                            case AppOpsManager.MODE_ALLOWED:
+                                return PackageManagerInternal.ExternalSourcesPolicy.USER_TRUSTED;
+                            case AppOpsManager.MODE_ERRORED:
+                                return PackageManagerInternal.ExternalSourcesPolicy.USER_BLOCKED;
+                            default:
+                                return PackageManagerInternal.ExternalSourcesPolicy.USER_DEFAULT;
+                        }
+                    }
+                });
+    }
+
+    @VisibleForTesting
+    void prepareInternalCallbacks() {
         getUserManagerInternal().addUserLifecycleListener(
                 new UserManagerInternal.UserLifecycleListener() {
                     @Override
@@ -1131,62 +1181,6 @@
                         }
                     }
                 });
-
-        final IntentFilter packageSuspendFilter = new IntentFilter();
-        packageSuspendFilter.addAction(Intent.ACTION_PACKAGES_UNSUSPENDED);
-        packageSuspendFilter.addAction(Intent.ACTION_PACKAGES_SUSPENDED);
-        mContext.registerReceiverAsUser(new BroadcastReceiver() {
-            @Override
-            public void onReceive(Context context, Intent intent) {
-                final int[] changedUids = intent.getIntArrayExtra(Intent.EXTRA_CHANGED_UID_LIST);
-                final String[] changedPkgs = intent.getStringArrayExtra(
-                        Intent.EXTRA_CHANGED_PACKAGE_LIST);
-                for (int code : OPS_RESTRICTED_ON_SUSPEND) {
-                    ArraySet<OnOpModeChangedListener> onModeChangedListeners;
-                    synchronized (AppOpsService.this) {
-                        onModeChangedListeners =
-                                mAppOpsCheckingService.getOpModeChangedListeners(code);
-                        if (onModeChangedListeners == null) {
-                            continue;
-                        }
-                    }
-                    for (int i = 0; i < changedUids.length; i++) {
-                        final int changedUid = changedUids[i];
-                        final String changedPkg = changedPkgs[i];
-                        // We trust packagemanager to insert matching uid and packageNames in the
-                        // extras
-                        notifyOpChanged(onModeChangedListeners, code, changedUid, changedPkg);
-                    }
-                }
-            }
-        }, UserHandle.ALL, packageSuspendFilter, null, null);
-
-        mHandler.postDelayed(new Runnable() {
-            @Override
-            public void run() {
-                List<String> packageNames = getPackageListAndResample();
-                initializeRarelyUsedPackagesList(new ArraySet<>(packageNames));
-            }
-        }, RARELY_USED_PACKAGES_INITIALIZATION_DELAY_MILLIS);
-
-        getPackageManagerInternal().setExternalSourcesPolicy(
-                new PackageManagerInternal.ExternalSourcesPolicy() {
-                    @Override
-                    public int getPackageTrustedToInstallApps(String packageName, int uid) {
-                        int appOpMode = checkOperation(AppOpsManager.OP_REQUEST_INSTALL_PACKAGES,
-                                uid, packageName);
-                        switch (appOpMode) {
-                            case AppOpsManager.MODE_ALLOWED:
-                                return PackageManagerInternal.ExternalSourcesPolicy.USER_TRUSTED;
-                            case AppOpsManager.MODE_ERRORED:
-                                return PackageManagerInternal.ExternalSourcesPolicy.USER_BLOCKED;
-                            default:
-                                return PackageManagerInternal.ExternalSourcesPolicy.USER_DEFAULT;
-                        }
-                    }
-                });
-
-        mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class);
     }
 
     /**
@@ -1205,6 +1199,11 @@
                     initializeUserUidStatesLocked(userId, packageStates);
                 }
             }
+
+            for (int uid : NON_PACKAGE_UIDS) {
+                mUidStates.put(uid, new UidState(uid));
+            }
+            mUidStatesInitialized = true;
         }
     }
 
@@ -1248,8 +1247,6 @@
                 ops.put(code, new Op(uidState, packageName, code, uid));
             }
         }
-
-        uidState.evalForegroundOps();
     }
 
     /**
@@ -1323,14 +1320,42 @@
     // The callback method from AppOpsUidStateTracker
     private void onUidStateChanged(int uid, int state, boolean foregroundModeMayChange) {
         synchronized (this) {
-            UidState uidState = getUidStateLocked(uid, true);
+            UidState uidState = getUidStateLocked(uid, false);
 
-            if (uidState != null && foregroundModeMayChange && uidState.hasForegroundWatchers) {
-                for (int fgi = uidState.foregroundOps.size() - 1; fgi >= 0; fgi--) {
-                    if (!uidState.foregroundOps.valueAt(fgi)) {
+            boolean hasForegroundWatchers = false;
+
+            for (int i = 0; i < mModeWatchers.size(); i++) {
+                ModeCallback cb = mModeWatchers.valueAt(i);
+                if (cb.isWatchingUid(uid) && (cb.getFlags() & WATCH_FOREGROUND_CHANGES) != 0) {
+                    hasForegroundWatchers = true;
+                    break;
+                }
+            }
+
+            if (uidState != null && foregroundModeMayChange && hasForegroundWatchers) {
+
+                SparseBooleanArray foregroundOps = new SparseBooleanArray();
+
+                SparseBooleanArray uidForegroundOps = mAppOpsCheckingService.getForegroundOps(uid);
+                for (int i = 0; i < uidForegroundOps.size(); i++) {
+                    foregroundOps.put(uidForegroundOps.keyAt(i), true);
+                }
+                String[] uidPackageNames = getPackagesForUid(uid);
+
+                int userId = UserHandle.getUserId(uid);
+                for (String packageName : uidPackageNames) {
+                    SparseBooleanArray packageForegroundOps =
+                            mAppOpsCheckingService.getForegroundOps(packageName, userId);
+                    for (int i = 0; i < packageForegroundOps.size(); i++) {
+                        foregroundOps.put(packageForegroundOps.keyAt(i), true);
+                    }
+                }
+
+                for (int fgi = foregroundOps.size() - 1; fgi >= 0; fgi--) {
+                    if (!foregroundOps.valueAt(fgi)) {
                         continue;
                     }
-                    final int code = uidState.foregroundOps.keyAt(fgi);
+                    final int code = foregroundOps.keyAt(fgi);
 
                     if (uidState.getUidMode(code) != AppOpsManager.opToDefaultMode(code)
                             && uidState.getUidMode(code) == AppOpsManager.MODE_FOREGROUND) {
@@ -1339,7 +1364,7 @@
                                 this, code, uidState.uid, true, null));
                     } else if (!uidState.pkgOps.isEmpty()) {
                         final ArraySet<OnOpModeChangedListener> listenerSet =
-                                mAppOpsCheckingService.getOpModeChangedListeners(code);
+                                mOpModeWatchers.get(code);
                         if (listenerSet != null) {
                             for (int cbi = listenerSet.size() - 1; cbi >= 0; cbi--) {
                                 final OnOpModeChangedListener listener = listenerSet.valueAt(cbi);
@@ -1396,12 +1421,6 @@
             @ActivityManager.ProcessCapability int capability) {
         synchronized (this) {
             getUidStateTracker().updateUidProcState(uid, procState, capability);
-            if (!mUidStates.contains(uid)) {
-                UidState uidState = new UidState(uid);
-                mUidStates.put(uid, uidState);
-                onUidStateChanged(uid,
-                        AppOpsUidStateTracker.processStateToUidState(procState), false);
-            }
         }
     }
 
@@ -1536,7 +1555,7 @@
                 return null;
             }
             ArrayList<AppOpsManager.OpEntry> resOps = collectOps(pkgOps, ops);
-            if (resOps == null) {
+            if (resOps == null || resOps.size() == 0) {
                 return null;
             }
             ArrayList<AppOpsManager.PackageOps> res = new ArrayList<AppOpsManager.PackageOps>();
@@ -1793,6 +1812,12 @@
                 if (mode == defaultMode) {
                     return;
                 }
+                if (uid >= Process.FIRST_APPLICATION_UID) {
+                    // TODO change to a throw; no crashing for now.
+                    Slog.e(TAG, "Trying to set mode for unknown uid " + uid + ".");
+                }
+                // I suppose we'll support setting these uids. Shouldn't matter later when UidState
+                // is removed.
                 uidState = new UidState(uid);
                 mUidStates.put(uid, uidState);
             }
@@ -1806,7 +1831,6 @@
             if (!uidState.setUidMode(code, mode)) {
                 return;
             }
-            uidState.evalForegroundOps();
             if (mode != MODE_ERRORED && mode != previousMode) {
                 updateStartedOpModeForUidLocked(code, mode == MODE_IGNORED, uid);
             }
@@ -1825,10 +1849,85 @@
      */
     private void notifyOpChangedForAllPkgsInUid(int code, int uid, boolean onlyForeground,
             @Nullable IAppOpsCallback callbackToIgnore) {
-        ModeCallback listenerToIgnore = callbackToIgnore != null
-                ? mModeWatchers.get(callbackToIgnore.asBinder()) : null;
-        mAppOpsCheckingService.notifyOpChangedForAllPkgsInUid(code, uid, onlyForeground,
-                listenerToIgnore);
+        String[] uidPackageNames = getPackagesForUid(uid);
+        ArrayMap<OnOpModeChangedListener, ArraySet<String>> callbackSpecs = null;
+        synchronized (this) {
+            ArraySet<OnOpModeChangedListener> callbacks = mOpModeWatchers.get(code);
+            if (callbacks != null) {
+                final int callbackCount = callbacks.size();
+                for (int i = 0; i < callbackCount; i++) {
+                    OnOpModeChangedListener callback = callbacks.valueAt(i);
+
+                    if (!callback.isWatchingUid(uid)) {
+                        continue;
+                    }
+
+                    if (onlyForeground && (callback.getFlags()
+                            & WATCH_FOREGROUND_CHANGES) == 0) {
+                        continue;
+                    }
+
+                    ArraySet<String> changedPackages = new ArraySet<>();
+                    Collections.addAll(changedPackages, uidPackageNames);
+                    if (callbackSpecs == null) {
+                        callbackSpecs = new ArrayMap<>();
+                    }
+                    callbackSpecs.put(callback, changedPackages);
+                }
+            }
+
+            for (String uidPackageName : uidPackageNames) {
+                callbacks = mPackageModeWatchers.get(uidPackageName);
+                if (callbacks != null) {
+                    if (callbackSpecs == null) {
+                        callbackSpecs = new ArrayMap<>();
+                    }
+                    final int callbackCount = callbacks.size();
+                    for (int i = 0; i < callbackCount; i++) {
+                        OnOpModeChangedListener callback = callbacks.valueAt(i);
+
+                        if (onlyForeground && (callback.getFlags()
+                                & WATCH_FOREGROUND_CHANGES) == 0) {
+                            continue;
+                        }
+
+                        ArraySet<String> changedPackages = callbackSpecs.get(callback);
+                        if (changedPackages == null) {
+                            changedPackages = new ArraySet<>();
+                            callbackSpecs.put(callback, changedPackages);
+                        }
+                        changedPackages.add(uidPackageName);
+                    }
+                }
+            }
+
+            if (callbackSpecs != null && callbackToIgnore != null) {
+                callbackSpecs.remove(mModeWatchers.get(callbackToIgnore.asBinder()));
+            }
+        }
+
+        if (callbackSpecs == null) {
+            return;
+        }
+
+        for (int i = 0; i < callbackSpecs.size(); i++) {
+            final OnOpModeChangedListener callback = callbackSpecs.keyAt(i);
+            final ArraySet<String> reportedPackageNames = callbackSpecs.valueAt(i);
+            if (reportedPackageNames == null) {
+                mHandler.sendMessage(PooledLambda.obtainMessage(
+                        AppOpsService::notifyOpChanged,
+                        this, callback, code, uid, (String) null));
+
+            } else {
+                final int reportedPackageCount = reportedPackageNames.size();
+                for (int j = 0; j < reportedPackageCount; j++) {
+                    final String reportedPackageName = reportedPackageNames.valueAt(j);
+                    mHandler.sendMessage(PooledLambda.obtainMessage(
+                            AppOpsService::notifyOpChanged,
+                            this, callback, code, uid, reportedPackageName));
+                }
+            }
+        }
     }
 
     private void updatePermissionRevokedCompat(int uid, int switchCode, int mode) {
@@ -1975,19 +2074,15 @@
                 if (op.getMode() != mode) {
                     previousMode = op.getMode();
                     op.setMode(mode);
-
-                    if (uidState != null) {
-                        uidState.evalForegroundOps();
-                    }
                     ArraySet<OnOpModeChangedListener> cbs =
-                            mAppOpsCheckingService.getOpModeChangedListeners(code);
+                            mOpModeWatchers.get(code);
                     if (cbs != null) {
                         if (repCbs == null) {
                             repCbs = new ArraySet<>();
                         }
                         repCbs.addAll(cbs);
                     }
-                    cbs = mAppOpsCheckingService.getPackageModeChangedListeners(packageName);
+                    cbs = mPackageModeWatchers.get(packageName);
                     if (cbs != null) {
                         if (repCbs == null) {
                             repCbs = new ArraySet<>();
@@ -2026,9 +2121,42 @@
         }
     }
 
-    private void notifyOpChanged(OnOpModeChangedListener callback, int code,
+    private void notifyOpChanged(OnOpModeChangedListener onModeChangedListener, int code,
             int uid, String packageName) {
-        mAppOpsCheckingService.notifyOpChanged(callback, code, uid, packageName);
+        Objects.requireNonNull(onModeChangedListener);
+
+        if (uid != UID_ANY && onModeChangedListener.getWatchingUid() >= 0
+                && onModeChangedListener.getWatchingUid() != uid) {
+            return;
+        }
+
+        // See CALL_BACK_ON_CHANGED_LISTENER_WITH_SWITCHED_OP_CHANGE
+        int[] switchedCodes;
+        if (onModeChangedListener.getWatchedOpCode() == ALL_OPS) {
+            switchedCodes = mSwitchedOps.get(code);
+        } else if (onModeChangedListener.getWatchedOpCode() == OP_NONE) {
+            switchedCodes = new int[]{code};
+        } else {
+            switchedCodes = new int[]{onModeChangedListener.getWatchedOpCode()};
+        }
+
+        for (int switchedCode : switchedCodes) {
+            // There are features watching for mode changes such as window manager
+            // and location manager which are in our process. The callbacks in these
+            // features may require permissions our remote caller does not have.
+            final long identity = Binder.clearCallingIdentity();
+            try {
+                if (shouldIgnoreCallback(switchedCode, onModeChangedListener.getCallingPid(),
+                        onModeChangedListener.getCallingUid())) {
+                    continue;
+                }
+                onModeChangedListener.onOpModeChanged(switchedCode, uid, packageName);
+            } catch (RemoteException e) {
+                /* ignore */
+            } finally {
+                Binder.restoreCallingIdentity(identity);
+            }
+        }
     }
 
     private static ArrayList<ChangeRec> addChange(ArrayList<ChangeRec> reports,
@@ -2127,11 +2255,9 @@
                             uidState.setUidMode(code, newMode);
                             for (String packageName : getPackagesForUid(uidState.uid)) {
                                 callbacks = addCallbacks(callbacks, code, uidState.uid, packageName,
-                                        previousMode,
-                                        mAppOpsCheckingService.getOpModeChangedListeners(code));
+                                        previousMode, mOpModeWatchers.get(code));
                                 callbacks = addCallbacks(callbacks, code, uidState.uid, packageName,
-                                        previousMode, mAppOpsCheckingService
-                                                .getPackageModeChangedListeners(packageName));
+                                        previousMode, mPackageModeWatchers.get(packageName));
 
                                 allChanges = addChange(allChanges, code, uidState.uid,
                                         packageName, previousMode);
@@ -2180,11 +2306,9 @@
                             uidChanged = true;
                             final int uid = curOp.uidState.uid;
                             callbacks = addCallbacks(callbacks, curOp.op, uid, packageName,
-                                    previousMode,
-                                    mAppOpsCheckingService.getOpModeChangedListeners(curOp.op));
+                                    previousMode, mOpModeWatchers.get(curOp.op));
                             callbacks = addCallbacks(callbacks, curOp.op, uid, packageName,
-                                    previousMode, mAppOpsCheckingService
-                                            .getPackageModeChangedListeners(packageName));
+                                    previousMode, mPackageModeWatchers.get(packageName));
 
                             allChanges = addChange(allChanges, curOp.op, uid, packageName,
                                     previousMode);
@@ -2200,9 +2324,6 @@
                                 UserHandle.getUserId(uidState.uid));
                     }
                 }
-                if (uidChanged) {
-                    uidState.evalForegroundOps();
-                }
             }
 
             if (changed) {
@@ -2279,15 +2400,6 @@
         dpmi.resetOp(op, packageName, userId);
     }
 
-    private void evalAllForegroundOpsLocked() {
-        for (int uidi = mUidStates.size() - 1; uidi >= 0; uidi--) {
-            final UidState uidState = mUidStates.valueAt(uidi);
-            if (uidState.foregroundOps != null) {
-                uidState.evalForegroundOps();
-            }
-        }
-    }
-
     @Override
     public void startWatchingMode(int op, String packageName, IAppOpsCallback callback) {
         startWatchingModeWithFlags(op, packageName, 0, callback);
@@ -2331,12 +2443,21 @@
                 mModeWatchers.put(callback.asBinder(), cb);
             }
             if (switchOp != AppOpsManager.OP_NONE) {
-                mAppOpsCheckingService.startWatchingOpModeChanged(cb, switchOp);
+                ArraySet<OnOpModeChangedListener> cbs = mOpModeWatchers.get(switchOp);
+                if (cbs == null) {
+                    cbs = new ArraySet<>();
+                    mOpModeWatchers.put(switchOp, cbs);
+                }
+                cbs.add(cb);
             }
             if (mayWatchPackageName) {
-                mAppOpsCheckingService.startWatchingPackageModeChanged(cb, packageName);
+                ArraySet<OnOpModeChangedListener> cbs = mPackageModeWatchers.get(packageName);
+                if (cbs == null) {
+                    cbs = new ArraySet<>();
+                    mPackageModeWatchers.put(packageName, cbs);
+                }
+                cbs.add(cb);
             }
-            evalAllForegroundOpsLocked();
         }
     }
 
@@ -2349,10 +2470,21 @@
             ModeCallback cb = mModeWatchers.remove(callback.asBinder());
             if (cb != null) {
                 cb.unlinkToDeath();
-                mAppOpsCheckingService.removeListener(cb);
+                for (int i = mOpModeWatchers.size() - 1; i >= 0; i--) {
+                    ArraySet<OnOpModeChangedListener> cbs = mOpModeWatchers.valueAt(i);
+                    cbs.remove(cb);
+                    if (cbs.size() <= 0) {
+                        mOpModeWatchers.removeAt(i);
+                    }
+                }
+                for (int i = mPackageModeWatchers.size() - 1; i >= 0; i--) {
+                    ArraySet<OnOpModeChangedListener> cbs = mPackageModeWatchers.valueAt(i);
+                    cbs.remove(cb);
+                    if (cbs.size() <= 0) {
+                        mPackageModeWatchers.removeAt(i);
+                    }
+                }
             }
-
-            evalAllForegroundOpsLocked();
         }
     }
 
@@ -3705,7 +3837,7 @@
     /**
      * Create a restriction description matching the properties of the package.
      *
-     * @param pkg The package to create the restriction description for
+     * @param packageState The package to create the restriction description for
      *
      * @return The restriction matching the package
      */
@@ -3909,7 +4041,7 @@
      */
     private Ops getOpsLocked(int uid, String packageName, @Nullable String attributionTag,
             boolean isAttributionTagValid, @Nullable RestrictionBypass bypass, boolean edit) {
-        UidState uidState = getUidStateLocked(uid, edit);
+        UidState uidState = getUidStateLocked(uid, false);
         if (uidState == null) {
             return null;
         }
@@ -5135,8 +5267,55 @@
                 pw.println();
             }
 
-            if (!dumpHistory) {
-                needSep |= mAppOpsCheckingService.dumpListeners(dumpOp, dumpUid, dumpPackage, pw);
+            if (mOpModeWatchers.size() > 0 && !dumpHistory) {
+                boolean printedHeader = false;
+                for (int i = 0; i < mOpModeWatchers.size(); i++) {
+                    if (dumpOp >= 0 && dumpOp != mOpModeWatchers.keyAt(i)) {
+                        continue;
+                    }
+                    boolean printedOpHeader = false;
+                    ArraySet<OnOpModeChangedListener> callbacks = mOpModeWatchers.valueAt(i);
+                    for (int j = 0; j < callbacks.size(); j++) {
+                        final OnOpModeChangedListener cb = callbacks.valueAt(j);
+                        if (dumpPackage != null
+                                && dumpUid != UserHandle.getAppId(cb.getWatchingUid())) {
+                            continue;
+                        }
+                        needSep = true;
+                        if (!printedHeader) {
+                            pw.println("  Op mode watchers:");
+                            printedHeader = true;
+                        }
+                        if (!printedOpHeader) {
+                            pw.print("    Op ");
+                            pw.print(AppOpsManager.opToName(mOpModeWatchers.keyAt(i)));
+                            pw.println(":");
+                            printedOpHeader = true;
+                        }
+                        pw.print("      #"); pw.print(j); pw.print(": ");
+                        pw.println(cb);
+                    }
+                }
+            }
+            if (mPackageModeWatchers.size() > 0 && dumpOp < 0 && !dumpHistory) {
+                boolean printedHeader = false;
+                for (int i = 0; i < mPackageModeWatchers.size(); i++) {
+                    if (dumpPackage != null && !dumpPackage.equals(mPackageModeWatchers.keyAt(i))) {
+                        continue;
+                    }
+                    needSep = true;
+                    if (!printedHeader) {
+                        pw.println("  Package mode watchers:");
+                        printedHeader = true;
+                    }
+                    pw.print("    Pkg "); pw.print(mPackageModeWatchers.keyAt(i));
+                    pw.println(":");
+                    ArraySet<OnOpModeChangedListener> callbacks = mPackageModeWatchers.valueAt(i);
+                    for (int j = 0; j < callbacks.size(); j++) {
+                        pw.print("      #"); pw.print(j); pw.print(": ");
+                        pw.println(callbacks.valueAt(j));
+                    }
+                }
             }
 
             if (mModeWatchers.size() > 0 && dumpOp < 0 && !dumpHistory) {
@@ -5336,11 +5515,6 @@
                             }
                         }
                     }
-                    if (uidState.foregroundOps != null && !hasOp) {
-                        if (uidState.foregroundOps.indexOfKey(dumpOp) > 0) {
-                            hasOp = true;
-                        }
-                    }
                     if (!hasOp || !hasPackage || !hasMode) {
                         continue;
                     }
@@ -5348,21 +5522,6 @@
 
                 pw.print("  Uid "); UserHandle.formatUid(pw, uidState.uid); pw.println(":");
                 uidState.dump(pw, nowElapsed);
-                if (uidState.foregroundOps != null && (dumpMode < 0
-                        || dumpMode == AppOpsManager.MODE_FOREGROUND)) {
-                    pw.println("    foregroundOps:");
-                    for (int j = 0; j < uidState.foregroundOps.size(); j++) {
-                        if (dumpOp >= 0 && dumpOp != uidState.foregroundOps.keyAt(j)) {
-                            continue;
-                        }
-                        pw.print("      ");
-                        pw.print(AppOpsManager.opToName(uidState.foregroundOps.keyAt(j)));
-                        pw.print(": ");
-                        pw.println(uidState.foregroundOps.valueAt(j) ? "WATCHER" : "SILENT");
-                    }
-                    pw.print("    hasForegroundWatchers=");
-                    pw.println(uidState.hasForegroundWatchers);
-                }
                 needSep = true;
 
                 if (opModes != null) {
@@ -5564,7 +5723,7 @@
     private void notifyWatchersOfChange(int code, int uid) {
         final ArraySet<OnOpModeChangedListener> modeChangedListenerSet;
         synchronized (this) {
-            modeChangedListenerSet = mAppOpsCheckingService.getOpModeChangedListeners(code);
+            modeChangedListenerSet = mOpModeWatchers.get(code);
             if (modeChangedListenerSet == null) {
                 return;
             }
@@ -5651,10 +5810,10 @@
         }
     }
 
+    @android.annotation.EnforcePermission(android.Manifest.permission.MANAGE_APPOPS)
     @Override
     public void resetPackageOpsNoHistory(@NonNull String packageName) {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_APPOPS,
-                "resetPackageOpsNoHistory");
+        resetPackageOpsNoHistory_enforcePermission();
         synchronized (AppOpsService.this) {
             final int uid = mPackageManagerInternal.getPackageUid(packageName, 0,
                     UserHandle.getCallingUserId());
@@ -5673,52 +5832,52 @@
         }
     }
 
+    @android.annotation.EnforcePermission(android.Manifest.permission.MANAGE_APPOPS)
     @Override
     public void setHistoryParameters(@AppOpsManager.HistoricalMode int mode,
             long baseSnapshotInterval, int compressionStep) {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_APPOPS,
-                "setHistoryParameters");
+        setHistoryParameters_enforcePermission();
         // Must not hold the appops lock
         mHistoricalRegistry.setHistoryParameters(mode, baseSnapshotInterval, compressionStep);
     }
 
+    @android.annotation.EnforcePermission(android.Manifest.permission.MANAGE_APPOPS)
     @Override
     public void offsetHistory(long offsetMillis) {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_APPOPS,
-                "offsetHistory");
+        offsetHistory_enforcePermission();
         // Must not hold the appops lock
         mHistoricalRegistry.offsetHistory(offsetMillis);
         mHistoricalRegistry.offsetDiscreteHistory(offsetMillis);
     }
 
+    @android.annotation.EnforcePermission(android.Manifest.permission.MANAGE_APPOPS)
     @Override
     public void addHistoricalOps(HistoricalOps ops) {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_APPOPS,
-                "addHistoricalOps");
+        addHistoricalOps_enforcePermission();
         // Must not hold the appops lock
         mHistoricalRegistry.addHistoricalOps(ops);
     }
 
+    @android.annotation.EnforcePermission(android.Manifest.permission.MANAGE_APPOPS)
     @Override
     public void resetHistoryParameters() {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_APPOPS,
-                "resetHistoryParameters");
+        resetHistoryParameters_enforcePermission();
         // Must not hold the appops lock
         mHistoricalRegistry.resetHistoryParameters();
     }
 
+    @android.annotation.EnforcePermission(android.Manifest.permission.MANAGE_APPOPS)
     @Override
     public void clearHistory() {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_APPOPS,
-                "clearHistory");
+        clearHistory_enforcePermission();
         // Must not hold the appops lock
         mHistoricalRegistry.clearAllHistory();
     }
 
+    @android.annotation.EnforcePermission(android.Manifest.permission.MANAGE_APPOPS)
     @Override
     public void rebootHistory(long offlineDurationMillis) {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_APPOPS,
-                "rebootHistory");
+        rebootHistory_enforcePermission();
 
         Preconditions.checkArgument(offlineDurationMillis >= 0);
 
diff --git a/services/core/java/com/android/server/appop/AppOpsServiceTestingShim.java b/services/core/java/com/android/server/appop/AppOpsServiceTestingShim.java
new file mode 100644
index 0000000..c605375
--- /dev/null
+++ b/services/core/java/com/android/server/appop/AppOpsServiceTestingShim.java
@@ -0,0 +1,204 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.appop;
+
+import android.util.SparseBooleanArray;
+import android.util.SparseIntArray;
+
+import java.util.Objects;
+
+/**
+ * A testing shim, which supports running two variants of an AppOpsServiceInterface at once,
+ * and checking the results of both.
+ */
+public class AppOpsServiceTestingShim implements AppOpsCheckingServiceInterface {
+
+    private AppOpsCheckingServiceInterface mOldImplementation;
+    private AppOpsCheckingServiceInterface mNewImplementation;
+
+    public AppOpsServiceTestingShim(AppOpsCheckingServiceInterface oldValImpl,
+            AppOpsCheckingServiceInterface newImpl) {
+        mOldImplementation = oldValImpl;
+        mNewImplementation = newImpl;
+    }
+
+    private void signalImplDifference(String message) {
+        //TODO b/252886104 implement
+    }
+
+    @Override
+    public void writeState() {
+        mOldImplementation.writeState();
+        mNewImplementation.writeState();
+    }
+
+    @Override
+    public void readState() {
+        mOldImplementation.readState();
+        mNewImplementation.readState();
+    }
+
+    @Override
+    public void shutdown() {
+        mOldImplementation.shutdown();
+        mNewImplementation.shutdown();
+    }
+
+    @Override
+    public void systemReady() {
+        mOldImplementation.systemReady();
+        mNewImplementation.systemReady();
+    }
+
+    @Override
+    public SparseIntArray getNonDefaultUidModes(int uid) {
+        SparseIntArray oldVal = mOldImplementation.getNonDefaultUidModes(uid);
+        SparseIntArray newVal = mNewImplementation.getNonDefaultUidModes(uid);
+
+        if (!Objects.equals(oldVal, newVal)) {
+            signalImplDifference("getNonDefaultUidModes");
+        }
+
+        return newVal;
+    }
+
+    @Override
+    public SparseIntArray getNonDefaultPackageModes(String packageName, int userId) {
+        SparseIntArray oldVal = mOldImplementation.getNonDefaultPackageModes(packageName, userId);
+        SparseIntArray newVal = mNewImplementation.getNonDefaultPackageModes(packageName, userId);
+
+        if (!Objects.equals(oldVal, newVal)) {
+            signalImplDifference("getNonDefaultPackageModes");
+        }
+
+        return newVal;
+    }
+
+    @Override
+    public int getUidMode(int uid, int op) {
+        int oldVal = mOldImplementation.getUidMode(uid, op);
+        int newVal = mNewImplementation.getUidMode(uid, op);
+
+        if (oldVal != newVal) {
+            signalImplDifference("getUidMode");
+        }
+
+        return newVal;
+    }
+
+    @Override
+    public boolean setUidMode(int uid, int op, int mode) {
+        boolean oldVal = mOldImplementation.setUidMode(uid, op, mode);
+        boolean newVal = mNewImplementation.setUidMode(uid, op, mode);
+
+        if (oldVal != newVal) {
+            signalImplDifference("setUidMode");
+        }
+
+        return newVal;
+    }
+
+    @Override
+    public int getPackageMode(String packageName, int op, int userId) {
+        int oldVal = mOldImplementation.getPackageMode(packageName, op, userId);
+        int newVal = mNewImplementation.getPackageMode(packageName, op, userId);
+
+        if (oldVal != newVal) {
+            signalImplDifference("getPackageMode");
+        }
+
+        return newVal;
+    }
+
+    @Override
+    public void setPackageMode(String packageName, int op, int mode, int userId) {
+        mOldImplementation.setPackageMode(packageName, op, mode, userId);
+        mNewImplementation.setPackageMode(packageName, op, mode, userId);
+    }
+
+    @Override
+    public boolean removePackage(String packageName, int userId) {
+        boolean oldVal = mOldImplementation.removePackage(packageName, userId);
+        boolean newVal = mNewImplementation.removePackage(packageName, userId);
+
+        if (oldVal != newVal) {
+            signalImplDifference("removePackage");
+        }
+
+        return newVal;
+    }
+
+    @Override
+    public void removeUid(int uid) {
+        mOldImplementation.removeUid(uid);
+        mNewImplementation.removeUid(uid);
+    }
+
+    @Override
+    public boolean areUidModesDefault(int uid) {
+        boolean oldVal = mOldImplementation.areUidModesDefault(uid);
+        boolean newVal = mNewImplementation.areUidModesDefault(uid);
+
+        if (oldVal != newVal) {
+            signalImplDifference("areUidModesDefault");
+        }
+
+        return newVal;
+    }
+
+    @Override
+    public boolean arePackageModesDefault(String packageName, int userId) {
+        boolean oldVal = mOldImplementation.arePackageModesDefault(packageName, userId);
+        boolean newVal = mNewImplementation.arePackageModesDefault(packageName, userId);
+
+        if (oldVal != newVal) {
+            signalImplDifference("arePackageModesDefault");
+        }
+
+        return newVal;
+    }
+
+    @Override
+    public void clearAllModes() {
+        mOldImplementation.clearAllModes();
+        mNewImplementation.clearAllModes();
+    }
+
+    @Override
+    public SparseBooleanArray getForegroundOps(int uid) {
+        SparseBooleanArray oldVal = mOldImplementation.getForegroundOps(uid);
+        SparseBooleanArray newVal = mNewImplementation.getForegroundOps(uid);
+
+        if (!Objects.equals(oldVal, newVal)) {
+            signalImplDifference("getForegroundOps");
+        }
+
+        return newVal;
+    }
+
+    @Override
+    public SparseBooleanArray getForegroundOps(String packageName, int userId) {
+        SparseBooleanArray oldVal = mOldImplementation.getForegroundOps(packageName, userId);
+        SparseBooleanArray newVal = mNewImplementation.getForegroundOps(packageName, userId);
+
+        if (!Objects.equals(oldVal, newVal)) {
+            signalImplDifference("getForegroundOps");
+        }
+
+        return newVal;
+    }
+}
diff --git a/services/core/java/com/android/server/appop/LegacyAppOpStateParser.java b/services/core/java/com/android/server/appop/LegacyAppOpStateParser.java
new file mode 100644
index 0000000..a6d5050
--- /dev/null
+++ b/services/core/java/com/android/server/appop/LegacyAppOpStateParser.java
@@ -0,0 +1,255 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.appop;
+
+import static android.app.AppOpsManager.opToDefaultMode;
+
+import android.annotation.NonNull;
+import android.app.AppOpsManager;
+import android.os.UserHandle;
+import android.util.ArrayMap;
+import android.util.AtomicFile;
+import android.util.Slog;
+import android.util.SparseArray;
+import android.util.SparseIntArray;
+import android.util.Xml;
+
+import com.android.internal.util.XmlUtils;
+import com.android.modules.utils.TypedXmlPullParser;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+
+class LegacyAppOpStateParser {
+    static final String TAG = LegacyAppOpStateParser.class.getSimpleName();
+
+    private static final int NO_FILE_VERSION = -2;
+    private static final int NO_VERSION = -1;
+
+    /**
+     * Reads legacy app-ops data into given maps.
+     */
+    public int readState(AtomicFile file, SparseArray<SparseIntArray> uidModes,
+            SparseArray<ArrayMap<String, SparseIntArray>> userPackageModes) {
+        FileInputStream stream;
+        try {
+            stream = file.openRead();
+        } catch (FileNotFoundException e) {
+            Slog.i(TAG, "No existing app ops " + file.getBaseFile() + "; starting empty");
+            return NO_FILE_VERSION;
+        }
+
+        try {
+            TypedXmlPullParser parser = Xml.resolvePullParser(stream);
+            int type;
+            while ((type = parser.next()) != XmlPullParser.START_TAG
+                    && type != XmlPullParser.END_DOCUMENT) {
+                // Parse next until we reach the start or end
+            }
+
+            if (type != XmlPullParser.START_TAG) {
+                throw new IllegalStateException("no start tag found");
+            }
+
+            int versionAtBoot = parser.getAttributeInt(null, "v", NO_VERSION);
+
+            int outerDepth = parser.getDepth();
+            while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+                    && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
+                if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
+                    continue;
+                }
+
+                String tagName = parser.getName();
+                if (tagName.equals("pkg")) {
+                    // version 2 has the structure pkg -> uid -> op ->
+                    // in version 3, since pkg and uid states are kept completely
+                    // independent we switch to user -> pkg -> op
+                    readPackage(parser, userPackageModes);
+                } else if (tagName.equals("uid")) {
+                    readUidOps(parser, uidModes);
+                } else if (tagName.equals("user")) {
+                    readUser(parser, userPackageModes);
+                } else {
+                    Slog.w(TAG, "Unknown element under <app-ops>: "
+                            + parser.getName());
+                    XmlUtils.skipCurrentTag(parser);
+                }
+            }
+            return versionAtBoot;
+        } catch (XmlPullParserException e) {
+            throw new RuntimeException(e);
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    private void readPackage(TypedXmlPullParser parser,
+            SparseArray<ArrayMap<String, SparseIntArray>> userPackageModes)
+            throws NumberFormatException, XmlPullParserException, IOException {
+        String pkgName = parser.getAttributeValue(null, "n");
+        int outerDepth = parser.getDepth();
+        int type;
+        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
+            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
+                continue;
+            }
+
+            String tagName = parser.getName();
+            if (tagName.equals("uid")) {
+                readPackageUid(parser, pkgName, userPackageModes);
+            } else {
+                Slog.w(TAG, "Unknown element under <pkg>: "
+                        + parser.getName());
+                XmlUtils.skipCurrentTag(parser);
+            }
+        }
+    }
+
+    private void readPackageUid(TypedXmlPullParser parser, String pkgName,
+            SparseArray<ArrayMap<String, SparseIntArray>> userPackageModes)
+            throws NumberFormatException, XmlPullParserException, IOException {
+        int userId = UserHandle.getUserId(parser.getAttributeInt(null, "n"));
+        int outerDepth = parser.getDepth();
+        int type;
+        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
+            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
+                continue;
+            }
+
+            String tagName = parser.getName();
+            if (tagName.equals("op")) {
+                readOp(parser, userId, pkgName, userPackageModes);
+            } else {
+                Slog.w(TAG, "Unknown element under <pkg>: "
+                        + parser.getName());
+                XmlUtils.skipCurrentTag(parser);
+            }
+        }
+    }
+
+    private void readUidOps(TypedXmlPullParser parser, SparseArray<SparseIntArray> uidModes)
+            throws NumberFormatException,
+            XmlPullParserException, IOException {
+        final int uid = parser.getAttributeInt(null, "n");
+        SparseIntArray modes = uidModes.get(uid);
+        if (modes == null) {
+            modes = new SparseIntArray();
+            uidModes.put(uid, modes);
+        }
+
+        int outerDepth = parser.getDepth();
+        int type;
+        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
+            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
+                continue;
+            }
+
+            String tagName = parser.getName();
+            if (tagName.equals("op")) {
+                final int code = parser.getAttributeInt(null, "n");
+                final int mode = parser.getAttributeInt(null, "m");
+
+                if (mode != opToDefaultMode(code)) {
+                    modes.put(code, mode);
+                }
+            } else {
+                Slog.w(TAG, "Unknown element under <uid>: "
+                        + parser.getName());
+                XmlUtils.skipCurrentTag(parser);
+            }
+        }
+    }
+
+    private void readUser(TypedXmlPullParser parser,
+            SparseArray<ArrayMap<String, SparseIntArray>> userPackageModes)
+            throws NumberFormatException, XmlPullParserException, IOException {
+        int userId = parser.getAttributeInt(null, "n");
+        int outerDepth = parser.getDepth();
+        int type;
+        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
+            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
+                continue;
+            }
+
+            String tagName = parser.getName();
+            if (tagName.equals("pkg")) {
+                readPackageOp(parser, userId, userPackageModes);
+            } else {
+                Slog.w(TAG, "Unknown element under <user>: "
+                        + parser.getName());
+                XmlUtils.skipCurrentTag(parser);
+            }
+        }
+    }
+
+    // read package tag refactored in Android U
+    private void readPackageOp(TypedXmlPullParser parser, int userId,
+            SparseArray<ArrayMap<String, SparseIntArray>> userPackageModes)
+            throws NumberFormatException, XmlPullParserException, IOException {
+        String pkgName = parser.getAttributeValue(null, "n");
+        int outerDepth = parser.getDepth();
+        int type;
+        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
+            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
+                continue;
+            }
+
+            String tagName = parser.getName();
+            if (tagName.equals("op")) {
+                readOp(parser, userId, pkgName, userPackageModes);
+            } else {
+                Slog.w(TAG, "Unknown element under <pkg>: "
+                        + parser.getName());
+                XmlUtils.skipCurrentTag(parser);
+            }
+        }
+    }
+
+    private void readOp(TypedXmlPullParser parser, int userId, @NonNull String pkgName,
+            SparseArray<ArrayMap<String, SparseIntArray>> userPackageModes)
+            throws NumberFormatException, XmlPullParserException {
+        final int opCode = parser.getAttributeInt(null, "n");
+        final int defaultMode = AppOpsManager.opToDefaultMode(opCode);
+        final int mode = parser.getAttributeInt(null, "m", defaultMode);
+
+        if (mode != defaultMode) {
+            ArrayMap<String, SparseIntArray> packageModes = userPackageModes.get(userId);
+            if (packageModes == null) {
+                packageModes = new ArrayMap<>();
+                userPackageModes.put(userId, packageModes);
+            }
+
+            SparseIntArray modes = packageModes.get(pkgName);
+            if (modes == null) {
+                modes = new SparseIntArray();
+                packageModes.put(pkgName, modes);
+            }
+
+            modes.put(opCode, mode);
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/attention/AttentionManagerService.java b/services/core/java/com/android/server/attention/AttentionManagerService.java
index 658e38b..5edbaa9 100644
--- a/services/core/java/com/android/server/attention/AttentionManagerService.java
+++ b/services/core/java/com/android/server/attention/AttentionManagerService.java
@@ -96,12 +96,15 @@
     @VisibleForTesting
     static final String KEY_SERVICE_ENABLED = "service_enabled";
 
-    /** Default value in absence of {@link DeviceConfig} override. */
+    /** Default service enabled value in absence of {@link DeviceConfig} override. */
     private static final boolean DEFAULT_SERVICE_ENABLED = true;
 
     @VisibleForTesting
     boolean mIsServiceEnabled;
 
+    @VisibleForTesting
+    boolean mIsProximityEnabled;
+
     /**
      * DeviceConfig flag name, describes how much time we consider a result fresh; if the check
      * attention called within that period - cached value will be returned.
@@ -180,6 +183,9 @@
             DeviceConfig.addOnPropertiesChangedListener(NAMESPACE_ATTENTION_MANAGER_SERVICE,
                     ActivityThread.currentApplication().getMainExecutor(),
                     (properties) -> onDeviceConfigChange(properties.getKeyset()));
+            mIsProximityEnabled = mContext.getResources()
+                    .getBoolean(com.android.internal.R.bool.config_enableProximityService);
+            Slog.i(LOG_TAG, "mIsProximityEnabled is: " + mIsProximityEnabled);
         }
     }
 
@@ -351,7 +357,7 @@
     @VisibleForTesting
     boolean onStartProximityUpdates(ProximityUpdateCallbackInternal callbackInternal) {
         Objects.requireNonNull(callbackInternal);
-        if (!mIsServiceEnabled) {
+        if (!mIsProximityEnabled) {
             Slog.w(LOG_TAG, "Trying to call onProximityUpdate() on an unsupported device.");
             return false;
         }
@@ -488,6 +494,7 @@
     private void dumpInternal(IndentingPrintWriter ipw) {
         ipw.println("Attention Manager Service (dumpsys attention) state:\n");
         ipw.println("isServiceEnabled=" + mIsServiceEnabled);
+        ipw.println("mIsProximityEnabled=" + mIsProximityEnabled);
         ipw.println("mStaleAfterMillis=" + mStaleAfterMillis);
         ipw.println("AttentionServicePackageName=" + getServiceConfigPackage(mContext));
         ipw.println("Resolved component:");
@@ -519,6 +526,11 @@
         }
 
         @Override
+        public boolean isProximitySupported() {
+            return AttentionManagerService.this.mIsProximityEnabled;
+        }
+
+        @Override
         public boolean checkAttention(long timeout, AttentionCallbackInternal callbackInternal) {
             return AttentionManagerService.this.checkAttention(timeout, callbackInternal);
         }
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index d43687b..ae8ddeb 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -2486,13 +2486,11 @@
         return true;
     }
 
+    @android.annotation.EnforcePermission(android.Manifest.permission.WRITE_SETTINGS)
     /** @see AudioManager#setEncodedSurroundMode(int) */
     @Override
     public boolean setEncodedSurroundMode(@AudioManager.EncodedSurroundOutputMode int mode) {
-        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.WRITE_SETTINGS)
-                != PackageManager.PERMISSION_GRANTED) {
-            throw new SecurityException("Missing WRITE_SETTINGS permission");
-        }
+        setEncodedSurroundMode_enforcePermission();
 
         final long token = Binder.clearCallingIdentity();
         try {
@@ -7504,15 +7502,13 @@
     public @interface BtProfile {}
 
 
+    @android.annotation.EnforcePermission(android.Manifest.permission.BLUETOOTH_STACK)
     /**
      * See AudioManager.handleBluetoothActiveDeviceChanged(...)
      */
     public void handleBluetoothActiveDeviceChanged(BluetoothDevice newDevice,
             BluetoothDevice previousDevice, @NonNull BluetoothProfileConnectionInfo info) {
-        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.BLUETOOTH_STACK)
-                != PackageManager.PERMISSION_GRANTED) {
-            throw new SecurityException("Bluetooth is the only caller allowed");
-        }
+        handleBluetoothActiveDeviceChanged_enforcePermission();
         if (info == null) {
             throw new IllegalArgumentException("Illegal null BluetoothProfileConnectionInfo for"
                     + " device " + previousDevice + " -> " + newDevice);
@@ -10475,9 +10471,10 @@
         }
     }
 
+    @android.annotation.EnforcePermission(android.Manifest.permission.REMOTE_AUDIO_PLAYBACK)
     @Override
     public void setRingtonePlayer(IRingtonePlayer player) {
-        mContext.enforceCallingOrSelfPermission(REMOTE_AUDIO_PLAYBACK, null);
+        setRingtonePlayer_enforcePermission();
         mRingtonePlayer = player;
     }
 
diff --git a/services/core/java/com/android/server/clipboard/ClipboardService.java b/services/core/java/com/android/server/clipboard/ClipboardService.java
index fab138b..85b4f75 100644
--- a/services/core/java/com/android/server/clipboard/ClipboardService.java
+++ b/services/core/java/com/android/server/clipboard/ClipboardService.java
@@ -470,6 +470,7 @@
                     callingPackage);
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.SET_CLIP_SOURCE)
         @Override
         public void setPrimaryClipAsPackage(
                 ClipData clip,
@@ -478,8 +479,7 @@
                 @UserIdInt int userId,
                 int deviceId,
                 String sourcePackage) {
-            getContext().enforceCallingOrSelfPermission(Manifest.permission.SET_CLIP_SOURCE,
-                    "Requires SET_CLIP_SOURCE permission");
+            setPrimaryClipAsPackage_enforcePermission();
             checkAndSetPrimaryClip(clip, callingPackage, attributionTag, userId, deviceId,
                     sourcePackage);
         }
@@ -765,11 +765,11 @@
             }
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.SET_CLIP_SOURCE)
         @Override
         public String getPrimaryClipSource(
                 String callingPackage, String attributionTag, int userId, int deviceId) {
-            getContext().enforceCallingOrSelfPermission(Manifest.permission.SET_CLIP_SOURCE,
-                    "Requires SET_CLIP_SOURCE permission");
+            getPrimaryClipSource_enforcePermission();
             final int intendingUid = getIntendingUid(callingPackage, userId);
             final int intendingUserId = UserHandle.getUserId(intendingUid);
             final int intendingDeviceId = getIntendingDeviceId(deviceId, intendingUid);
diff --git a/services/core/java/com/android/server/content/ContentService.java b/services/core/java/com/android/server/content/ContentService.java
index 781920c..1b48e3c 100644
--- a/services/core/java/com/android/server/content/ContentService.java
+++ b/services/core/java/com/android/server/content/ContentService.java
@@ -1150,10 +1150,10 @@
         }
     }
 
+    @android.annotation.EnforcePermission(android.Manifest.permission.READ_SYNC_STATS)
     @Override
     public boolean isSyncActive(Account account, String authority, ComponentName cname) {
-        mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_STATS,
-                "no permission to read the sync stats");
+        isSyncActive_enforcePermission();
 
         final int callingUid = Binder.getCallingUid();
         final int userId = UserHandle.getCallingUserId();
@@ -1254,11 +1254,11 @@
         return isSyncPendingAsUser(account, authority, cname, UserHandle.getCallingUserId());
     }
 
+    @android.annotation.EnforcePermission(android.Manifest.permission.READ_SYNC_STATS)
     @Override
     public boolean isSyncPendingAsUser(Account account, String authority, ComponentName cname,
                                        int userId) {
-        mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_STATS,
-                "no permission to read the sync stats");
+        isSyncPendingAsUser_enforcePermission();
         enforceCrossUserPermission(userId,
                 "no permission to retrieve the sync settings for user " + userId);
 
diff --git a/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java b/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java
index 9645690..8f9a1fd 100644
--- a/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java
+++ b/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java
@@ -1185,12 +1185,11 @@
             }
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.CONTROL_DEVICE_STATE)
         @Override // Binder call
         public void onStateRequestOverlayDismissed(boolean shouldCancelRequest) {
 
-            getContext().enforceCallingOrSelfPermission(CONTROL_DEVICE_STATE,
-                    "CONTROL_DEVICE_STATE permission required to control the state request "
-                            + "overlay");
+            onStateRequestOverlayDismissed_enforcePermission();
 
             final long callingIdentity = Binder.clearCallingIdentity();
             try {
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index c3a4c2e..0c67ac4 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -3441,10 +3441,10 @@
             }
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.CONFIGURE_WIFI_DISPLAY)
         @Override // Binder call
         public void startWifiDisplayScan() {
-            mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
-                    "Permission required to start wifi display scans");
+            startWifiDisplayScan_enforcePermission();
 
             final int callingPid = Binder.getCallingPid();
             final long token = Binder.clearCallingIdentity();
@@ -3455,10 +3455,10 @@
             }
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.CONFIGURE_WIFI_DISPLAY)
         @Override // Binder call
         public void stopWifiDisplayScan() {
-            mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
-                    "Permission required to stop wifi display scans");
+            stopWifiDisplayScan_enforcePermission();
 
             final int callingPid = Binder.getCallingPid();
             final long token = Binder.clearCallingIdentity();
@@ -3532,10 +3532,10 @@
             }
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.CONFIGURE_WIFI_DISPLAY)
         @Override // Binder call
         public void pauseWifiDisplay() {
-            mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
-                    "Permission required to pause a wifi display session");
+            pauseWifiDisplay_enforcePermission();
 
             final long token = Binder.clearCallingIdentity();
             try {
@@ -3545,10 +3545,10 @@
             }
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.CONFIGURE_WIFI_DISPLAY)
         @Override // Binder call
         public void resumeWifiDisplay() {
-            mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
-                    "Permission required to resume a wifi display session");
+            resumeWifiDisplay_enforcePermission();
 
             final long token = Binder.clearCallingIdentity();
             try {
@@ -3571,11 +3571,10 @@
             }
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
         @Override // Binder call
         public void setUserDisabledHdrTypes(int[] userDisabledFormats) {
-            mContext.enforceCallingOrSelfPermission(
-                    Manifest.permission.WRITE_SECURE_SETTINGS,
-                    "Permission required to write the user settings.");
+            setUserDisabledHdrTypes_enforcePermission();
 
             final long token = Binder.clearCallingIdentity();
             try {
@@ -3598,11 +3597,10 @@
             DisplayControl.overrideHdrTypes(displayToken, modes);
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
         @Override // Binder call
         public void setAreUserDisabledHdrTypesAllowed(boolean areUserDisabledHdrTypesAllowed) {
-            mContext.enforceCallingOrSelfPermission(
-                    Manifest.permission.WRITE_SECURE_SETTINGS,
-                    "Permission required to write the user settings.");
+            setAreUserDisabledHdrTypesAllowed_enforcePermission();
             final long token = Binder.clearCallingIdentity();
             try {
                 setAreUserDisabledHdrTypesAllowedInternal(areUserDisabledHdrTypesAllowed);
@@ -3625,11 +3623,10 @@
             }
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.CONFIGURE_DISPLAY_COLOR_MODE)
         @Override // Binder call
         public void requestColorMode(int displayId, int colorMode) {
-            mContext.enforceCallingOrSelfPermission(
-                    Manifest.permission.CONFIGURE_DISPLAY_COLOR_MODE,
-                    "Permission required to change the display color mode");
+            requestColorMode_enforcePermission();
             final long token = Binder.clearCallingIdentity();
             try {
                 requestColorModeInternal(displayId, colorMode);
@@ -3706,11 +3703,10 @@
             }
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.BRIGHTNESS_SLIDER_USAGE)
         @Override // Binder call
         public ParceledListSlice<BrightnessChangeEvent> getBrightnessEvents(String callingPackage) {
-            mContext.enforceCallingOrSelfPermission(
-                    Manifest.permission.BRIGHTNESS_SLIDER_USAGE,
-                    "Permission to read brightness events.");
+            getBrightnessEvents_enforcePermission();
 
             final int callingUid = Binder.getCallingUid();
             AppOpsManager appOpsManager = mContext.getSystemService(AppOpsManager.class);
@@ -3739,11 +3735,10 @@
             }
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.ACCESS_AMBIENT_LIGHT_STATS)
         @Override // Binder call
         public ParceledListSlice<AmbientBrightnessDayStats> getAmbientBrightnessStats() {
-            mContext.enforceCallingOrSelfPermission(
-                    Manifest.permission.ACCESS_AMBIENT_LIGHT_STATS,
-                    "Permission required to to access ambient light stats.");
+            getAmbientBrightnessStats_enforcePermission();
             final int callingUid = Binder.getCallingUid();
             final int userId = UserHandle.getUserId(callingUid);
             final long token = Binder.clearCallingIdentity();
@@ -3757,12 +3752,11 @@
             }
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.CONFIGURE_DISPLAY_BRIGHTNESS)
         @Override // Binder call
         public void setBrightnessConfigurationForUser(
                 BrightnessConfiguration c, @UserIdInt int userId, String packageName) {
-            mContext.enforceCallingOrSelfPermission(
-                    Manifest.permission.CONFIGURE_DISPLAY_BRIGHTNESS,
-                    "Permission required to change the display's brightness configuration");
+            setBrightnessConfigurationForUser_enforcePermission();
             if (userId != UserHandle.getCallingUserId()) {
                 mContext.enforceCallingOrSelfPermission(
                         Manifest.permission.INTERACT_ACROSS_USERS,
@@ -3787,12 +3781,11 @@
             }
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.CONFIGURE_DISPLAY_BRIGHTNESS)
         @Override // Binder call
         public void setBrightnessConfigurationForDisplay(BrightnessConfiguration c,
                 String uniqueId, int userId, String packageName) {
-            mContext.enforceCallingOrSelfPermission(
-                    Manifest.permission.CONFIGURE_DISPLAY_BRIGHTNESS,
-                    "Permission required to change the display's brightness configuration");
+            setBrightnessConfigurationForDisplay_enforcePermission();
             if (userId != UserHandle.getCallingUserId()) {
                 mContext.enforceCallingOrSelfPermission(
                         Manifest.permission.INTERACT_ACROSS_USERS,
@@ -3807,12 +3800,11 @@
             }
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.CONFIGURE_DISPLAY_BRIGHTNESS)
         @Override // Binder call
         public BrightnessConfiguration getBrightnessConfigurationForDisplay(String uniqueId,
                 int userId) {
-            mContext.enforceCallingOrSelfPermission(
-                    Manifest.permission.CONFIGURE_DISPLAY_BRIGHTNESS,
-                    "Permission required to read the display's brightness configuration");
+            getBrightnessConfigurationForDisplay_enforcePermission();
             if (userId != UserHandle.getCallingUserId()) {
                 mContext.enforceCallingOrSelfPermission(
                         Manifest.permission.INTERACT_ACROSS_USERS,
@@ -3856,11 +3848,10 @@
 
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.CONFIGURE_DISPLAY_BRIGHTNESS)
         @Override // Binder call
         public BrightnessConfiguration getDefaultBrightnessConfiguration() {
-            mContext.enforceCallingOrSelfPermission(
-                    Manifest.permission.CONFIGURE_DISPLAY_BRIGHTNESS,
-                    "Permission required to read the display's default brightness configuration");
+            getDefaultBrightnessConfiguration_enforcePermission();
             final long token = Binder.clearCallingIdentity();
             try {
                 synchronized (mSyncRoot) {
@@ -3872,11 +3863,10 @@
             }
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.CONTROL_DISPLAY_BRIGHTNESS)
         @Override
         public BrightnessInfo getBrightnessInfo(int displayId) {
-            mContext.enforceCallingOrSelfPermission(
-                    Manifest.permission.CONTROL_DISPLAY_BRIGHTNESS,
-                    "Permission required to read the display's brightness info.");
+            getBrightnessInfo_enforcePermission();
             final long token = Binder.clearCallingIdentity();
             try {
                 synchronized (mSyncRoot) {
@@ -3904,11 +3894,10 @@
             }
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.CONTROL_DISPLAY_BRIGHTNESS)
         @Override // Binder call
         public void setTemporaryBrightness(int displayId, float brightness) {
-            mContext.enforceCallingOrSelfPermission(
-                    Manifest.permission.CONTROL_DISPLAY_BRIGHTNESS,
-                    "Permission required to set the display's brightness");
+            setTemporaryBrightness_enforcePermission();
             final long token = Binder.clearCallingIdentity();
             try {
                 synchronized (mSyncRoot) {
@@ -3920,11 +3909,10 @@
             }
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.CONTROL_DISPLAY_BRIGHTNESS)
         @Override // Binder call
         public void setBrightness(int displayId, float brightness) {
-            mContext.enforceCallingOrSelfPermission(
-                    Manifest.permission.CONTROL_DISPLAY_BRIGHTNESS,
-                    "Permission required to set the display's brightness");
+            setBrightness_enforcePermission();
             if (!isValidBrightness(brightness)) {
                 Slog.w(TAG, "Attempted to set invalid brightness" + brightness);
                 return;
@@ -3963,11 +3951,10 @@
             return brightness;
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.CONTROL_DISPLAY_BRIGHTNESS)
         @Override // Binder call
         public void setTemporaryAutoBrightnessAdjustment(float adjustment) {
-            mContext.enforceCallingOrSelfPermission(
-                    Manifest.permission.CONTROL_DISPLAY_BRIGHTNESS,
-                    "Permission required to set the display's auto brightness adjustment");
+            setTemporaryAutoBrightnessAdjustment_enforcePermission();
             final long token = Binder.clearCallingIdentity();
             try {
                 synchronized (mSyncRoot) {
@@ -4007,11 +3994,10 @@
             }
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.MODIFY_USER_PREFERRED_DISPLAY_MODE)
         @Override // Binder call
         public void setUserPreferredDisplayMode(int displayId, Display.Mode mode) {
-            mContext.enforceCallingOrSelfPermission(
-                    Manifest.permission.MODIFY_USER_PREFERRED_DISPLAY_MODE,
-                    "Permission required to set the user preferred display mode.");
+            setUserPreferredDisplayMode_enforcePermission();
             final long token = Binder.clearCallingIdentity();
             try {
                 setUserPreferredDisplayModeInternal(displayId, mode);
@@ -4096,11 +4082,10 @@
             }
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.OVERRIDE_DISPLAY_MODE_REQUESTS)
         @Override // Binder call
         public void setShouldAlwaysRespectAppRequestedMode(boolean enabled) {
-            mContext.enforceCallingOrSelfPermission(
-                    Manifest.permission.OVERRIDE_DISPLAY_MODE_REQUESTS,
-                    "Permission required to override display mode requests.");
+            setShouldAlwaysRespectAppRequestedMode_enforcePermission();
             final long token = Binder.clearCallingIdentity();
             try {
                 setShouldAlwaysRespectAppRequestedModeInternal(enabled);
@@ -4109,11 +4094,10 @@
             }
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.OVERRIDE_DISPLAY_MODE_REQUESTS)
         @Override // Binder call
         public boolean shouldAlwaysRespectAppRequestedMode() {
-            mContext.enforceCallingOrSelfPermission(
-                    Manifest.permission.OVERRIDE_DISPLAY_MODE_REQUESTS,
-                    "Permission required to override display mode requests.");
+            shouldAlwaysRespectAppRequestedMode_enforcePermission();
             final long token = Binder.clearCallingIdentity();
             try {
                 return shouldAlwaysRespectAppRequestedModeInternal();
@@ -4122,11 +4106,10 @@
             }
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.MODIFY_REFRESH_RATE_SWITCHING_TYPE)
         @Override // Binder call
         public void setRefreshRateSwitchingType(int newValue) {
-            mContext.enforceCallingOrSelfPermission(
-                    Manifest.permission.MODIFY_REFRESH_RATE_SWITCHING_TYPE,
-                    "Permission required to modify refresh rate switching type.");
+            setRefreshRateSwitchingType_enforcePermission();
             final long token = Binder.clearCallingIdentity();
             try {
                 setRefreshRateSwitchingTypeInternal(newValue);
diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
index 79984c9..5e36eff 100644
--- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
@@ -70,7 +70,7 @@
 
     private static final String UNIQUE_ID_PREFIX = "local:";
 
-    private static final String PROPERTY_EMULATOR_CIRCULAR = "ro.emulator.circular";
+    private static final String PROPERTY_EMULATOR_CIRCULAR = "ro.boot.emulator.circular";
 
     private final LongSparseArray<LocalDisplayDevice> mDevices = new LongSparseArray<>();
 
diff --git a/services/core/java/com/android/server/display/TEST_MAPPING b/services/core/java/com/android/server/display/TEST_MAPPING
index c4a566f..57c2e01 100644
--- a/services/core/java/com/android/server/display/TEST_MAPPING
+++ b/services/core/java/com/android/server/display/TEST_MAPPING
@@ -16,20 +16,6 @@
                 {"exclude-annotation": "androidx.test.filters.FlakyTest"},
                 {"exclude-annotation": "org.junit.Ignore"}
             ]
-        },
-        {
-            "name": "CtsMediaProjectionTestCases",
-            "options": [
-                {
-                    "exclude-annotation": "android.platform.test.annotations.FlakyTest"
-                },
-                {
-                    "exclude-annotation": "androidx.test.filters.FlakyTest"
-                },
-                {
-                    "exclude-annotation": "org.junit.Ignore"
-                }
-            ]
         }
     ]
 }
\ No newline at end of file
diff --git a/services/core/java/com/android/server/display/color/ColorDisplayService.java b/services/core/java/com/android/server/display/color/ColorDisplayService.java
index 0284d9c..a1a10eb 100644
--- a/services/core/java/com/android/server/display/color/ColorDisplayService.java
+++ b/services/core/java/com/android/server/display/color/ColorDisplayService.java
@@ -1621,11 +1621,10 @@
     @VisibleForTesting
     final class BinderService extends IColorDisplayManager.Stub {
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS)
         @Override
         public void setColorMode(int colorMode) {
-            getContext().enforceCallingOrSelfPermission(
-                    Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS,
-                    "Permission required to set display color mode");
+            setColorMode_enforcePermission();
             final long token = Binder.clearCallingIdentity();
             try {
                 setColorModeInternal(colorMode);
@@ -1715,11 +1714,10 @@
             }
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS)
         @Override
         public boolean setNightDisplayActivated(boolean activated) {
-            getContext().enforceCallingOrSelfPermission(
-                    Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS,
-                    "Permission required to set night display activated");
+            setNightDisplayActivated_enforcePermission();
             final long token = Binder.clearCallingIdentity();
             try {
                 mNightDisplayTintController.setActivated(activated);
@@ -1739,11 +1737,10 @@
             }
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS)
         @Override
         public boolean setNightDisplayColorTemperature(int temperature) {
-            getContext().enforceCallingOrSelfPermission(
-                    Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS,
-                    "Permission required to set night display temperature");
+            setNightDisplayColorTemperature_enforcePermission();
             final long token = Binder.clearCallingIdentity();
             try {
                 return mNightDisplayTintController.setColorTemperature(temperature);
@@ -1762,11 +1759,10 @@
             }
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS)
         @Override
         public boolean setNightDisplayAutoMode(int autoMode) {
-            getContext().enforceCallingOrSelfPermission(
-                    Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS,
-                    "Permission required to set night display auto mode");
+            setNightDisplayAutoMode_enforcePermission();
             final long token = Binder.clearCallingIdentity();
             try {
                 return setNightDisplayAutoModeInternal(autoMode);
@@ -1775,11 +1771,10 @@
             }
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS)
         @Override
         public int getNightDisplayAutoMode() {
-            getContext().enforceCallingOrSelfPermission(
-                    Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS,
-                    "Permission required to get night display auto mode");
+            getNightDisplayAutoMode_enforcePermission();
             final long token = Binder.clearCallingIdentity();
             try {
                 return getNightDisplayAutoModeInternal();
@@ -1798,11 +1793,10 @@
             }
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS)
         @Override
         public boolean setNightDisplayCustomStartTime(Time startTime) {
-            getContext().enforceCallingOrSelfPermission(
-                    Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS,
-                    "Permission required to set night display custom start time");
+            setNightDisplayCustomStartTime_enforcePermission();
             final long token = Binder.clearCallingIdentity();
             try {
                 return setNightDisplayCustomStartTimeInternal(startTime);
@@ -1821,11 +1815,10 @@
             }
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS)
         @Override
         public boolean setNightDisplayCustomEndTime(Time endTime) {
-            getContext().enforceCallingOrSelfPermission(
-                    Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS,
-                    "Permission required to set night display custom end time");
+            setNightDisplayCustomEndTime_enforcePermission();
             final long token = Binder.clearCallingIdentity();
             try {
                 return setNightDisplayCustomEndTimeInternal(endTime);
@@ -1844,11 +1837,10 @@
             }
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS)
         @Override
         public boolean setDisplayWhiteBalanceEnabled(boolean enabled) {
-            getContext().enforceCallingOrSelfPermission(
-                    Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS,
-                    "Permission required to set night display activated");
+            setDisplayWhiteBalanceEnabled_enforcePermission();
             final long token = Binder.clearCallingIdentity();
             try {
                 return setDisplayWhiteBalanceSettingEnabled(enabled);
@@ -1877,11 +1869,10 @@
             }
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS)
         @Override
         public boolean setReduceBrightColorsActivated(boolean activated) {
-            getContext().enforceCallingOrSelfPermission(
-                    Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS,
-                    "Permission required to set reduce bright colors activation state");
+            setReduceBrightColorsActivated_enforcePermission();
             final long token = Binder.clearCallingIdentity();
             try {
                 return setReduceBrightColorsActivatedInternal(activated);
@@ -1910,11 +1901,10 @@
             }
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS)
         @Override
         public boolean setReduceBrightColorsStrength(int strength) {
-            getContext().enforceCallingOrSelfPermission(
-                    Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS,
-                    "Permission required to set reduce bright colors strength");
+            setReduceBrightColorsStrength_enforcePermission();
             final long token = Binder.clearCallingIdentity();
             try {
                 return setReduceBrightColorsStrengthInternal(strength);
diff --git a/services/core/java/com/android/server/location/LocationManagerService.java b/services/core/java/com/android/server/location/LocationManagerService.java
index 115421d..efa80b7 100644
--- a/services/core/java/com/android/server/location/LocationManagerService.java
+++ b/services/core/java/com/android/server/location/LocationManagerService.java
@@ -297,6 +297,8 @@
                 refreshAppOpsRestrictions(userId);
             }
         });
+        mInjector.getEmergencyHelper().addOnEmergencyStateChangedListener(
+                this::onEmergencyStateChanged);
 
         // set up passive provider first since it will be required for all other location providers,
         // which are loaded later once the system is ready.
@@ -568,6 +570,11 @@
         refreshAppOpsRestrictions(userId);
     }
 
+    private void onEmergencyStateChanged() {
+        boolean isInEmergency = mInjector.getEmergencyHelper().isInEmergency(Long.MIN_VALUE);
+        mInjector.getLocationUsageLogger().logEmergencyStateChanged(isInEmergency);
+    }
+
     private void logLocationEnabledState() {
         boolean locationEnabled = false;
         // Location setting is considered on if it is enabled for any one user
@@ -598,10 +605,11 @@
         return mGnssManagerService == null ? 0 : mGnssManagerService.getGnssBatchSize();
     }
 
+    @android.annotation.EnforcePermission(android.Manifest.permission.LOCATION_HARDWARE)
     @Override
     public void startGnssBatch(long periodNanos, ILocationListener listener, String packageName,
             @Nullable String attributionTag, String listenerId) {
-        mContext.enforceCallingOrSelfPermission(Manifest.permission.LOCATION_HARDWARE, null);
+        startGnssBatch_enforcePermission();
 
         if (mGnssManagerService == null) {
             return;
@@ -627,9 +635,10 @@
         }
     }
 
+    @android.annotation.EnforcePermission(android.Manifest.permission.LOCATION_HARDWARE)
     @Override
     public void flushGnssBatch() {
-        mContext.enforceCallingOrSelfPermission(Manifest.permission.LOCATION_HARDWARE, null);
+        flushGnssBatch_enforcePermission();
 
         if (mGnssManagerService == null) {
             return;
@@ -642,9 +651,10 @@
         }
     }
 
+    @android.annotation.EnforcePermission(android.Manifest.permission.LOCATION_HARDWARE)
     @Override
     public void stopGnssBatch() {
-        mContext.enforceCallingOrSelfPermission(Manifest.permission.LOCATION_HARDWARE, null);
+        stopGnssBatch_enforcePermission();
 
         if (mGnssManagerService == null) {
             return;
@@ -1110,10 +1120,11 @@
         }
     }
 
+    @android.annotation.EnforcePermission(android.Manifest.permission.INTERACT_ACROSS_USERS)
     @Override
     @RequiresPermission(INTERACT_ACROSS_USERS)
     public void addProviderRequestListener(IProviderRequestListener listener) {
-        mContext.enforceCallingOrSelfPermission(INTERACT_ACROSS_USERS, null);
+        addProviderRequestListener_enforcePermission();
         for (LocationProviderManager manager : mProviderManagers) {
             if (manager.isVisibleToCaller()) {
                 manager.addProviderRequestListener(listener);
@@ -1194,10 +1205,11 @@
         return manager.getProperties();
     }
 
+    @android.annotation.EnforcePermission(android.Manifest.permission.READ_DEVICE_CONFIG)
     @Override
     public boolean isProviderPackage(@Nullable String provider, String packageName,
             @Nullable String attributionTag) {
-        mContext.enforceCallingOrSelfPermission(permission.READ_DEVICE_CONFIG, null);
+        isProviderPackage_enforcePermission();
 
         for (LocationProviderManager manager : mProviderManagers) {
             if (provider != null && !provider.equals(manager.getName())) {
@@ -1216,9 +1228,10 @@
         return false;
     }
 
+    @android.annotation.EnforcePermission(android.Manifest.permission.READ_DEVICE_CONFIG)
     @Override
     public List<String> getProviderPackages(String provider) {
-        mContext.enforceCallingOrSelfPermission(permission.READ_DEVICE_CONFIG, null);
+        getProviderPackages_enforcePermission();
 
         LocationProviderManager manager = getLocationProviderManager(provider);
         if (manager == null) {
diff --git a/services/core/java/com/android/server/location/gnss/NetworkTimeHelper.java b/services/core/java/com/android/server/location/gnss/NetworkTimeHelper.java
index f5114b7..01c108b 100644
--- a/services/core/java/com/android/server/location/gnss/NetworkTimeHelper.java
+++ b/services/core/java/com/android/server/location/gnss/NetworkTimeHelper.java
@@ -37,7 +37,7 @@
      * a platform bug. This switch will be removed in a future release. If there are problems with
      * the new impl we'd like to hear about them.
      */
-    static final boolean USE_TIME_DETECTOR_IMPL = false;
+    static final boolean USE_TIME_DETECTOR_IMPL = true;
 
     /**
      * The callback interface used by {@link NetworkTimeHelper} to report the time to {@link
diff --git a/services/core/java/com/android/server/location/injector/EmergencyHelper.java b/services/core/java/com/android/server/location/injector/EmergencyHelper.java
index be4bf50..10cf714 100644
--- a/services/core/java/com/android/server/location/injector/EmergencyHelper.java
+++ b/services/core/java/com/android/server/location/injector/EmergencyHelper.java
@@ -16,14 +16,55 @@
 
 package com.android.server.location.injector;
 
+import java.util.concurrent.CopyOnWriteArrayList;
+
 /**
  * Provides helpers for emergency sessions.
  */
 public abstract class EmergencyHelper {
 
+    private final CopyOnWriteArrayList<EmergencyStateChangedListener> mListeners;
+
+    protected EmergencyHelper() {
+        mListeners = new CopyOnWriteArrayList<>();
+    }
+
+    /**
+     * Listener for emergency state changes.
+     */
+    public interface EmergencyStateChangedListener {
+        /**
+         * Called when state changes.
+         */
+        void onStateChanged();
+    }
+
     /**
      * Returns true if the device is in an emergency session, or if an emergency session ended
      * within the given extension time.
      */
     public abstract boolean isInEmergency(long extensionTimeMs);
+
+    /**
+     * Add a listener for changes to the emergency location state.
+     */
+    public void addOnEmergencyStateChangedListener(EmergencyStateChangedListener listener) {
+        mListeners.add(listener);
+    }
+
+    /**
+     * Remove a listener for changes to the emergency location state.
+     */
+    public void removeOnEmergencyStateChangedListener(EmergencyStateChangedListener listener) {
+        mListeners.remove(listener);
+    }
+
+    /**
+     * Notify listeners for emergency state of state change
+     */
+    protected final void dispatchEmergencyStateChanged() {
+        for (EmergencyStateChangedListener listener : mListeners) {
+            listener.onStateChanged();
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/location/injector/Injector.java b/services/core/java/com/android/server/location/injector/Injector.java
index b2c8672..4a0c4b2 100644
--- a/services/core/java/com/android/server/location/injector/Injector.java
+++ b/services/core/java/com/android/server/location/injector/Injector.java
@@ -16,13 +16,11 @@
 
 package com.android.server.location.injector;
 
-import com.android.internal.annotations.VisibleForTesting;
 import com.android.server.location.settings.LocationSettings;
 
 /**
  * Injects various location dependencies so that they may be controlled by tests.
  */
-@VisibleForTesting
 public interface Injector {
 
     /** Returns a UserInfoHelper. */
diff --git a/services/core/java/com/android/server/location/injector/LocationUsageLogger.java b/services/core/java/com/android/server/location/injector/LocationUsageLogger.java
index a9701b3..9319e89 100644
--- a/services/core/java/com/android/server/location/injector/LocationUsageLogger.java
+++ b/services/core/java/com/android/server/location/injector/LocationUsageLogger.java
@@ -129,6 +129,13 @@
         FrameworkStatsLog.write(FrameworkStatsLog.LOCATION_ENABLED_STATE_CHANGED, enabled);
     }
 
+    /**
+     * Log emergency location state change event
+     */
+    public synchronized void logEmergencyStateChanged(boolean isInEmergency) {
+        FrameworkStatsLog.write(FrameworkStatsLog.EMERGENCY_STATE_CHANGED, isInEmergency);
+    }
+
     private static int bucketizeProvider(String provider) {
         if (LocationManager.NETWORK_PROVIDER.equals(provider)) {
             return LocationStatsEnums.PROVIDER_NETWORK;
diff --git a/services/core/java/com/android/server/location/injector/SystemEmergencyHelper.java b/services/core/java/com/android/server/location/injector/SystemEmergencyHelper.java
index 1fb00ef..c772e08 100644
--- a/services/core/java/com/android/server/location/injector/SystemEmergencyHelper.java
+++ b/services/core/java/com/android/server/location/injector/SystemEmergencyHelper.java
@@ -27,6 +27,7 @@
 import android.telephony.TelephonyManager;
 import android.util.Log;
 
+import com.android.internal.telephony.TelephonyIntents;
 import com.android.server.FgThread;
 
 import java.util.Objects;
@@ -73,12 +74,25 @@
                     try {
                         mIsInEmergencyCall = mTelephonyManager.isEmergencyNumber(
                                 intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER));
+                        dispatchEmergencyStateChanged();
                     } catch (IllegalStateException e) {
                         Log.w(TAG, "Failed to call TelephonyManager.isEmergencyNumber().", e);
                     }
                 }
             }
         }, new IntentFilter(Intent.ACTION_NEW_OUTGOING_CALL));
+
+        mContext.registerReceiver(new BroadcastReceiver() {
+            @Override
+            public void onReceive(Context context, Intent intent) {
+                if (!TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED.equals(
+                        intent.getAction())) {
+                    return;
+                }
+
+                dispatchEmergencyStateChanged();
+            }
+        }, new IntentFilter(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED));
     }
 
     @Override
@@ -108,6 +122,7 @@
                     if (mIsInEmergencyCall) {
                         mEmergencyCallEndRealtimeMs = SystemClock.elapsedRealtime();
                         mIsInEmergencyCall = false;
+                        dispatchEmergencyStateChanged();
                     }
                 }
             }
diff --git a/services/core/java/com/android/server/location/provider/LocationProviderManager.java b/services/core/java/com/android/server/location/provider/LocationProviderManager.java
index 925ab65..a5a1351 100644
--- a/services/core/java/com/android/server/location/provider/LocationProviderManager.java
+++ b/services/core/java/com/android/server/location/provider/LocationProviderManager.java
@@ -64,6 +64,7 @@
 import android.location.LocationManagerInternal.ProviderEnabledListener;
 import android.location.LocationRequest;
 import android.location.LocationResult;
+import android.location.altitude.AltitudeConverter;
 import android.location.provider.IProviderRequestListener;
 import android.location.provider.ProviderProperties;
 import android.location.provider.ProviderRequest;
@@ -81,6 +82,7 @@
 import android.os.SystemClock;
 import android.os.UserHandle;
 import android.os.WorkSource;
+import android.provider.DeviceConfig;
 import android.stats.location.LocationStatsEnums;
 import android.text.TextUtils;
 import android.util.ArraySet;
@@ -94,6 +96,7 @@
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.util.Preconditions;
 import com.android.server.FgThread;
+import com.android.server.IoThread;
 import com.android.server.LocalServices;
 import com.android.server.location.LocationPermissions;
 import com.android.server.location.LocationPermissions.PermissionLevel;
@@ -122,6 +125,7 @@
 import com.android.server.location.settings.LocationUserSettings;
 
 import java.io.FileDescriptor;
+import java.io.IOException;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
@@ -1441,6 +1445,10 @@
     @GuardedBy("mMultiplexerLock")
     @Nullable private StateChangedListener mStateChangedListener;
 
+    /** Enables missing MSL altitudes to be added on behalf of the provider. */
+    private final AltitudeConverter mAltitudeConverter = new AltitudeConverter();
+    private volatile boolean mIsAltitudeConverterIdle = true;
+
     public LocationProviderManager(Context context, Injector injector,
             String name, @Nullable PassiveLocationProviderManager passiveManager) {
         this(context, injector, name, passiveManager, Collections.emptyList());
@@ -2512,33 +2520,18 @@
     @GuardedBy("mMultiplexerLock")
     @Override
     public void onReportLocation(LocationResult locationResult) {
-        LocationResult filtered;
+        LocationResult processed;
         if (mPassiveManager != null) {
-            filtered = locationResult.filter(location -> {
-                if (!location.isMock()) {
-                    if (location.getLatitude() == 0 && location.getLongitude() == 0) {
-                        Log.e(TAG, "blocking 0,0 location from " + mName + " provider");
-                        return false;
-                    }
-                }
-
-                if (!location.isComplete()) {
-                    Log.e(TAG, "blocking incomplete location from " + mName + " provider");
-                    return false;
-                }
-
-                return true;
-            });
-
-            if (filtered == null) {
+            processed = processReportedLocation(locationResult);
+            if (processed == null) {
                 return;
             }
 
             // don't log location received for passive provider because it's spammy
-            EVENT_LOG.logProviderReceivedLocations(mName, filtered.size());
+            EVENT_LOG.logProviderReceivedLocations(mName, processed.size());
         } else {
-            // passive provider should get already filtered results as input
-            filtered = locationResult;
+            // passive provider should get already processed results as input
+            processed = locationResult;
         }
 
         // check for non-monotonic locations if we're not the passive manager. the passive manager
@@ -2554,20 +2547,78 @@
         }
 
         // update last location
-        setLastLocation(filtered.getLastLocation(), UserHandle.USER_ALL);
+        setLastLocation(processed.getLastLocation(), UserHandle.USER_ALL);
 
         // attempt listener delivery
         deliverToListeners(registration -> {
-            return registration.acceptLocationChange(filtered);
+            return registration.acceptLocationChange(processed);
         });
 
         // notify passive provider
         if (mPassiveManager != null) {
-            mPassiveManager.updateLocation(filtered);
+            mPassiveManager.updateLocation(processed);
         }
     }
 
     @GuardedBy("mMultiplexerLock")
+    @Nullable
+    private LocationResult processReportedLocation(LocationResult locationResult) {
+        LocationResult processed = locationResult.filter(location -> {
+            if (!location.isMock()) {
+                if (location.getLatitude() == 0 && location.getLongitude() == 0) {
+                    Log.e(TAG, "blocking 0,0 location from " + mName + " provider");
+                    return false;
+                }
+            }
+
+            if (!location.isComplete()) {
+                Log.e(TAG, "blocking incomplete location from " + mName + " provider");
+                return false;
+            }
+
+            return true;
+        });
+        if (processed == null) {
+            return null;
+        }
+
+        // Attempt to add a missing MSL altitude on behalf of the provider.
+        if (DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_LOCATION,
+                "enable_location_provider_manager_msl", true)) {
+            return processed.map(location -> {
+                if (!location.hasMslAltitude() && location.hasAltitude()) {
+                    try {
+                        Location locationCopy = new Location(location);
+                        if (mAltitudeConverter.addMslAltitudeToLocation(locationCopy)) {
+                            return locationCopy;
+                        }
+                        // Only queue up one IO thread runnable.
+                        if (mIsAltitudeConverterIdle) {
+                            mIsAltitudeConverterIdle = false;
+                            IoThread.getExecutor().execute(() -> {
+                                try {
+                                    // Results added to the location copy are essentially discarded.
+                                    // We only rely on the side effect of loading altitude assets
+                                    // into the converter's memory cache.
+                                    mAltitudeConverter.addMslAltitudeToLocation(mContext,
+                                            locationCopy);
+                                } catch (IOException e) {
+                                    Log.e(TAG, "not loading MSL altitude assets: " + e);
+                                }
+                                mIsAltitudeConverterIdle = true;
+                            });
+                        }
+                    } catch (IllegalArgumentException e) {
+                        Log.e(TAG, "not adding MSL altitude to location: " + e);
+                    }
+                }
+                return location;
+            });
+        }
+        return processed;
+    }
+
+    @GuardedBy("mMultiplexerLock")
     private void onUserStarted(int userId) {
         if (userId == UserHandle.USER_NULL) {
             return;
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index 0da94ff6..6264851 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -2171,17 +2171,6 @@
                 // credential has matched
                 mBiometricDeferredQueue.addPendingLockoutResetForUser(userId,
                         authResult.syntheticPassword.deriveGkPassword());
-
-                // perform verifyChallenge with synthetic password which generates the real GK auth
-                // token and response for the current user
-                response = mSpManager.verifyChallenge(getGateKeeperService(),
-                        authResult.syntheticPassword, 0L /* challenge */, userId);
-                if (response.getResponseCode() != VerifyCredentialResponse.RESPONSE_OK) {
-                    // This shouldn't really happen: the unwrapping of SP succeeds, but SP doesn't
-                    // match the recorded GK password handle.
-                    Slog.wtf(TAG, "verifyChallenge with SP failed.");
-                    return VerifyCredentialResponse.ERROR;
-                }
             }
         }
         if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) {
@@ -2803,7 +2792,7 @@
      *
      * Also maintains the invariants described in {@link SyntheticPasswordManager} by
      * setting/clearing the protection (by the SP) on the user's auth-bound Keystore keys when the
-     * LSKF is added/removed, respectively.  If the new LSKF is nonempty, then the Gatekeeper auth
+     * LSKF is added/removed, respectively.  If an LSKF is being added, then the Gatekeeper auth
      * token is also refreshed.
      */
     @GuardedBy("mSpManager")
@@ -2820,9 +2809,7 @@
             // not needed by synchronizeUnifiedWorkChallengeForProfiles()
             profilePasswords = null;
 
-            if (mSpManager.hasSidForUser(userId)) {
-                mSpManager.verifyChallenge(getGateKeeperService(), sp, 0L, userId);
-            } else {
+            if (!mSpManager.hasSidForUser(userId)) {
                 mSpManager.newSidForUser(getGateKeeperService(), sp, userId);
                 mSpManager.verifyChallenge(getGateKeeperService(), sp, 0L, userId);
                 setKeystorePassword(sp.deriveKeyStorePassword(), userId);
diff --git a/services/core/java/com/android/server/media/MediaFeatureFlagManager.java b/services/core/java/com/android/server/media/MediaFeatureFlagManager.java
index 70ee38f..f555505 100644
--- a/services/core/java/com/android/server/media/MediaFeatureFlagManager.java
+++ b/services/core/java/com/android/server/media/MediaFeatureFlagManager.java
@@ -17,6 +17,8 @@
 package com.android.server.media;
 
 import android.annotation.StringDef;
+import android.app.ActivityThread;
+import android.app.Application;
 import android.provider.DeviceConfig;
 
 import java.lang.annotation.ElementType;
@@ -31,10 +33,13 @@
      */
     private static final String NAMESPACE_MEDIA_BETTER_TOGETHER = "media_better_together";
 
-    @StringDef(prefix = "FEATURE_", value = {
-            FEATURE_AUDIO_STRATEGIES_IS_USING_LEGACY_CONTROLLER
-    })
-    @Target({ ElementType.TYPE_USE, ElementType.TYPE_PARAMETER })
+    @StringDef(
+            prefix = "FEATURE_",
+            value = {
+                FEATURE_AUDIO_STRATEGIES_IS_USING_LEGACY_CONTROLLER,
+                FEATURE_SCANNING_MINIMUM_PACKAGE_IMPORTANCE
+            })
+    @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})
     @Retention(RetentionPolicy.SOURCE)
     /* package */ @interface MediaFeatureFlag {}
 
@@ -46,6 +51,13 @@
             FEATURE_AUDIO_STRATEGIES_IS_USING_LEGACY_CONTROLLER =
             "BluetoothRouteController__enable_legacy_bluetooth_routes_controller";
 
+    /**
+     * Whether to use IMPORTANCE_FOREGROUND (i.e. 100) or IMPORTANCE_FOREGROUND_SERVICE (i.e. 125)
+     * as the minimum package importance for scanning.
+     */
+    /* package */ static final @MediaFeatureFlag String
+            FEATURE_SCANNING_MINIMUM_PACKAGE_IMPORTANCE = "scanning_package_minimum_importance";
+
     private static final MediaFeatureFlagManager sInstance = new MediaFeatureFlagManager();
 
     private MediaFeatureFlagManager() {
@@ -63,4 +75,29 @@
     public boolean getBoolean(@MediaFeatureFlag String key, boolean defaultValue) {
         return DeviceConfig.getBoolean(NAMESPACE_MEDIA_BETTER_TOGETHER, key, defaultValue);
     }
+
+    /**
+     * Returns an int value from {@link DeviceConfig} from the system_time namespace, or {@code
+     * defaultValue} if there is no explicit value set.
+     */
+    public int getInt(@MediaFeatureFlag String key, int defaultValue) {
+        return DeviceConfig.getInt(NAMESPACE_MEDIA_BETTER_TOGETHER, key, defaultValue);
+    }
+
+    /**
+     * Adds a listener to react for changes in media feature flags values. Future calls to this
+     * method with the same listener will replace the old namespace and executor.
+     *
+     * @param onPropertiesChangedListener The listener to add.
+     */
+    public void addOnPropertiesChangedListener(
+            DeviceConfig.OnPropertiesChangedListener onPropertiesChangedListener) {
+        Application currentApplication = ActivityThread.currentApplication();
+        if (currentApplication != null) {
+            DeviceConfig.addOnPropertiesChangedListener(
+                    NAMESPACE_MEDIA_BETTER_TOGETHER,
+                    currentApplication.getMainExecutor(),
+                    onPropertiesChangedListener);
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
index 3c97aaf8..087c5bb 100644
--- a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
+++ b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
@@ -24,12 +24,12 @@
 import static android.media.MediaRouter2Utils.getProviderId;
 
 import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;
+import static com.android.server.media.MediaFeatureFlagManager.FEATURE_SCANNING_MINIMUM_PACKAGE_IMPORTANCE;
 
 import android.Manifest;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.ActivityManager;
-import android.app.ActivityThread;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.Context;
@@ -92,15 +92,11 @@
     //       in MediaRouter2, remove this constant and replace the usages with the real request IDs.
     private static final long DUMMY_REQUEST_ID = -1;
 
-    private static final String MEDIA_BETTER_TOGETHER_NAMESPACE = "media_better_together";
-
-    private static final String KEY_SCANNING_PACKAGE_MINIMUM_IMPORTANCE =
-            "scanning_package_minimum_importance";
-
-    private static int sPackageImportanceForScanning = DeviceConfig.getInt(
-            MEDIA_BETTER_TOGETHER_NAMESPACE,
-            /* name */ KEY_SCANNING_PACKAGE_MINIMUM_IMPORTANCE,
-            /* defaultValue */ IMPORTANCE_FOREGROUND_SERVICE);
+    private static int sPackageImportanceForScanning =
+            MediaFeatureFlagManager.getInstance()
+                    .getInt(
+                            FEATURE_SCANNING_MINIMUM_PACKAGE_IMPORTANCE,
+                            IMPORTANCE_FOREGROUND_SERVICE);
 
     private final Context mContext;
     private final UserManagerInternal mUserManagerInternal;
@@ -156,9 +152,8 @@
 
         mContext.registerReceiver(mScreenOnOffReceiver, screenOnOffIntentFilter);
 
-        DeviceConfig.addOnPropertiesChangedListener(MEDIA_BETTER_TOGETHER_NAMESPACE,
-                ActivityThread.currentApplication().getMainExecutor(),
-                this::onDeviceConfigChange);
+        MediaFeatureFlagManager.getInstance()
+                .addOnPropertiesChangedListener(this::onDeviceConfigChange);
     }
 
     // Start of methods that implement MediaRouter2 operations.
@@ -1002,9 +997,11 @@
             return;
         }
 
-        Slog.i(TAG, TextUtils.formatSimple(
-                "setSessionVolumeWithRouter2 | router: %d, session: %s, volume: %d",
-                routerRecord.mRouterId,  uniqueSessionId, volume));
+        Slog.i(
+                TAG,
+                TextUtils.formatSimple(
+                        "setSessionVolumeWithRouter2 | router: %d, session: %s, volume: %d",
+                        routerRecord.mRouterId, uniqueSessionId, volume));
 
         routerRecord.mUserRecord.mHandler.sendMessage(
                 obtainMessage(UserHandler::setSessionVolumeOnHandler,
@@ -1021,9 +1018,11 @@
             return;
         }
 
-        Slog.i(TAG, TextUtils.formatSimple(
-                "releaseSessionWithRouter2 | router: %d, session: %s",
-                routerRecord.mRouterId,  uniqueSessionId));
+        Slog.i(
+                TAG,
+                TextUtils.formatSimple(
+                        "releaseSessionWithRouter2 | router: %d, session: %s",
+                        routerRecord.mRouterId, uniqueSessionId));
 
         routerRecord.mUserRecord.mHandler.sendMessage(
                 obtainMessage(UserHandler::releaseSessionOnHandler,
@@ -1100,8 +1099,11 @@
             // TODO: UserRecord <-> routerRecord, why do they reference each other?
             // How about removing mUserRecord from routerRecord?
             routerRecord.mUserRecord.mHandler.sendMessage(
-                    obtainMessage(UserHandler::notifyDiscoveryPreferenceChangedToManager,
-                        routerRecord.mUserRecord.mHandler, routerRecord, manager));
+                    obtainMessage(
+                            UserHandler::notifyDiscoveryPreferenceChangedToManager,
+                            routerRecord.mUserRecord.mHandler,
+                            routerRecord,
+                            manager));
         }
 
         userRecord.mHandler.sendMessage(
@@ -1381,9 +1383,10 @@
     // End of locked methods that are used by both MediaRouter2 and MediaRouter2Manager.
 
     private void onDeviceConfigChange(@NonNull DeviceConfig.Properties properties) {
-        sPackageImportanceForScanning = properties.getInt(
-                /* name */ KEY_SCANNING_PACKAGE_MINIMUM_IMPORTANCE,
-                /* defaultValue */ IMPORTANCE_FOREGROUND_SERVICE);
+        sPackageImportanceForScanning =
+                properties.getInt(
+                        /* name */ FEATURE_SCANNING_MINIMUM_PACKAGE_IMPORTANCE,
+                        /* defaultValue */ IMPORTANCE_FOREGROUND_SERVICE);
     }
 
     static long toUniqueRequestId(int requesterId, int originalRequestId) {
@@ -1734,10 +1737,10 @@
             }
             boolean isUidRelevant;
             synchronized (service.mLock) {
-                isUidRelevant = mUserRecord.mRouterRecords.stream().anyMatch(
-                        router -> router.mUid == uid)
-                        | mUserRecord.mManagerRecords.stream().anyMatch(
-                            manager -> manager.mUid == uid);
+                isUidRelevant =
+                        mUserRecord.mRouterRecords.stream().anyMatch(router -> router.mUid == uid)
+                                | mUserRecord.mManagerRecords.stream()
+                                        .anyMatch(manager -> manager.mUid == uid);
             }
             if (isUidRelevant) {
                 sendMessage(PooledLambda.obtainMessage(
@@ -2400,7 +2403,7 @@
         private static void notifyRoutesUpdatedToRouterRecords(
                 @NonNull List<RouterRecord> routerRecords,
                 @NonNull List<MediaRoute2Info> routes) {
-            for (RouterRecord routerRecord: routerRecords) {
+            for (RouterRecord routerRecord : routerRecords) {
                 List<MediaRoute2Info> filteredRoutes = getFilteredRoutesForPackageName(routes,
                         routerRecord.mPackageName);
                 try {
@@ -2412,15 +2415,15 @@
         }
 
         /**
-         * Filters list of routes to return only public routes or routes provided by
-         * the same package name or routes containing this package name in its allow list.
+         * Filters list of routes to return only public routes or routes provided by the same
+         * package name or routes containing this package name in its allow list.
+         *
          * @param routes initial list of routes to be filtered.
          * @param packageName router's package name to filter routes for it.
          * @return only the routes that this package name is allowed to see.
          */
         private static List<MediaRoute2Info> getFilteredRoutesForPackageName(
-                @NonNull List<MediaRoute2Info> routes,
-                @NonNull String packageName) {
+                @NonNull List<MediaRoute2Info> routes, @NonNull String packageName) {
             List<MediaRoute2Info> filteredRoutes = new ArrayList<>();
             for (MediaRoute2Info route : routes) {
                 if (route.isVisibleTo(packageName)) {
@@ -2609,11 +2612,15 @@
                             .map(record -> record.mDiscoveryPreference)
                             .collect(Collectors.toList());
                 } else {
-                    discoveryPreferences = routerRecords.stream().filter(record ->
-                            service.mActivityManager.getPackageImportance(record.mPackageName)
-                                    <= sPackageImportanceForScanning)
-                            .map(record -> record.mDiscoveryPreference)
-                            .collect(Collectors.toList());
+                    discoveryPreferences =
+                            routerRecords.stream()
+                                    .filter(
+                                            record ->
+                                                    service.mActivityManager.getPackageImportance(
+                                                                    record.mPackageName)
+                                                            <= sPackageImportanceForScanning)
+                                    .map(record -> record.mDiscoveryPreference)
+                                    .collect(Collectors.toList());
                 }
             }
 
@@ -2658,6 +2665,7 @@
             return null;
         }
     }
+
     static final class SessionCreationRequest {
         public final RouterRecord mRouterRecord;
         public final long mUniqueRequestId;
diff --git a/services/core/java/com/android/server/media/projection/TEST_MAPPING b/services/core/java/com/android/server/media/projection/TEST_MAPPING
index 4324930..a792498 100644
--- a/services/core/java/com/android/server/media/projection/TEST_MAPPING
+++ b/services/core/java/com/android/server/media/projection/TEST_MAPPING
@@ -13,20 +13,6 @@
           "exclude-annotation": "org.junit.Ignore"
         }
       ]
-    },
-    {
-      "name": "CtsMediaProjectionTestCases",
-      "options": [
-        {
-          "exclude-annotation": "android.platform.test.annotations.FlakyTest"
-        },
-        {
-          "exclude-annotation": "androidx.test.filters.FlakyTest"
-        },
-        {
-          "exclude-annotation": "org.junit.Ignore"
-        }
-      ]
     }
   ]
 }
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 9ec9ff5..8d47645 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -4279,6 +4279,7 @@
             return getActiveNotificationsWithAttribution(callingPkg, null);
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.ACCESS_NOTIFICATIONS)
         /**
          * System-only API for getting a list of current (i.e. not cleared) notifications.
          *
@@ -4289,9 +4290,7 @@
         public StatusBarNotification[] getActiveNotificationsWithAttribution(String callingPkg,
                 String callingAttributionTag) {
             // enforce() will ensure the calling uid has the correct permission
-            getContext().enforceCallingOrSelfPermission(
-                    android.Manifest.permission.ACCESS_NOTIFICATIONS,
-                    "NotificationManagerService.getActiveNotifications");
+            getActiveNotificationsWithAttribution_enforcePermission();
 
             ArrayList<StatusBarNotification> tmp = new ArrayList<>();
             int uid = Binder.getCallingUid();
@@ -4407,6 +4406,7 @@
                     includeSnoozed);
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.ACCESS_NOTIFICATIONS)
         /**
          * System-only API for getting a list of recent (cleared, no longer shown) notifications.
          */
@@ -4415,9 +4415,7 @@
         public StatusBarNotification[] getHistoricalNotificationsWithAttribution(String callingPkg,
                 String callingAttributionTag, int count, boolean includeSnoozed) {
             // enforce() will ensure the calling uid has the correct permission
-            getContext().enforceCallingOrSelfPermission(
-                    android.Manifest.permission.ACCESS_NOTIFICATIONS,
-                    "NotificationManagerService.getHistoricalNotifications");
+            getHistoricalNotificationsWithAttribution_enforcePermission();
 
             StatusBarNotification[] tmp = null;
             int uid = Binder.getCallingUid();
@@ -4433,6 +4431,7 @@
             return tmp;
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.ACCESS_NOTIFICATIONS)
         /**
          * System-only API for getting a list of historical notifications. May contain multiple days
          * of notifications.
@@ -4443,9 +4442,7 @@
         public NotificationHistory getNotificationHistory(String callingPkg,
                 String callingAttributionTag) {
             // enforce() will ensure the calling uid has the correct permission
-            getContext().enforceCallingOrSelfPermission(
-                    android.Manifest.permission.ACCESS_NOTIFICATIONS,
-                    "NotificationManagerService.getNotificationHistory");
+            getNotificationHistory_enforcePermission();
             int uid = Binder.getCallingUid();
 
             // noteOp will check to make sure the callingPkg matches the uid
diff --git a/services/core/java/com/android/server/pm/AppsFilterLocked.java b/services/core/java/com/android/server/pm/AppsFilterLocked.java
index 29bb14e..e29f2b9 100644
--- a/services/core/java/com/android/server/pm/AppsFilterLocked.java
+++ b/services/core/java/com/android/server/pm/AppsFilterLocked.java
@@ -28,21 +28,28 @@
     /**
      * The following locks guard the accesses for the list/set class members
      */
-    protected final Object mForceQueryableLock = new Object();
-    protected final Object mQueriesViaPackageLock = new Object();
-    protected final Object mQueriesViaComponentLock = new Object();
+    protected final PackageManagerTracedLock mForceQueryableLock =
+            new PackageManagerTracedLock();
+    protected final PackageManagerTracedLock mQueriesViaPackageLock =
+            new PackageManagerTracedLock();
+    protected final PackageManagerTracedLock mQueriesViaComponentLock =
+            new PackageManagerTracedLock();
     /**
      * This lock covers both {@link #mImplicitlyQueryable} and {@link #mRetainedImplicitlyQueryable}
      */
-    protected final Object mImplicitlyQueryableLock = new Object();
-    protected final Object mQueryableViaUsesLibraryLock = new Object();
-    protected final Object mProtectedBroadcastsLock = new Object();
-    protected final Object mQueryableViaUsesPermissionLock = new Object();
+    protected final PackageManagerTracedLock mImplicitlyQueryableLock =
+        new PackageManagerTracedLock();
+    protected final PackageManagerTracedLock mQueryableViaUsesLibraryLock =
+        new PackageManagerTracedLock();
+    protected final PackageManagerTracedLock mProtectedBroadcastsLock =
+        new PackageManagerTracedLock();
+    protected final PackageManagerTracedLock mQueryableViaUsesPermissionLock =
+        new PackageManagerTracedLock();
 
     /**
      * Guards the access for {@link AppsFilterBase#mShouldFilterCache};
      */
-    protected final Object mCacheLock = new Object();
+    protected final PackageManagerTracedLock mCacheLock = new PackageManagerTracedLock();
 
     @Override
     protected boolean isForceQueryable(int appId) {
diff --git a/services/core/java/com/android/server/pm/Computer.java b/services/core/java/com/android/server/pm/Computer.java
index 9748aba..1e9a15d 100644
--- a/services/core/java/com/android/server/pm/Computer.java
+++ b/services/core/java/com/android/server/pm/Computer.java
@@ -60,7 +60,6 @@
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
-import java.util.Collection;
 import java.util.List;
 import java.util.Set;
 
@@ -679,5 +678,5 @@
     UserInfo[] getUserInfos();
 
     @NonNull
-    Collection<SharedUserSetting> getAllSharedUsers();
+    ArrayMap<String, ? extends SharedUserApi> getSharedUsers();
 }
diff --git a/services/core/java/com/android/server/pm/ComputerEngine.java b/services/core/java/com/android/server/pm/ComputerEngine.java
index 6f7ce80..2a337e4 100644
--- a/services/core/java/com/android/server/pm/ComputerEngine.java
+++ b/services/core/java/com/android/server/pm/ComputerEngine.java
@@ -301,8 +301,8 @@
         }
 
         @NonNull
-        public Collection<SharedUserSetting> getAllSharedUsers() {
-            return mSettings.getAllSharedUsersLPw();
+        ArrayMap<String, ? extends SharedUserApi> getSharedUsers() {
+            return mSettings.getSharedUsersLocked().untrackedStorage();
         }
 
         @Nullable
@@ -5489,8 +5489,8 @@
     @Override
     public SparseArray<String> getAppsWithSharedUserIds() {
         final SparseArray<String> sharedUserIds = new SparseArray<>();
-        for (SharedUserSetting setting : mSettings.getAllSharedUsers()) {
-            sharedUserIds.put(UserHandle.getAppId(setting.mAppId), setting.name);
+        for (SharedUserApi sharedUser : mSettings.getSharedUsers().values()) {
+            sharedUserIds.put(UserHandle.getAppId(sharedUser.getAppId()), sharedUser.getName());
         }
         return sharedUserIds;
     }
@@ -5790,8 +5790,8 @@
 
     @Override
     @NonNull
-    public Collection<SharedUserSetting> getAllSharedUsers() {
-        return mSettings.getAllSharedUsers();
+    public ArrayMap<String, ? extends SharedUserApi> getSharedUsers() {
+        return mSettings.getSharedUsers();
     }
 
     @Override
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index 69e92e0..84e9c3f 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -1296,9 +1296,10 @@
                 installReason, allowListedPermissions, statusReceiver);
     }
 
+    @android.annotation.EnforcePermission(android.Manifest.permission.INSTALL_PACKAGES)
     @Override
     public void setPermissionsResult(int sessionId, boolean accepted) {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INSTALL_PACKAGES, TAG);
+        setPermissionsResult_enforcePermission();
 
         synchronized (mSessions) {
             PackageInstallerSession session = mSessions.get(sessionId);
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index ea6383e..70a24f2 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -1134,8 +1134,13 @@
             info.userId = userId;
             info.installerPackageName = mInstallSource.mInstallerPackageName;
             info.installerAttributionTag = mInstallSource.mInstallerAttributionTag;
-            info.resolvedBaseCodePath = (mResolvedBaseFile != null) ?
-                    mResolvedBaseFile.getAbsolutePath() : null;
+            if (mContext.checkCallingOrSelfPermission(
+                    Manifest.permission.READ_INSTALLED_SESSION_PATHS)
+                            == PackageManager.PERMISSION_GRANTED && mResolvedBaseFile != null) {
+                info.resolvedBaseCodePath = mResolvedBaseFile.getAbsolutePath();
+            } else {
+                info.resolvedBaseCodePath = null;
+            }
             info.progress = progress;
             info.sealed = mSealed;
             info.isCommitted = isCommitted();
@@ -2757,11 +2762,6 @@
                         : PackageInstaller.ACTION_CONFIRM_INSTALL);
         intent.setPackage(mPm.getPackageInstallerPackageName());
         intent.putExtra(PackageInstaller.EXTRA_SESSION_ID, sessionId);
-        synchronized (mLock) {
-            intent.putExtra(PackageInstaller.EXTRA_RESOLVED_BASE_PATH,
-                    mResolvedBaseFile != null ? mResolvedBaseFile.getAbsolutePath() : null);
-        }
-
         sendOnUserActionRequired(mContext, target, sessionId, intent);
     }
 
@@ -4087,16 +4087,18 @@
         return params.installFlags;
     }
 
+    @android.annotation.EnforcePermission(android.Manifest.permission.USE_INSTALLER_V2)
     @Override
     public DataLoaderParamsParcel getDataLoaderParams() {
-        mContext.enforceCallingOrSelfPermission(Manifest.permission.USE_INSTALLER_V2, null);
+        getDataLoaderParams_enforcePermission();
         return params.dataLoaderParams != null ? params.dataLoaderParams.getData() : null;
     }
 
+    @android.annotation.EnforcePermission(android.Manifest.permission.USE_INSTALLER_V2)
     @Override
     public void addFile(int location, String name, long lengthBytes, byte[] metadata,
             byte[] signature) {
-        mContext.enforceCallingOrSelfPermission(Manifest.permission.USE_INSTALLER_V2, null);
+        addFile_enforcePermission();
         if (!isDataLoaderInstallation()) {
             throw new IllegalStateException(
                     "Cannot add files to non-data loader installation session.");
@@ -4127,9 +4129,10 @@
         }
     }
 
+    @android.annotation.EnforcePermission(android.Manifest.permission.USE_INSTALLER_V2)
     @Override
     public void removeFile(int location, String name) {
-        mContext.enforceCallingOrSelfPermission(Manifest.permission.USE_INSTALLER_V2, null);
+        removeFile_enforcePermission();
         if (!isDataLoaderInstallation()) {
             throw new IllegalStateException(
                     "Cannot add files to non-data loader installation session.");
diff --git a/services/core/java/com/android/server/pm/PackageManagerLocal.java b/services/core/java/com/android/server/pm/PackageManagerLocal.java
index 935c4dd..6266ef3 100644
--- a/services/core/java/com/android/server/pm/PackageManagerLocal.java
+++ b/services/core/java/com/android/server/pm/PackageManagerLocal.java
@@ -24,6 +24,7 @@
 import android.os.UserHandle;
 
 import com.android.server.pm.pkg.PackageState;
+import com.android.server.pm.pkg.SharedUserApi;
 
 import java.io.IOException;
 import java.lang.annotation.Retention;
@@ -150,6 +151,16 @@
         Map<String, PackageState> getPackageStates();
 
         /**
+         * Returns a map of all {@link SharedUserApi SharedUsers} on the device.
+         *
+         * @return Mapping of shared user name to {@link SharedUserApi}.
+         *
+         * @hide Pending API
+         */
+        @NonNull
+        Map<String, SharedUserApi> getSharedUsers();
+
+        /**
          * Returns a map of all disabled system {@link PackageState PackageStates} on the device.
          *
          * @return Mapping of package name to disabled system {@link PackageState}.
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 6b213b7..b76e313 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -189,6 +189,7 @@
 import com.android.modules.utils.TypedXmlPullParser;
 import com.android.modules.utils.TypedXmlSerializer;
 import com.android.permission.persistence.RuntimePermissionsPersistence;
+import com.android.permission.persistence.RuntimePermissionsState;
 import com.android.server.EventLogTags;
 import com.android.server.FgThread;
 import com.android.server.LocalManagerRegistry;
@@ -197,6 +198,7 @@
 import com.android.server.PackageWatchdog;
 import com.android.server.ServiceThread;
 import com.android.server.SystemConfig;
+import com.android.server.ThreadPriorityBooster;
 import com.android.server.Watchdog;
 import com.android.server.apphibernation.AppHibernationManagerInternal;
 import com.android.server.art.DexUseManagerLocal;
@@ -219,6 +221,7 @@
 import com.android.server.pm.parsing.pkg.ParsedPackage;
 import com.android.server.pm.permission.LegacyPermissionManagerInternal;
 import com.android.server.pm.permission.LegacyPermissionManagerService;
+import com.android.server.pm.permission.LegacyPermissionSettings;
 import com.android.server.pm.permission.PermissionManagerService;
 import com.android.server.pm.permission.PermissionManagerServiceInternal;
 import com.android.server.pm.pkg.AndroidPackage;
@@ -994,6 +997,32 @@
     private final DistractingPackageHelper mDistractingPackageHelper;
     private final StorageEventHelper mStorageEventHelper;
 
+    private static final boolean ENABLE_BOOST = true;
+
+    private static ThreadPriorityBooster sThreadPriorityBooster = new ThreadPriorityBooster(
+            Process.THREAD_PRIORITY_FOREGROUND, LockGuard.INDEX_PACKAGES);
+
+    /**
+     * Boost the priority of the thread before holding PM traced lock.
+     * @hide
+     */
+    public static void boostPriorityForPackageManagerTracedLockedSection() {
+        if (ENABLE_BOOST) {
+            sThreadPriorityBooster.boost();
+        }
+    }
+
+
+    /**
+     * Restore the priority of the thread after release the PM traced lock.
+     * @hide
+     */
+    public static void resetPriorityAfterPackageManagerTracedLockedSection() {
+        if (ENABLE_BOOST) {
+            sThreadPriorityBooster.reset();
+        }
+    }
+
     /**
      * Invalidate the package info cache, which includes updating the cached computer.
      * @hide
@@ -2367,13 +2396,6 @@
 
         mInjector.getSystemWrapper().enablePackageCaches();
 
-        // Now after opening every single application zip, make sure they
-        // are all flushed.  Not really needed, but keeps things nice and
-        // tidy.
-        t.traceBegin("GC");
-        VMRuntime.getRuntime().requestConcurrentGC();
-        t.traceEnd();
-
         // The initial scanning above does many calls into installd while
         // holding the mPackages lock, but we're mostly interested in yelling
         // once we have a booted system.
@@ -4662,11 +4684,11 @@
             }
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.CLEAR_APP_USER_DATA)
         @Override
         public void clearApplicationUserData(final String packageName,
                 final IPackageDataObserver observer, final int userId) {
-            mContext.enforceCallingOrSelfPermission(
-                    android.Manifest.permission.CLEAR_APP_USER_DATA, null);
+            clearApplicationUserData_enforcePermission();
 
             final int callingUid = Binder.getCallingUid();
             final Computer snapshot = snapshotComputer();
@@ -4738,10 +4760,10 @@
             });
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
         @Override
         public void clearCrossProfileIntentFilters(int sourceUserId, String ownerPackage) {
-            mContext.enforceCallingOrSelfPermission(
-                    android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, null);
+            clearCrossProfileIntentFilters_enforcePermission();
             final int callingUid = Binder.getCallingUid();
             final Computer snapshot = snapshotComputer();
             enforceOwnerRights(snapshot, ownerPackage, callingUid);
@@ -4753,13 +4775,13 @@
             scheduleWritePackageRestrictions(sourceUserId);
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
         @Override
         public boolean removeCrossProfileIntentFilter(IntentFilter intentFilter,
                 String ownerPackage,
                 int sourceUserId,
                 int targetUserId, int flags) {
-            mContext.enforceCallingOrSelfPermission(
-                    android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, null);
+            removeCrossProfileIntentFilter_enforcePermission();
             final int callingUid = Binder.getCallingUid();
             enforceOwnerRights(snapshotComputer(), ownerPackage, callingUid);
             mUserManager.enforceCrossProfileIntentFilterAccess(sourceUserId, targetUserId,
@@ -4927,11 +4949,11 @@
         }
 
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.CLEAR_APP_CACHE)
         @Override
         public void freeStorage(final String volumeUuid, final long freeStorageSize,
                 final @StorageManager.AllocateFlags int flags, final IntentSender pi) {
-            mContext.enforceCallingOrSelfPermission(
-                    android.Manifest.permission.CLEAR_APP_CACHE, TAG);
+            freeStorage_enforcePermission();
             mHandler.post(() -> {
                 boolean success = false;
                 try {
@@ -4954,11 +4976,11 @@
             });
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.CLEAR_APP_CACHE)
         @Override
         public void freeStorageAndNotify(final String volumeUuid, final long freeStorageSize,
                 final @StorageManager.AllocateFlags int flags, final IPackageDataObserver observer) {
-            mContext.enforceCallingOrSelfPermission(
-                    android.Manifest.permission.CLEAR_APP_CACHE, null);
+            freeStorageAndNotify_enforcePermission();
             mHandler.post(() -> {
                 boolean success = false;
                 try {
@@ -5043,10 +5065,10 @@
             return token;
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.ACCESS_INSTANT_APPS)
         @Override
         public String getInstantAppAndroidId(String packageName, int userId) {
-            mContext.enforceCallingOrSelfPermission(
-                    android.Manifest.permission.ACCESS_INSTANT_APPS, "getInstantAppAndroidId");
+            getInstantAppAndroidId_enforcePermission();
             final Computer snapshot = snapshotComputer();
             snapshot.enforceCrossUserPermission(Binder.getCallingUid(), userId,
                     true /* requireFullPermission */, false /* checkShell */,
@@ -5138,16 +5160,17 @@
             return getMimeGroupInternal(snapshot, packageName, mimeGroup);
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS)
         @Override
         public int getMoveStatus(int moveId) {
-            mContext.enforceCallingOrSelfPermission(
-                    Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS, null);
+            getMoveStatus_enforcePermission();
             return mMoveCallbacks.mLastStatus.get(moveId);
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.GET_APP_METADATA)
         @Override
         public ParcelFileDescriptor getAppMetadataFd(String packageName, int userId) {
-            mContext.enforceCallingOrSelfPermission(GET_APP_METADATA, "getAppMetadataFd");
+            getAppMetadataFd_enforcePermission();
             final int callingUid = Binder.getCallingUid();
             final Computer snapshot = snapshotComputer();
             final PackageStateInternal ps = snapshot.getPackageStateForInstalledAndFiltered(
@@ -5244,11 +5267,10 @@
                     packageNames, userId, callingUid);
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.PACKAGE_VERIFICATION_AGENT)
         @Override
         public VerifierDeviceIdentity getVerifierDeviceIdentity() throws RemoteException {
-            mContext.enforceCallingOrSelfPermission(
-                    Manifest.permission.PACKAGE_VERIFICATION_AGENT,
-                    "Only package verification agents can read the verifier device identity");
+            getVerifierDeviceIdentity_enforcePermission();
 
             synchronized (mLock) {
                 return mSettings.getVerifierDeviceIdentityLPw(mLiveComputer);
@@ -5270,10 +5292,10 @@
                     false /*direct*/, false /* retainOnUpdate */);
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.MAKE_UID_VISIBLE)
         @Override
         public void makeUidVisible(int recipientUid, int visibleUid) {
-            mContext.enforceCallingOrSelfPermission(
-                    android.Manifest.permission.MAKE_UID_VISIBLE, "makeUidVisible");
+            makeUidVisible_enforcePermission();
             final int callingUid = Binder.getCallingUid();
             final int recipientUserId = UserHandle.getUserId(recipientUid);
             final int visibleUserId = UserHandle.getUserId(visibleUid);
@@ -5372,9 +5394,10 @@
                     processName, uid, seinfo, pid);
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.MOVE_PACKAGE)
         @Override
         public int movePackage(final String packageName, final String volumeUuid) {
-            mContext.enforceCallingOrSelfPermission(Manifest.permission.MOVE_PACKAGE, null);
+            movePackage_enforcePermission();
 
             final int callingUid = Binder.getCallingUid();
             final UserHandle user = new UserHandle(UserHandle.getUserId(callingUid));
@@ -5393,9 +5416,10 @@
             return moveId;
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.MOVE_PACKAGE)
         @Override
         public int movePrimaryStorage(String volumeUuid) throws RemoteException {
-            mContext.enforceCallingOrSelfPermission(Manifest.permission.MOVE_PACKAGE, null);
+            movePrimaryStorage_enforcePermission();
 
             final int realMoveId = mNextMoveId.getAndIncrement();
             final Bundle extras = new Bundle();
@@ -5583,10 +5607,10 @@
             }
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS)
         @Override
         public void registerMoveCallback(IPackageMoveObserver callback) {
-            mContext.enforceCallingOrSelfPermission(
-                    Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS, null);
+            registerMoveCallback_enforcePermission();
             mMoveCallbacks.register(callback);
         }
 
@@ -5688,10 +5712,11 @@
                     userId, callingPackage);
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.MANAGE_USERS)
         @Override
         public boolean setApplicationHiddenSettingAsUser(String packageName, boolean hidden,
                 int userId) {
-            mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USERS, null);
+            setApplicationHiddenSettingAsUser_enforcePermission();
             final int callingUid = Binder.getCallingUid();
             final Computer snapshot = snapshotComputer();
             snapshot.enforceCrossUserPermission(callingUid, userId, true /* requireFullPermission */,
@@ -5775,11 +5800,11 @@
             }
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.DELETE_PACKAGES)
         @Override
         public boolean setBlockUninstallForUser(String packageName, boolean blockUninstall,
                 int userId) {
-            mContext.enforceCallingOrSelfPermission(
-                    Manifest.permission.DELETE_PACKAGES, null);
+            setBlockUninstallForUser_enforcePermission();
             final Computer snapshot = snapshotComputer();
             PackageStateInternal packageState = snapshot.getPackageStateInternal(packageName);
             if (packageState != null && packageState.getPkg() != null) {
@@ -5871,10 +5896,10 @@
             scheduleWritePackageRestrictions(userId);
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
         @Override
         public boolean setInstallLocation(int loc) {
-            mContext.enforceCallingOrSelfPermission(Manifest.permission.WRITE_SECURE_SETTINGS,
-                    null);
+            setInstallLocation_enforcePermission();
             if (getInstallLocation() == loc) {
                 return true;
             }
@@ -6185,17 +6210,18 @@
                     state.userState(userId).setSplashScreenTheme(themeId));
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.INSTALL_PACKAGES)
         @Override
         public void setUpdateAvailable(String packageName, boolean updateAvailable) {
-            mContext.enforceCallingOrSelfPermission(Manifest.permission.INSTALL_PACKAGES, null);
+            setUpdateAvailable_enforcePermission();
             commitPackageStateMutation(null, packageName, state ->
                     state.setUpdateAvailable(updateAvailable));
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS)
         @Override
         public void unregisterMoveCallback(IPackageMoveObserver callback) {
-            mContext.enforceCallingOrSelfPermission(
-                    Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS, null);
+            unregisterMoveCallback_enforcePermission();
             mMoveCallbacks.unregister(callback);
         }
 
@@ -6736,6 +6762,30 @@
         }
 
         @Override
+        public LegacyPermissionSettings getLegacyPermissions() {
+            synchronized (mLock) {
+                return mSettings.mPermissions;
+            }
+        }
+
+        /**
+         * Read legacy permission states for permissions migration to new permission subsystem.
+         */
+        @Override
+        public RuntimePermissionsState getLegacyPermissionsState(int userId) {
+            synchronized (mLock) {
+                return mSettings.getLegacyPermissionsState(userId);
+            }
+        }
+
+        @Override
+        public int getLegacyPermissionsVersion(@UserIdInt int userId) {
+            synchronized (mLock) {
+                return mSettings.getDefaultRuntimePermissionsVersion(userId);
+            }
+        }
+
+        @Override
         @SuppressWarnings("GuardedBy")
         public boolean isPermissionUpgradeNeeded(int userId) {
             return mSettings.isPermissionUpgradeNeeded(userId);
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 417ba07..584617b 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -110,6 +110,7 @@
 import com.android.server.pm.pkg.PackageStateInternal;
 import com.android.server.pm.pkg.PackageUserState;
 import com.android.server.pm.pkg.PackageUserStateInternal;
+import com.android.server.pm.pkg.SharedUserApi;
 import com.android.server.pm.pkg.SuspendParams;
 import com.android.server.pm.pkg.component.ParsedComponent;
 import com.android.server.pm.pkg.component.ParsedIntentInfo;
@@ -696,7 +697,7 @@
         mHandler = handler;
         mLock = lock;
         mAppIds = new AppIdSettingMap();
-        mPermissions = new LegacyPermissionSettings(lock);
+        mPermissions = new LegacyPermissionSettings();
         mRuntimePermissionsPersistence = new RuntimePermissionPersistence(
                 runtimePermissionsPersistence, new Consumer<Integer>() {
             @Override
@@ -867,6 +868,10 @@
         return s;
     }
 
+    WatchedArrayMap<String, ? extends SharedUserApi> getSharedUsersLocked() {
+        return mSharedUsers;
+    }
+
     Collection<SharedUserSetting> getAllSharedUsersLPw() {
         return mSharedUsers.values();
     }
@@ -3287,6 +3292,11 @@
                 mPackages, mSharedUsers, getUserRuntimePermissionsFile(userId));
     }
 
+    RuntimePermissionsState getLegacyPermissionsState(@UserIdInt int userId) {
+        return mRuntimePermissionsPersistence.getLegacyPermissionsState(
+                userId, mPackages, mSharedUsers);
+    }
+
     void applyDefaultPreferredAppsLPw(int userId) {
         // First pull data from any pre-installed apps.
         final PackageManagerInternal pmInternal =
@@ -5712,7 +5722,7 @@
                 legacyPermissionDataProvider,
                 @NonNull WatchedArrayMap<String, ? extends PackageStateInternal> packageStates,
                 @NonNull WatchedArrayMap<String, SharedUserSetting> sharedUsers,
-                @Nullable Handler pmHandler, @NonNull Object pmLock,
+                @Nullable Handler pmHandler, @NonNull PackageManagerTracedLock pmLock,
                 boolean sync) {
             synchronized (mLock) {
                 mAsyncHandler.removeMessages(userId);
@@ -5722,44 +5732,16 @@
             Runnable writer = () -> {
                 boolean isLegacyPermissionStateStale = mIsLegacyPermissionStateStale.getAndSet(
                         false);
+                Map<String, List<RuntimePermissionsState.PermissionState>> packagePermissions;
+                Map<String, List<RuntimePermissionsState.PermissionState>> sharedUserPermissions;
 
-                final Map<String, List<RuntimePermissionsState.PermissionState>>
-                        packagePermissions = new ArrayMap<>();
-                final Map<String, List<RuntimePermissionsState.PermissionState>>
-                        sharedUserPermissions = new ArrayMap<>();
                 synchronized (pmLock) {
                     if (sync || isLegacyPermissionStateStale) {
                         legacyPermissionDataProvider.writeLegacyPermissionStateTEMP();
                     }
 
-                    int packagesSize = packageStates.size();
-                    for (int i = 0; i < packagesSize; i++) {
-                        String packageName = packageStates.keyAt(i);
-                        PackageStateInternal packageState = packageStates.valueAt(i);
-                        if (!packageState.hasSharedUser()) {
-                            List<RuntimePermissionsState.PermissionState> permissions =
-                                    getPermissionsFromPermissionsState(
-                                            packageState.getLegacyPermissionState(), userId);
-                            if (permissions.isEmpty()
-                                    && !packageState.isInstallPermissionsFixed()) {
-                                // Storing an empty state means the package is known to the
-                                // system and its install permissions have been granted and fixed.
-                                // If this is not the case, we should not store anything.
-                                continue;
-                            }
-                            packagePermissions.put(packageName, permissions);
-                        }
-                    }
-
-                    final int sharedUsersSize = sharedUsers.size();
-                    for (int i = 0; i < sharedUsersSize; i++) {
-                        String sharedUserName = sharedUsers.keyAt(i);
-                        SharedUserSetting sharedUserSetting = sharedUsers.valueAt(i);
-                        List<RuntimePermissionsState.PermissionState> permissions =
-                                getPermissionsFromPermissionsState(
-                                        sharedUserSetting.getLegacyPermissionState(), userId);
-                        sharedUserPermissions.put(sharedUserName, permissions);
-                    }
+                    packagePermissions = getPackagePermissions(userId, packageStates);
+                    sharedUserPermissions = getShareUsersPermissions(userId, sharedUsers);
                 }
                 synchronized (mLock) {
                     int version = mVersions.get(userId, INITIAL_VERSION);
@@ -5787,6 +5769,68 @@
             }
         }
 
+        @NonNull
+        RuntimePermissionsState getLegacyPermissionsState(int userId,
+                @NonNull WatchedArrayMap<String, ? extends PackageStateInternal> packageStates,
+                @NonNull WatchedArrayMap<String, SharedUserSetting> sharedUsers) {
+            int version;
+            String fingerprint;
+            synchronized (mLock) {
+                version = mVersions.get(userId, INITIAL_VERSION);
+                fingerprint = mFingerprints.get(userId);
+            }
+
+            return new RuntimePermissionsState(
+                    version, fingerprint, getPackagePermissions(userId, packageStates),
+                    getShareUsersPermissions(userId, sharedUsers));
+        }
+
+        @NonNull
+        private Map<String, List<RuntimePermissionsState.PermissionState>> getPackagePermissions(
+                int userId,
+                @NonNull WatchedArrayMap<String, ? extends PackageStateInternal> packageStates) {
+            final Map<String, List<RuntimePermissionsState.PermissionState>>
+                    packagePermissions = new ArrayMap<>();
+
+            final int packagesSize = packageStates.size();
+            for (int i = 0; i < packagesSize; i++) {
+                String packageName = packageStates.keyAt(i);
+                PackageStateInternal packageState = packageStates.valueAt(i);
+                if (!packageState.hasSharedUser()) {
+                    List<RuntimePermissionsState.PermissionState> permissions =
+                            getPermissionsFromPermissionsState(
+                                    packageState.getLegacyPermissionState(), userId);
+                    if (permissions.isEmpty()
+                            && !packageState.isInstallPermissionsFixed()) {
+                        // Storing an empty state means the package is known to the
+                        // system and its install permissions have been granted and fixed.
+                        // If this is not the case, we should not store anything.
+                        continue;
+                    }
+                    packagePermissions.put(packageName, permissions);
+                }
+            }
+            return packagePermissions;
+        }
+
+        @NonNull
+        private Map<String, List<RuntimePermissionsState.PermissionState>> getShareUsersPermissions(
+                int userId, @NonNull WatchedArrayMap<String, SharedUserSetting> sharedUsers) {
+            final Map<String, List<RuntimePermissionsState.PermissionState>>
+                    sharedUserPermissions = new ArrayMap<>();
+
+            final int sharedUsersSize = sharedUsers.size();
+            for (int i = 0; i < sharedUsersSize; i++) {
+                String sharedUserName = sharedUsers.keyAt(i);
+                SharedUserSetting sharedUserSetting = sharedUsers.valueAt(i);
+                List<RuntimePermissionsState.PermissionState> permissions =
+                        getPermissionsFromPermissionsState(
+                                sharedUserSetting.getLegacyPermissionState(), userId);
+                sharedUserPermissions.put(sharedUserName, permissions);
+            }
+            return sharedUserPermissions;
+        }
+
         private void writePendingStates() {
             while (true) {
                 final RuntimePermissionsState runtimePermissions;
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index ab9d1cf..7603c45 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -2260,7 +2260,7 @@
     @Override
     public boolean isRestricted(@UserIdInt int userId) {
         if (userId != UserHandle.getCallingUserId()) {
-            checkCreateUsersPermission("query isRestricted for user " + userId);
+            checkQueryOrCreateUsersPermission("query isRestricted for user " + userId);
         }
         synchronized (mUsersLock) {
             final UserInfo userInfo = getUserInfoLU(userId);
@@ -2481,41 +2481,58 @@
     @Override
     public boolean setUserEphemeral(@UserIdInt int userId, boolean enableEphemeral) {
         checkCreateUsersPermission("update ephemeral user flag");
-        UserData userToUpdate = null;
+        return enableEphemeral
+                ? UserManager.isRemoveResultSuccessful(setUserEphemeralUnchecked(userId))
+                : setUserNonEphemeralUnchecked(userId);
+    }
+
+    private boolean setUserNonEphemeralUnchecked(@UserIdInt int userId) {
         synchronized (mPackagesLock) {
+            final UserData userData;
             synchronized (mUsersLock) {
-                final UserData userData = mUsers.get(userId);
+                userData = mUsers.get(userId);
                 if (userData == null) {
-                    Slog.e(LOG_TAG, "User not found for setting ephemeral mode: u" + userId);
+                    Slog.e(LOG_TAG, TextUtils.formatSimple(
+                            "Cannot set user %d non-ephemeral, invalid user id provided.", userId));
                     return false;
                 }
-                boolean isEphemeralUser = (userData.info.flags & UserInfo.FLAG_EPHEMERAL) != 0;
-                boolean isEphemeralOnCreateUser =
-                        (userData.info.flags & UserInfo.FLAG_EPHEMERAL_ON_CREATE) != 0;
-                // when user is created in ephemeral mode via FLAG_EPHEMERAL
-                // its state cannot be changed to non ephemeral.
-                // FLAG_EPHEMERAL_ON_CREATE is used to keep track of this state
-                if (isEphemeralOnCreateUser && !enableEphemeral) {
-                    Slog.e(LOG_TAG, "Failed to change user state to non-ephemeral for user "
-                            + userId);
+                if (!userData.info.isEphemeral()) {
+                    return true;
+                }
+
+                if ((userData.info.flags & UserInfo.FLAG_EPHEMERAL_ON_CREATE) != 0) {
+                    // when user is created in ephemeral mode via FLAG_EPHEMERAL
+                    // its state cannot be changed to non-ephemeral.
+                    // FLAG_EPHEMERAL_ON_CREATE is used to keep track of this state
+                    Slog.e(LOG_TAG, TextUtils.formatSimple("User %d can not be changed to "
+                            + "non-ephemeral because it was set ephemeral on create.", userId));
                     return false;
                 }
-                if (isEphemeralUser != enableEphemeral) {
-                    if (enableEphemeral) {
-                        userData.info.flags |= UserInfo.FLAG_EPHEMERAL;
-                    } else {
-                        userData.info.flags &= ~UserInfo.FLAG_EPHEMERAL;
-                    }
-                    userToUpdate = userData;
-                }
             }
-            if (userToUpdate != null) {
-                writeUserLP(userToUpdate);
-            }
+            userData.info.flags &= ~UserInfo.FLAG_EPHEMERAL;
+            writeUserLP(userData);
         }
         return true;
     }
 
+    private @UserManager.RemoveResult int setUserEphemeralUnchecked(@UserIdInt int userId) {
+        synchronized (mPackagesLock) {
+            final UserData userData;
+            synchronized (mUsersLock) {
+                final int userRemovability = getUserRemovabilityLocked(userId, "set as ephemeral");
+                if (userRemovability != UserManager.REMOVE_RESULT_USER_IS_REMOVABLE) {
+                    return userRemovability;
+                }
+                userData = mUsers.get(userId);
+            }
+            userData.info.flags |= UserInfo.FLAG_EPHEMERAL;
+            writeUserLP(userData);
+        }
+        Slog.i(LOG_TAG, TextUtils.formatSimple(
+                "User %d is set ephemeral and will be removed on user switch or reboot.", userId));
+        return UserManager.REMOVE_RESULT_DEFERRED;
+    }
+
     @Override
     public void setUserIcon(@UserIdInt int userId, Bitmap bitmap) {
         try {
@@ -5522,23 +5539,37 @@
     }
 
     private boolean removeUserWithProfilesUnchecked(@UserIdInt int userId) {
-        UserInfo userInfo = getUserInfoNoChecks(userId);
-
-        if (userInfo == null) {
-            Slog.e(LOG_TAG, TextUtils.formatSimple(
-                    "Cannot remove user %d, invalid user id provided.", userId));
-            return false;
+        final UserData userData;
+        final boolean isProfile;
+        final IntArray profileIds;
+        synchronized (mUsersLock) {
+            final int userRemovability = getUserRemovabilityLocked(userId, "removed");
+            if (userRemovability != UserManager.REMOVE_RESULT_USER_IS_REMOVABLE) {
+                return UserManager.isRemoveResultSuccessful(userRemovability);
+            }
+            userData = mUsers.get(userId);
+            isProfile = userData.info.isProfile();
+            profileIds = isProfile ? null : getProfileIdsLU(userId, null, false);
         }
 
-        if (!userInfo.isProfile()) {
-            int[] profileIds = getProfileIds(userId, false);
-            for (int profileId : profileIds) {
+        if (!isProfile) {
+            Pair<Integer, Integer> currentAndTargetUserIds = getCurrentAndTargetUserIds();
+            if (userId == currentAndTargetUserIds.first) {
+                Slog.w(LOG_TAG, "Current user cannot be removed.");
+                return false;
+            }
+            if (userId == currentAndTargetUserIds.second) {
+                Slog.w(LOG_TAG, "Target user of an ongoing user switch cannot be removed.");
+                return false;
+            }
+            for (int i = profileIds.size() - 1; i >= 0; i--) {
+                int profileId = profileIds.get(i);
                 if (profileId == userId) {
                     //Remove the associated profiles first and then remove the user
                     continue;
                 }
                 Slog.i(LOG_TAG, "removing profile:" + profileId
-                        + "associated with user:" + userId);
+                        + " associated with user:" + userId);
                 if (!removeUserUnchecked(profileId)) {
                     // If the profile was not immediately removed, make sure it is marked as
                     // ephemeral. Don't mark as disabled since, per UserInfo.FLAG_DISABLED
@@ -5585,45 +5616,16 @@
         final long ident = Binder.clearCallingIdentity();
         try {
             final UserData userData;
-            Pair<Integer, Integer> currentAndTargetUserIds = getCurrentAndTargetUserIds();
-            if (userId == currentAndTargetUserIds.first) {
-                Slog.w(LOG_TAG, "Current user cannot be removed.");
-                return false;
-            }
-            if (userId == currentAndTargetUserIds.second) {
-                Slog.w(LOG_TAG, "Target user of an ongoing user switch cannot be removed.");
-                return false;
-            }
             synchronized (mPackagesLock) {
                 synchronized (mUsersLock) {
+                    final int userRemovability = getUserRemovabilityLocked(userId, "removed");
+                    if (userRemovability != UserManager.REMOVE_RESULT_USER_IS_REMOVABLE) {
+                        return UserManager.isRemoveResultSuccessful(userRemovability);
+                    }
                     userData = mUsers.get(userId);
-                    if (userId == UserHandle.USER_SYSTEM) {
-                        Slog.e(LOG_TAG, "System user cannot be removed.");
-                        return false;
-                    }
-
-                    if (userData == null) {
-                        Slog.e(LOG_TAG, TextUtils.formatSimple(
-                                "Cannot remove user %d, invalid user id provided.", userId));
-                        return false;
-                    }
-
-                    if (isNonRemovableMainUser(userData.info)) {
-                        Slog.e(LOG_TAG, "Main user cannot be removed when "
-                                + "it's a permanent admin user.");
-                        return false;
-                    }
-
-                    if (mRemovingUserIds.get(userId)) {
-                        Slog.e(LOG_TAG, TextUtils.formatSimple(
-                                "User %d is already scheduled for removal.", userId));
-                        return false;
-                    }
-
                     Slog.i(LOG_TAG, "Removing user " + userId);
                     addRemovingUserIdLocked(userId);
                 }
-
                 // Set this to a partially created user, so that the user will be purged
                 // on next startup, in case the runtime stops now before stopping and
                 // removing the user completely.
@@ -5692,6 +5694,7 @@
     @Override
     public @UserManager.RemoveResult int removeUserWhenPossible(@UserIdInt int userId,
             boolean overrideDevicePolicy) {
+        Slog.i(LOG_TAG, "removeUserWhenPossible u" + userId);
         checkCreateUsersPermission("Only the system can remove users");
 
         if (!overrideDevicePolicy) {
@@ -5701,65 +5704,47 @@
                 return UserManager.REMOVE_RESULT_ERROR_USER_RESTRICTION;
             }
         }
+        Slog.i(LOG_TAG, "Attempting to immediately remove user " + userId);
+        if (removeUserWithProfilesUnchecked(userId)) {
+            return UserManager.REMOVE_RESULT_REMOVED;
+        }
+        Slog.i(LOG_TAG, TextUtils.formatSimple(
+                "Unable to immediately remove user %d. Now trying to set it ephemeral.", userId));
+        return setUserEphemeralUnchecked(userId);
+    }
+
+    /**
+     * Returns the user's removability status.
+     * User is removable if the return value is {@link UserManager#REMOVE_RESULT_USER_IS_REMOVABLE}.
+     * If the user is not removable this method also prints the reason.
+     * See also {@link UserManager#isRemoveResultSuccessful}.
+     */
+    @GuardedBy("mUsersLock")
+    private @UserManager.RemoveResult int getUserRemovabilityLocked(@UserIdInt int userId,
+            String msg) {
+        String prefix = TextUtils.formatSimple("User %d can not be %s, ", userId, msg);
         if (userId == UserHandle.USER_SYSTEM) {
-            Slog.e(LOG_TAG, "System user cannot be removed.");
+            Slog.e(LOG_TAG, prefix + "system user cannot be removed.");
             return UserManager.REMOVE_RESULT_ERROR_SYSTEM_USER;
         }
-
-        final long ident = Binder.clearCallingIdentity();
-        try {
-            final UserData userData;
-            synchronized (mPackagesLock) {
-                synchronized (mUsersLock) {
-                    userData = mUsers.get(userId);
-                    if (userData == null) {
-                        Slog.e(LOG_TAG,
-                                "Cannot remove user " + userId + ", invalid user id provided.");
-                        return UserManager.REMOVE_RESULT_ERROR_USER_NOT_FOUND;
-                    }
-
-                    if (isNonRemovableMainUser(userData.info)) {
-                        Slog.e(LOG_TAG, "Main user cannot be removed when "
-                                + "it's a permanent admin user.");
-                        return UserManager.REMOVE_RESULT_ERROR_MAIN_USER_PERMANENT_ADMIN;
-                    }
-
-                    if (mRemovingUserIds.get(userId)) {
-                        Slog.e(LOG_TAG, "User " + userId + " is already scheduled for removal.");
-                        return UserManager.REMOVE_RESULT_ALREADY_BEING_REMOVED;
-                    }
-                }
-
-                // Attempt to immediately remove a non-current and non-target user
-                Pair<Integer, Integer> currentAndTargetUserIds = getCurrentAndTargetUserIds();
-                if (userId != currentAndTargetUserIds.first
-                        && userId != currentAndTargetUserIds.second) {
-                    // Attempt to remove the user. This will fail if the user is the current user
-                    if (removeUserWithProfilesUnchecked(userId)) {
-                        return UserManager.REMOVE_RESULT_REMOVED;
-                    }
-                }
-                // If the user was not immediately removed, make sure it is marked as ephemeral.
-                // Don't mark as disabled since, per UserInfo.FLAG_DISABLED documentation, an
-                // ephemeral user should only be marked as disabled when its removal is in progress.
-                Slog.i(LOG_TAG, TextUtils.formatSimple("Unable to immediately remove user %d "
-                                + "(%s is %d). User is set as ephemeral and will be removed on "
-                                + "user switch or reboot.",
-                        userId,
-                        userId == currentAndTargetUserIds.first
-                                ? "current user"
-                                : "target user of an ongoing user switch",
-                        userId));
-                userData.info.flags |= UserInfo.FLAG_EPHEMERAL;
-                writeUserLP(userData);
-
-                return UserManager.REMOVE_RESULT_DEFERRED;
-            }
-        } finally {
-            Binder.restoreCallingIdentity(ident);
+        final UserData userData = mUsers.get(userId);
+        if (userData == null) {
+            Slog.e(LOG_TAG, prefix + "invalid user id provided.");
+            return UserManager.REMOVE_RESULT_ERROR_USER_NOT_FOUND;
         }
+        if (isNonRemovableMainUser(userData.info)) {
+            Slog.e(LOG_TAG, prefix
+                    + "main user cannot be removed when it's a permanent admin user.");
+            return UserManager.REMOVE_RESULT_ERROR_MAIN_USER_PERMANENT_ADMIN;
+        }
+        if (mRemovingUserIds.get(userId)) {
+            Slog.w(LOG_TAG, prefix + "it is already scheduled for removal.");
+            return UserManager.REMOVE_RESULT_ALREADY_BEING_REMOVED;
+        }
+        return UserManager.REMOVE_RESULT_USER_IS_REMOVABLE;
     }
 
+
     private void finishRemoveUser(final @UserIdInt int userId) {
         Slog.i(LOG_TAG, "finishRemoveUser " + userId);
 
diff --git a/services/core/java/com/android/server/pm/local/PackageManagerLocalImpl.java b/services/core/java/com/android/server/pm/local/PackageManagerLocalImpl.java
index 4e0a11d..8d05450 100644
--- a/services/core/java/com/android/server/pm/local/PackageManagerLocalImpl.java
+++ b/services/core/java/com/android/server/pm/local/PackageManagerLocalImpl.java
@@ -28,6 +28,7 @@
 import com.android.server.pm.PackageManagerLocal;
 import com.android.server.pm.PackageManagerService;
 import com.android.server.pm.pkg.PackageState;
+import com.android.server.pm.pkg.SharedUserApi;
 import com.android.server.pm.snapshot.PackageDataSnapshot;
 
 import java.io.IOException;
@@ -105,6 +106,9 @@
         private Map<String, PackageState> mCachedUnmodifiablePackageStates;
 
         @Nullable
+        private Map<String, SharedUserApi> mCachedUnmodifiableSharedUsers;
+
+        @Nullable
         private Map<String, PackageState> mCachedUnmodifiableDisabledSystemPackageStates;
 
         private UnfilteredSnapshotImpl(@NonNull PackageDataSnapshot snapshot) {
@@ -132,6 +136,19 @@
         @SuppressWarnings("RedundantSuppression")
         @NonNull
         @Override
+        public Map<String, SharedUserApi> getSharedUsers() {
+            checkClosed();
+
+            if (mCachedUnmodifiableSharedUsers == null) {
+                mCachedUnmodifiableSharedUsers =
+                        Collections.unmodifiableMap(mSnapshot.getSharedUsers());
+            }
+            return mCachedUnmodifiableSharedUsers;
+        }
+
+        @SuppressWarnings("RedundantSuppression")
+        @NonNull
+        @Override
         public Map<String, PackageState> getDisabledSystemPackageStates() {
             checkClosed();
 
diff --git a/services/core/java/com/android/server/pm/permission/AccessTestingShimFactory.java b/services/core/java/com/android/server/pm/permission/AccessTestingShimFactory.java
new file mode 100644
index 0000000..0682e92
--- /dev/null
+++ b/services/core/java/com/android/server/pm/permission/AccessTestingShimFactory.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.pm.permission;
+
+import static android.provider.DeviceConfig.NAMESPACE_PRIVACY;
+
+import android.content.Context;
+import android.provider.DeviceConfig;
+
+import com.android.server.appop.AppOpsCheckingServiceInterface;
+import com.android.server.appop.AppOpsServiceTestingShim;
+
+import java.util.function.Supplier;
+
+/**
+ * A factory which will select one or both implementations of a PermissionManagerServiceInterface or
+ * AppOpsCheckingServiceInterface, based upon either a DeviceConfig value, or a hard coded config.
+ */
+public class AccessTestingShimFactory {
+
+    private static final int RUN_OLD_SUBSYSTEM = 0;
+    private static final int RUN_NEW_SUBSYSTEM = 1;
+    private static final int RUN_BOTH_SUBSYSTEMS = 2;
+    public static final String DEVICE_CONFIG_SETTING = "selected_access_subsystem";
+
+    /**
+     * Get the PermissionManagerServiceInterface, based upon the current config state.
+     */
+    public static PermissionManagerServiceInterface getPms(Context context,
+            Supplier<PermissionManagerServiceInterface> oldImpl,
+            Supplier<PermissionManagerServiceInterface> newImpl) {
+        int selectedSystem = DeviceConfig.getInt(NAMESPACE_PRIVACY,
+                DEVICE_CONFIG_SETTING, RUN_OLD_SUBSYSTEM);
+        switch (selectedSystem) {
+            case RUN_BOTH_SUBSYSTEMS:
+                return new PermissionManagerServiceTestingShim(oldImpl.get(), newImpl.get());
+            case RUN_NEW_SUBSYSTEM:
+                return newImpl.get();
+            default:
+                return oldImpl.get();
+        }
+    }
+
+    /**
+     * Get the AppOpsCheckingServiceInterface, based upon the current config state.
+     */
+    public static AppOpsCheckingServiceInterface getAos(Context context,
+            Supplier<AppOpsCheckingServiceInterface> oldImpl,
+            Supplier<AppOpsCheckingServiceInterface> newImpl) {
+        int selectedSystem = DeviceConfig.getInt(NAMESPACE_PRIVACY,
+                DEVICE_CONFIG_SETTING, RUN_OLD_SUBSYSTEM);
+        switch (selectedSystem) {
+            case RUN_BOTH_SUBSYSTEMS:
+                return new AppOpsServiceTestingShim(oldImpl.get(), newImpl.get());
+            case RUN_NEW_SUBSYSTEM:
+                return newImpl.get();
+            default:
+                return oldImpl.get();
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/pm/permission/LegacyPermissionSettings.java b/services/core/java/com/android/server/pm/permission/LegacyPermissionSettings.java
index fc6d202..fe6cd4d 100644
--- a/services/core/java/com/android/server/pm/permission/LegacyPermissionSettings.java
+++ b/services/core/java/com/android/server/pm/permission/LegacyPermissionSettings.java
@@ -28,10 +28,10 @@
 import com.android.modules.utils.TypedXmlSerializer;
 import com.android.server.pm.DumpState;
 import com.android.server.pm.PackageManagerService;
+import com.android.server.pm.PackageManagerTracedLock;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
-import org.xmlpull.v1.XmlSerializer;
 
 import java.io.IOException;
 import java.io.PrintWriter;
@@ -59,11 +59,7 @@
     private final ArrayMap<String, LegacyPermission> mPermissionTrees = new ArrayMap<>();
 
     @NonNull
-    private final Object mLock;
-
-    public LegacyPermissionSettings(@NonNull Object lock) {
-        mLock = lock;
-    }
+    private final PackageManagerTracedLock mLock = new PackageManagerTracedLock();
 
     @NonNull
     public List<LegacyPermission> getPermissions() {
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index c5f939a..df0192c 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -390,13 +390,11 @@
         return oneTimePermissionUserManager;
     }
 
+    @android.annotation.EnforcePermission(android.Manifest.permission.MANAGE_ONE_TIME_PERMISSION_SESSIONS)
     @Override
     public void startOneTimePermissionSession(String packageName, @UserIdInt int userId,
             long timeoutMillis, long revokeAfterKilledDelayMillis) {
-        mContext.enforceCallingOrSelfPermission(
-                Manifest.permission.MANAGE_ONE_TIME_PERMISSION_SESSIONS,
-                "Must hold " + Manifest.permission.MANAGE_ONE_TIME_PERMISSION_SESSIONS
-                        + " to register permissions as one time.");
+        startOneTimePermissionSession_enforcePermission();
         Objects.requireNonNull(packageName);
 
         final long token = Binder.clearCallingIdentity();
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java
index cc2c9ad..3a0729c 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java
@@ -134,6 +134,7 @@
 import com.android.server.pm.ApexManager;
 import com.android.server.pm.KnownPackages;
 import com.android.server.pm.PackageInstallerService;
+import com.android.server.pm.PackageManagerTracedLock;
 import com.android.server.pm.UserManagerInternal;
 import com.android.server.pm.UserManagerService;
 import com.android.server.pm.parsing.PackageInfoUtils;
@@ -252,7 +253,7 @@
             new ArraySet<>();
 
     /** Lock to protect internal data access */
-    private final Object mLock = new Object();
+    private final PackageManagerTracedLock mLock = new PackageManagerTracedLock();
 
     /** Internal connection to the package manager */
     private final PackageManagerInternal mPackageManagerInt;
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceTestingShim.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceTestingShim.java
new file mode 100644
index 0000000..3db08de
--- /dev/null
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceTestingShim.java
@@ -0,0 +1,565 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.pm.permission;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.UserIdInt;
+import android.content.pm.PermissionGroupInfo;
+import android.content.pm.PermissionInfo;
+import android.content.pm.permission.SplitPermissionInfoParcelable;
+import android.permission.IOnPermissionsChangeListener;
+
+import com.android.server.pm.pkg.AndroidPackage;
+import com.android.server.pm.pkg.PackageState;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+
+/**
+ * A testing shim, which supports running two variants of a PermissionManagerServiceInterface at
+ * once, and checking the results of both.
+ */
+public class PermissionManagerServiceTestingShim implements PermissionManagerServiceInterface {
+
+    private PermissionManagerServiceInterface mOldImplementation;
+    private PermissionManagerServiceInterface mNewImplementation;
+
+    public PermissionManagerServiceTestingShim(PermissionManagerServiceInterface oldImpl,
+            PermissionManagerServiceInterface newImpl) {
+        mOldImplementation = oldImpl;
+        mNewImplementation = newImpl;
+    }
+
+    private void signalImplDifference(String message) {
+        //TODO b/252886104 implement
+    }
+
+
+    @Nullable
+    @Override
+    public byte[] backupRuntimePermissions(int userId) {
+        byte[] oldVal = mOldImplementation.backupRuntimePermissions(userId);
+        byte[] newVal = mNewImplementation.backupRuntimePermissions(userId);
+        if (!Arrays.equals(oldVal, newVal)) {
+            signalImplDifference("backupRuntimePermissions");
+        }
+
+        return newVal;
+    }
+
+    @Override
+    public void restoreRuntimePermissions(@NonNull byte[] backup, int userId) {
+        mOldImplementation.backupRuntimePermissions(userId);
+        mNewImplementation.backupRuntimePermissions(userId);
+    }
+
+    @Override
+    public void restoreDelayedRuntimePermissions(@NonNull String packageName, int userId) {
+        mOldImplementation.restoreDelayedRuntimePermissions(packageName, userId);
+        mNewImplementation.restoreDelayedRuntimePermissions(packageName, userId);
+
+    }
+
+    @Override
+    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        mOldImplementation.dump(fd, pw, args);
+        mNewImplementation.dump(fd, pw, args);
+    }
+
+    @Override
+    public List<PermissionGroupInfo> getAllPermissionGroups(int flags) {
+        List<PermissionGroupInfo> oldVal = mOldImplementation.getAllPermissionGroups(flags);
+        List<PermissionGroupInfo> newVal = mNewImplementation.getAllPermissionGroups(flags);
+
+        if (!Objects.equals(oldVal, newVal)) {
+            signalImplDifference("getAllPermissionGroups");
+        }
+        return newVal;
+    }
+
+    @Override
+    public PermissionGroupInfo getPermissionGroupInfo(String groupName, int flags) {
+        PermissionGroupInfo oldVal = mOldImplementation.getPermissionGroupInfo(groupName, flags);
+        PermissionGroupInfo newVal = mNewImplementation.getPermissionGroupInfo(groupName, flags);
+
+        if (!Objects.equals(oldVal, newVal)) {
+            signalImplDifference("getPermissionGroupInfo");
+        }
+        return newVal;
+    }
+
+    @Override
+    public PermissionInfo getPermissionInfo(@NonNull String permName, int flags,
+            @NonNull String opPackageName) {
+        PermissionInfo oldVal = mOldImplementation.getPermissionInfo(permName, flags,
+                opPackageName);
+        PermissionInfo newVal = mNewImplementation.getPermissionInfo(permName, flags,
+                opPackageName);
+
+        if (!Objects.equals(oldVal, newVal)) {
+            signalImplDifference("getPermissionInfo");
+        }
+        return newVal;
+    }
+
+    @Override
+    public List<PermissionInfo> queryPermissionsByGroup(String groupName, int flags) {
+        List<PermissionInfo> oldVal = mOldImplementation.queryPermissionsByGroup(groupName,
+                flags);
+        List<PermissionInfo> newVal = mNewImplementation.queryPermissionsByGroup(groupName, flags);
+
+        if (!Objects.equals(oldVal, newVal)) {
+            signalImplDifference("queryPermissionsByGroup");
+        }
+        return newVal;
+    }
+
+    @Override
+    public boolean addPermission(PermissionInfo info, boolean async) {
+        boolean oldVal = mOldImplementation.addPermission(info, async);
+        boolean newVal = mNewImplementation.addPermission(info, async);
+
+        if (!Objects.equals(oldVal, newVal)) {
+            signalImplDifference("addPermission");
+        }
+        return newVal;
+    }
+
+    @Override
+    public void removePermission(String permName) {
+        mOldImplementation.removePermission(permName);
+        mNewImplementation.removePermission(permName);
+    }
+
+    @Override
+    public int getPermissionFlags(String packageName, String permName, int userId) {
+        int oldVal = mOldImplementation.getPermissionFlags(packageName, permName, userId);
+        int newVal = mNewImplementation.getPermissionFlags(packageName, permName, userId);
+
+        if (!Objects.equals(oldVal, newVal)) {
+            signalImplDifference("getPermissionFlags");
+        }
+        return newVal;
+    }
+
+    @Override
+    public void updatePermissionFlags(String packageName, String permName, int flagMask,
+            int flagValues, boolean checkAdjustPolicyFlagPermission, int userId) {
+        mOldImplementation.updatePermissionFlags(packageName, permName, flagMask, flagValues,
+                checkAdjustPolicyFlagPermission, userId);
+        mNewImplementation.updatePermissionFlags(packageName, permName, flagMask, flagValues,
+                checkAdjustPolicyFlagPermission, userId);
+    }
+
+    @Override
+    public void updatePermissionFlagsForAllApps(int flagMask, int flagValues, int userId) {
+        mOldImplementation.updatePermissionFlagsForAllApps(flagMask, flagValues, userId);
+        mNewImplementation.updatePermissionFlagsForAllApps(flagMask, flagValues, userId);
+    }
+
+    @Override
+    public void addOnPermissionsChangeListener(IOnPermissionsChangeListener listener) {
+        mOldImplementation.addOnPermissionsChangeListener(listener);
+        mNewImplementation.addOnPermissionsChangeListener(listener);
+    }
+
+    @Override
+    public void removeOnPermissionsChangeListener(IOnPermissionsChangeListener listener) {
+        mOldImplementation.removeOnPermissionsChangeListener(listener);
+        mNewImplementation.removeOnPermissionsChangeListener(listener);
+    }
+
+    @Override
+    public boolean addAllowlistedRestrictedPermission(@NonNull String packageName,
+            @NonNull String permName, int flags, int userId) {
+        boolean oldVal = mOldImplementation.addAllowlistedRestrictedPermission(packageName,
+                permName,
+                flags, userId);
+        boolean newVal = mNewImplementation.addAllowlistedRestrictedPermission(packageName,
+                permName, flags, userId);
+
+        if (!Objects.equals(oldVal, newVal)) {
+            signalImplDifference("addAllowlistedRestrictedPermission");
+        }
+        return newVal;
+    }
+
+    @Override
+    public List<String> getAllowlistedRestrictedPermissions(@NonNull String packageName, int flags,
+            int userId) {
+        List<String> oldVal = mOldImplementation.getAllowlistedRestrictedPermissions(packageName,
+                flags, userId);
+        List<String> newVal = mNewImplementation.getAllowlistedRestrictedPermissions(packageName,
+                flags, userId);
+
+        if (!Objects.equals(oldVal, newVal)) {
+            signalImplDifference("getAllowlistedRestrictedPermissions");
+        }
+        return newVal;
+    }
+
+    @Override
+    public boolean removeAllowlistedRestrictedPermission(@NonNull String packageName,
+            @NonNull String permName, int flags, int userId) {
+        boolean oldVal = mOldImplementation.removeAllowlistedRestrictedPermission(packageName,
+                permName, flags, userId);
+        boolean newVal = mNewImplementation.removeAllowlistedRestrictedPermission(packageName,
+                permName, flags, userId);
+
+        if (!Objects.equals(oldVal, newVal)) {
+            signalImplDifference("removeAllowlistedRestrictedPermission");
+        }
+        return newVal;
+    }
+
+    @Override
+    public void grantRuntimePermission(String packageName, String permName, int userId) {
+        mOldImplementation.grantRuntimePermission(packageName, permName, userId);
+        mNewImplementation.grantRuntimePermission(packageName, permName, userId);
+    }
+
+    @Override
+    public void revokeRuntimePermission(String packageName, String permName, int userId,
+            String reason) {
+        mOldImplementation.grantRuntimePermission(packageName, permName, userId);
+        mNewImplementation.grantRuntimePermission(packageName, permName, userId);
+    }
+
+    @Override
+    public void revokePostNotificationPermissionWithoutKillForTest(String packageName, int userId) {
+        mOldImplementation.revokePostNotificationPermissionWithoutKillForTest(packageName,
+                userId);
+        mNewImplementation.revokePostNotificationPermissionWithoutKillForTest(packageName, userId);
+    }
+
+    @Override
+    public boolean shouldShowRequestPermissionRationale(String packageName, String permName,
+            int userId) {
+        boolean oldVal = mOldImplementation
+                .shouldShowRequestPermissionRationale(packageName, permName, userId);
+        boolean newVal = mNewImplementation
+                .shouldShowRequestPermissionRationale(packageName, permName, userId);
+
+        if (!Objects.equals(oldVal, newVal)) {
+            signalImplDifference("shouldShowRequestPermissionRationale");
+        }
+        return newVal;
+    }
+
+    @Override
+    public boolean isPermissionRevokedByPolicy(String packageName, String permName, int userId) {
+        boolean oldVal = mOldImplementation
+                .isPermissionRevokedByPolicy(packageName, permName, userId);
+        boolean newVal = mNewImplementation.isPermissionRevokedByPolicy(packageName, permName,
+                userId);
+
+        if (!Objects.equals(oldVal, newVal)) {
+            signalImplDifference("isPermissionRevokedByPolicy");
+        }
+        return newVal;
+    }
+
+    @Override
+    public List<SplitPermissionInfoParcelable> getSplitPermissions() {
+        List<SplitPermissionInfoParcelable> oldVal = mOldImplementation.getSplitPermissions();
+        List<SplitPermissionInfoParcelable> newVal = mNewImplementation.getSplitPermissions();
+
+        if (!Objects.equals(oldVal, newVal)) {
+            signalImplDifference("getSplitPermissions");
+        }
+        return newVal;
+    }
+
+    @Override
+    public int checkPermission(String pkgName, String permName, int userId) {
+        int oldVal = mOldImplementation.checkPermission(pkgName, permName, userId);
+        int newVal = mNewImplementation.checkPermission(pkgName, permName, userId);
+
+        if (!Objects.equals(oldVal, newVal)) {
+            signalImplDifference("checkPermission");
+        }
+        return newVal;
+    }
+
+    @Override
+    public int checkUidPermission(int uid, String permName) {
+        int oldVal = mOldImplementation.checkUidPermission(uid, permName);
+        int newVal = mNewImplementation.checkUidPermission(uid, permName);
+
+        if (!Objects.equals(oldVal, newVal)) {
+            signalImplDifference("checkUidPermission");
+        }
+        return newVal;
+    }
+
+    @Override
+    public void addOnRuntimePermissionStateChangedListener(@NonNull
+            PermissionManagerServiceInternal.OnRuntimePermissionStateChangedListener listener) {
+        mOldImplementation.addOnRuntimePermissionStateChangedListener(listener);
+        mNewImplementation.addOnRuntimePermissionStateChangedListener(listener);
+    }
+
+    @Override
+    public void removeOnRuntimePermissionStateChangedListener(@NonNull
+            PermissionManagerServiceInternal.OnRuntimePermissionStateChangedListener listener) {
+        mOldImplementation.removeOnRuntimePermissionStateChangedListener(listener);
+        mNewImplementation.removeOnRuntimePermissionStateChangedListener(listener);
+    }
+
+    @Override
+    public Map<String, Set<String>> getAllAppOpPermissionPackages() {
+        Map<String, Set<String>> oldVal = mOldImplementation.getAllAppOpPermissionPackages();
+        Map<String, Set<String>> newVal = mNewImplementation.getAllAppOpPermissionPackages();
+
+        if (!Objects.equals(oldVal, newVal)) {
+            signalImplDifference("getAllAppOpPermissionPackages");
+        }
+        return newVal;
+    }
+
+    @Override
+    public boolean isPermissionsReviewRequired(@NonNull String packageName, int userId) {
+        boolean oldVal = mOldImplementation.isPermissionsReviewRequired(packageName, userId);
+        boolean newVal = mNewImplementation.isPermissionsReviewRequired(packageName, userId);
+
+        if (!Objects.equals(oldVal, newVal)) {
+            signalImplDifference("isPermissionsReviewRequired");
+        }
+        return newVal;
+    }
+
+    @Override
+    public void resetRuntimePermissions(@NonNull AndroidPackage pkg, @UserIdInt int userId) {
+        mOldImplementation.resetRuntimePermissions(pkg, userId);
+        mNewImplementation.resetRuntimePermissions(pkg, userId);
+    }
+
+    @Override
+    public void resetRuntimePermissionsForUser(int userId) {
+        mOldImplementation.resetRuntimePermissionsForUser(userId);
+        mNewImplementation.resetRuntimePermissionsForUser(userId);
+    }
+
+    @Override
+    public void readLegacyPermissionStateTEMP() {
+        mOldImplementation.readLegacyPermissionStateTEMP();
+        mNewImplementation.readLegacyPermissionStateTEMP();
+    }
+
+    @Override
+    public void writeLegacyPermissionStateTEMP() {
+        mOldImplementation.writeLegacyPermissionStateTEMP();
+        mNewImplementation.writeLegacyPermissionStateTEMP();
+    }
+
+    @Override
+    public Set<String> getInstalledPermissions(String packageName) {
+        Set<String> oldVal = mOldImplementation.getInstalledPermissions(packageName);
+        Set<String> newVal = mNewImplementation.getInstalledPermissions(packageName);
+
+        if (!Objects.equals(oldVal, newVal)) {
+            signalImplDifference("getInstalledPermissions");
+        }
+        return newVal;
+    }
+
+    @NonNull
+    @Override
+    public Set<String> getGrantedPermissions(@NonNull String packageName, int userId) {
+        Set<String> oldVal = mOldImplementation.getGrantedPermissions(packageName, userId);
+        Set<String> newVal = mNewImplementation.getGrantedPermissions(packageName, userId);
+
+        if (!Objects.equals(oldVal, newVal)) {
+            signalImplDifference("getGrantedPermissions");
+        }
+        return newVal;
+    }
+
+    @NonNull
+    @Override
+    public int[] getPermissionGids(@NonNull String permissionName, int userId) {
+        int[] oldVal = mOldImplementation.getPermissionGids(permissionName, userId);
+        int[] newVal = mNewImplementation.getPermissionGids(permissionName, userId);
+
+        if (!Arrays.equals(oldVal, newVal)) {
+            signalImplDifference("getPermissionGids");
+        }
+        return newVal;
+    }
+
+    @NonNull
+    @Override
+    public String[] getAppOpPermissionPackages(@NonNull String permissionName) {
+        String[] oldVal = mOldImplementation.getAppOpPermissionPackages(permissionName);
+        String[] newVal = mNewImplementation.getAppOpPermissionPackages(permissionName);
+
+        if (!Arrays.equals(oldVal, newVal)) {
+            signalImplDifference("getAppOpPermissionPackages");
+        }
+        return newVal;
+    }
+
+    @Nullable
+    @Override
+    public Permission getPermissionTEMP(@NonNull String permName) {
+        Permission oldVal = mOldImplementation.getPermissionTEMP(permName);
+        Permission newVal = mNewImplementation.getPermissionTEMP(permName);
+
+        if (!Objects.equals(oldVal, newVal)) {
+            signalImplDifference("getPermissionTEMP");
+        }
+        return newVal;
+    }
+
+    @NonNull
+    @Override
+    public List<PermissionInfo> getAllPermissionsWithProtection(int protection) {
+        List<PermissionInfo> oldVal = mOldImplementation.getAllPermissionsWithProtection(
+                protection);
+        List<PermissionInfo> newVal = mNewImplementation.getAllPermissionsWithProtection(
+                protection);
+
+        if (!Objects.equals(oldVal, newVal)) {
+            signalImplDifference("getAllPermissionsWithProtection");
+        }
+        return newVal;
+    }
+
+    @NonNull
+    @Override
+    public List<PermissionInfo> getAllPermissionsWithProtectionFlags(int protectionFlags) {
+        List<PermissionInfo> oldVal = mOldImplementation
+                .getAllPermissionsWithProtectionFlags(protectionFlags);
+        List<PermissionInfo> newVal = mNewImplementation.getAllPermissionsWithProtectionFlags(
+                protectionFlags);
+
+        if (!Objects.equals(oldVal, newVal)) {
+            signalImplDifference("getAllPermissionsWithProtectionFlags");
+        }
+        return newVal;
+    }
+
+    @NonNull
+    @Override
+    public List<LegacyPermission> getLegacyPermissions() {
+        List<LegacyPermission> oldVal = mOldImplementation.getLegacyPermissions();
+        List<LegacyPermission> newVal = mNewImplementation.getLegacyPermissions();
+
+        if (!Objects.equals(oldVal, newVal)) {
+            signalImplDifference("getLegacyPermissions");
+        }
+        return newVal;
+    }
+
+    @NonNull
+    @Override
+    public LegacyPermissionState getLegacyPermissionState(int appId) {
+        LegacyPermissionState oldVal = mOldImplementation.getLegacyPermissionState(appId);
+        LegacyPermissionState newVal = mNewImplementation.getLegacyPermissionState(appId);
+
+        if (!Objects.equals(oldVal, newVal)) {
+            signalImplDifference("getLegacyPermissionState");
+        }
+        return newVal;
+    }
+
+    @Override
+    public void readLegacyPermissionsTEMP(
+            @NonNull LegacyPermissionSettings legacyPermissionSettings) {
+        mOldImplementation.readLegacyPermissionsTEMP(legacyPermissionSettings);
+        mNewImplementation.readLegacyPermissionsTEMP(legacyPermissionSettings);
+    }
+
+    @Override
+    public void writeLegacyPermissionsTEMP(
+            @NonNull LegacyPermissionSettings legacyPermissionSettings) {
+        mOldImplementation.writeLegacyPermissionsTEMP(legacyPermissionSettings);
+        mNewImplementation.writeLegacyPermissionsTEMP(legacyPermissionSettings);
+    }
+
+    @Override
+    public void onSystemReady() {
+        mOldImplementation.onSystemReady();
+        mNewImplementation.onSystemReady();
+    }
+
+    @Override
+    public void onStorageVolumeMounted(@NonNull String volumeUuid, boolean fingerprintChanged) {
+        mOldImplementation.onStorageVolumeMounted(volumeUuid, fingerprintChanged);
+        mNewImplementation.onStorageVolumeMounted(volumeUuid, fingerprintChanged);
+    }
+
+    @NonNull
+    @Override
+    public int[] getGidsForUid(int uid) {
+        int[] oldVal = mOldImplementation.getGidsForUid(uid);
+        int[] newVal = mNewImplementation.getGidsForUid(uid);
+
+        if (!Arrays.equals(oldVal, newVal)) {
+            signalImplDifference("getGidsForUid");
+        }
+        return newVal;
+    }
+
+    @Override
+    public void onUserCreated(int userId) {
+        mOldImplementation.onUserCreated(userId);
+        mNewImplementation.onUserCreated(userId);
+    }
+
+    @Override
+    public void onUserRemoved(int userId) {
+        mOldImplementation.onUserRemoved(userId);
+        mNewImplementation.onUserRemoved(userId);
+    }
+
+    @Override
+    public void onPackageAdded(@NonNull PackageState pkg, boolean isInstantApp,
+            @Nullable AndroidPackage oldPkg) {
+        mOldImplementation.onPackageAdded(pkg, isInstantApp, oldPkg);
+        mNewImplementation.onPackageAdded(pkg, isInstantApp, oldPkg);
+    }
+
+    @Override
+    public void onPackageInstalled(@NonNull AndroidPackage pkg, int previousAppId,
+            @NonNull PermissionManagerServiceInternal.PackageInstalledParams params, int userId) {
+        mOldImplementation.onPackageInstalled(pkg, previousAppId, params, userId);
+        mNewImplementation.onPackageInstalled(pkg, previousAppId, params, userId);
+    }
+
+    @Override
+    public void onPackageRemoved(@NonNull AndroidPackage pkg) {
+        mOldImplementation.onPackageRemoved(pkg);
+        mNewImplementation.onPackageRemoved(pkg);
+    }
+
+    @Override
+    public void onPackageUninstalled(@NonNull String packageName, int appId,
+            @NonNull PackageState packageState, @Nullable AndroidPackage pkg,
+            @NonNull List<AndroidPackage> sharedUserPkgs, int userId) {
+        mOldImplementation.onPackageUninstalled(packageName, appId, packageState, pkg,
+                sharedUserPkgs, userId);
+        mNewImplementation.onPackageUninstalled(packageName, appId, packageState, pkg,
+                sharedUserPkgs, userId);
+    }
+}
diff --git a/services/core/java/com/android/server/pm/permission/PermissionMigrationHelper.java b/services/core/java/com/android/server/pm/permission/PermissionMigrationHelper.java
new file mode 100644
index 0000000..67c56cd
--- /dev/null
+++ b/services/core/java/com/android/server/pm/permission/PermissionMigrationHelper.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.pm.permission;
+
+import android.annotation.NonNull;
+import android.content.pm.PermissionInfo;
+
+import java.util.Map;
+
+/**
+ * In-process api for permissions migration.
+ *
+ * @hide
+ */
+public interface PermissionMigrationHelper {
+    /**
+     * @return legacy permission definitions.
+     */
+    @NonNull
+    Map<String, LegacyPermission> getLegacyPermissions();
+
+    /**
+     * @return legacy permission trees.
+     */
+    @NonNull
+    Map<String, LegacyPermission> getLegacyPermissionTrees();
+
+    /**
+     * @return legacy permissions state for a user.
+     */
+    @NonNull
+    Map<Integer, Map<String, LegacyPermissionState>> getLegacyPermissionStates(int userId);
+
+    /**
+     * @return permissions file version for the given user.
+     */
+    int getLegacyPermissionsVersion(int userId);
+
+    /**
+     * Legacy permission definition.
+     */
+    final class LegacyPermission {
+        private final PermissionInfo mPermissionInfo;
+        private final int mType;
+
+        LegacyPermission(PermissionInfo permissionInfo, int type) {
+            mPermissionInfo = permissionInfo;
+            mType = type;
+        }
+
+        @NonNull
+        public PermissionInfo getPermissionInfo() {
+            return mPermissionInfo;
+        }
+
+        public int getType() {
+            return mType;
+        }
+    }
+
+    /**
+     * State of a legacy permission.
+     */
+    final class LegacyPermissionState {
+        private final boolean mGranted;
+        private final int mFlags;
+
+        LegacyPermissionState(boolean granted, int flags) {
+            mGranted = granted;
+            mFlags = flags;
+        }
+
+        /**
+         * @return Whether the permission is granted or not.
+         */
+        public boolean isGranted() {
+            return mGranted;
+        }
+
+        /**
+         * @return Permission flags.
+         */
+        public int getFlags() {
+            return mFlags;
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/pm/permission/PermissionMigrationHelperImpl.java b/services/core/java/com/android/server/pm/permission/PermissionMigrationHelperImpl.java
new file mode 100644
index 0000000..2ae39b7
--- /dev/null
+++ b/services/core/java/com/android/server/pm/permission/PermissionMigrationHelperImpl.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.pm.permission;
+
+import android.annotation.NonNull;
+import android.content.pm.PackageManagerInternal;
+import android.util.ArrayMap;
+import android.util.Log;
+
+import com.android.permission.persistence.RuntimePermissionsState;
+import com.android.server.LocalManagerRegistry;
+import com.android.server.LocalServices;
+import com.android.server.pm.PackageManagerLocal;
+import com.android.server.pm.pkg.PackageState;
+import com.android.server.pm.pkg.SharedUserApi;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Provider of legacy permissions data for new permission subsystem.
+ *
+ * @hide
+ */
+public class PermissionMigrationHelperImpl implements PermissionMigrationHelper {
+    private static final String LOG_TAG = PermissionMigrationHelperImpl.class.getSimpleName();
+
+    /**
+     * @return legacy permission definitions.
+     */
+    @NonNull
+    public Map<String, LegacyPermission> getLegacyPermissions() {
+        PackageManagerInternal mPackageManagerInternal =
+                LocalServices.getService(PackageManagerInternal.class);
+        return toLegacyPermissions(
+                mPackageManagerInternal.getLegacyPermissions().getPermissions());
+    }
+
+    /**
+     * @return legacy permission trees.
+     */
+    @NonNull
+    public Map<String, LegacyPermission> getLegacyPermissionTrees() {
+        PackageManagerInternal mPackageManagerInternal =
+                LocalServices.getService(PackageManagerInternal.class);
+        return toLegacyPermissions(
+                mPackageManagerInternal.getLegacyPermissions().getPermissionTrees());
+    }
+
+    @NonNull
+    private Map<String, LegacyPermission> toLegacyPermissions(
+            List<com.android.server.pm.permission.LegacyPermission> legacyPermissions) {
+        Map<String, LegacyPermission> permissions = new ArrayMap<>();
+        legacyPermissions.forEach(legacyPermission -> {
+            LegacyPermission permission = new LegacyPermission(legacyPermission.getPermissionInfo(),
+                    legacyPermission.getType());
+            permissions.put(legacyPermission.getPermissionInfo().name, permission);
+        });
+
+        return permissions;
+    }
+
+    /**
+     * @return permissions state for a user, i.e. map of appId to map of permission name and state.
+     */
+    @NonNull
+    public Map<Integer, Map<String, LegacyPermissionState>> getLegacyPermissionStates(int userId) {
+        PackageManagerInternal mPackageManagerInternal =
+                LocalServices.getService(PackageManagerInternal.class);
+        Map<Integer, Map<String, LegacyPermissionState>> appIdPermissionStates = new ArrayMap<>();
+
+        RuntimePermissionsState legacyState =
+                mPackageManagerInternal.getLegacyPermissionsState(userId);
+        PackageManagerLocal packageManagerLocal =
+                LocalManagerRegistry.getManager(PackageManagerLocal.class);
+
+        try (PackageManagerLocal.UnfilteredSnapshot snapshot =
+                     packageManagerLocal.withUnfilteredSnapshot()) {
+            Map<String, PackageState> packageStates = snapshot.getPackageStates();
+            legacyState.getPackagePermissions().forEach((packageName, permissionStates) -> {
+                if (!permissionStates.isEmpty()) {
+                    PackageState packageState = packageStates.get(packageName);
+                    if (packageState != null) {
+                        int appId = packageState.getAppId();
+                        appIdPermissionStates.put(appId,
+                                toLegacyPermissionStates(permissionStates));
+                    } else {
+                        Log.w(LOG_TAG, "Package " + packageName + " not found.");
+                    }
+                }
+            });
+
+            Map<String, SharedUserApi> sharedUsers = snapshot.getSharedUsers();
+            legacyState.getSharedUserPermissions().forEach((sharedUserName, permissionStates) -> {
+                if (!permissionStates.isEmpty()) {
+                    SharedUserApi sharedUser = sharedUsers.get(sharedUserName);
+                    if (sharedUser != null) {
+                        int appId = sharedUser.getAppId();
+                        appIdPermissionStates.put(appId,
+                                toLegacyPermissionStates(permissionStates));
+                    } else {
+                        Log.w(LOG_TAG, "Shared user " + sharedUserName + " not found.");
+                    }
+                }
+            });
+        }
+        return appIdPermissionStates;
+    }
+
+    @Override
+    public int getLegacyPermissionsVersion(int userId) {
+        PackageManagerInternal packageManagerInternal =
+                LocalServices.getService(PackageManagerInternal.class);
+        return packageManagerInternal.getLegacyPermissionsVersion(userId);
+    }
+
+    @NonNull
+    private Map<String, LegacyPermissionState> toLegacyPermissionStates(
+            List<RuntimePermissionsState.PermissionState> permissions) {
+        Map<String, LegacyPermissionState> legacyPermissions = new ArrayMap<>();
+
+        final int size = permissions.size();
+        for (int i = 0; i < size; i++) {
+            RuntimePermissionsState.PermissionState permState = permissions.get(i);
+            legacyPermissions.put(permState.getName(), new LegacyPermissionState(
+                    permState.isGranted(), permState.getFlags()));
+        }
+
+        return legacyPermissions;
+    }
+}
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 8165958..adaad2a 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -68,6 +68,7 @@
 import static android.view.WindowManagerGlobal.ADD_PERMISSION_DENIED;
 
 import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.SCREENSHOT_KEYCHORD_DELAY;
+import static com.android.internal.util.FrameworkStatsLog.ACCESSIBILITY_SHORTCUT_REPORTED__SHORTCUT_TYPE__A11Y_WEAR_TRIPLE_PRESS_GESTURE;
 import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_COVERED;
 import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_COVER_ABSENT;
 import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_UNCOVERED;
@@ -190,6 +191,7 @@
 
 import com.android.internal.R;
 import com.android.internal.accessibility.AccessibilityShortcutController;
+import com.android.internal.accessibility.util.AccessibilityStatsLogUtils;
 import com.android.internal.accessibility.util.AccessibilityUtils;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.app.AssistUtils;
@@ -1408,7 +1410,18 @@
                 if (DEBUG_INPUT) {
                     Slog.d(TAG, "Executing stem primary triple press action behavior.");
                 }
-                toggleTalkBack();
+
+                if (Settings.System.getIntForUser(mContext.getContentResolver(),
+                        Settings.System.WEAR_ACCESSIBILITY_GESTURE_ENABLED,
+                        /* def= */ 0, UserHandle.USER_CURRENT) == 1) {
+                    /** Toggle talkback begin */
+                    ComponentName componentName = getTalkbackComponent();
+                    if (componentName != null && toggleTalkBack(componentName)) {
+                        /** log stem triple press telemetry if it's a talkback enabled event */
+                        logStemTriplePressAccessibilityTelemetry(componentName);
+                    }
+                    /** Toggle talkback end */
+                }
                 break;
         }
     }
@@ -1427,17 +1440,39 @@
         }
     }
 
-    private void toggleTalkBack() {
-        final ComponentName componentName = getTalkbackComponent();
-        if (componentName == null) {
-            return;
-        }
-
+    /**
+     * A function that toggles talkback service
+     *
+     * @return {@code true} if talkback is enabled, {@code false} if talkback is disabled
+     */
+    private boolean toggleTalkBack(ComponentName componentName) {
         final Set<ComponentName> enabledServices =
                 AccessibilityUtils.getEnabledServicesFromSettings(mContext, mCurrentUserId);
 
+        boolean isTalkbackAlreadyEnabled = enabledServices.contains(componentName);
         AccessibilityUtils.setAccessibilityServiceState(mContext, componentName,
-                !enabledServices.contains(componentName));
+                !isTalkbackAlreadyEnabled);
+        /** if isTalkbackAlreadyEnabled is true, then it's a disabled event so return false
+         * and if isTalkbackAlreadyEnabled is false, return true as it's an enabled event */
+        return !isTalkbackAlreadyEnabled;
+    }
+
+    /**
+     * A function that logs stem triple press accessibility telemetry
+     * If the user setup (Oobe) is not completed, set the
+     * WEAR_ACCESSIBILITY_GESTURE_ENABLED_DURING_OOBE
+     * setting which will be later logged via Settings Snapshot
+     * else, log ACCESSIBILITY_SHORTCUT_REPORTED atom
+     */
+    private void logStemTriplePressAccessibilityTelemetry(ComponentName componentName) {
+        if (!AccessibilityUtils.isUserSetupCompleted(mContext)) {
+            Settings.Secure.putInt(mContext.getContentResolver(),
+                    Settings.System.WEAR_ACCESSIBILITY_GESTURE_ENABLED_DURING_OOBE, 1);
+        } else {
+            AccessibilityStatsLogUtils.logAccessibilityShortcutActivated(mContext, componentName,
+                    ACCESSIBILITY_SHORTCUT_REPORTED__SHORTCUT_TYPE__A11Y_WEAR_TRIPLE_PRESS_GESTURE,
+                    /* serviceEnabled= */ true);
+        }
     }
 
     private ComponentName getTalkbackComponent() {
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index 2e8a150..ea494db 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -6644,6 +6644,13 @@
         }
     }
 
+    @VisibleForTesting
+    int getPowerGroupSize() {
+        synchronized (mLock) {
+            return mPowerGroups.size();
+        }
+    }
+
     @GoToSleepReason
     private int getLastSleepReasonInternal() {
         synchronized (mLock) {
diff --git a/services/core/java/com/android/server/power/ShutdownThread.java b/services/core/java/com/android/server/power/ShutdownThread.java
index c2d4ac6..a5ca7ac 100644
--- a/services/core/java/com/android/server/power/ShutdownThread.java
+++ b/services/core/java/com/android/server/power/ShutdownThread.java
@@ -30,7 +30,6 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.pm.PackageManagerInternal;
-import android.media.AudioAttributes;
 import android.os.Bundle;
 import android.os.FileUtils;
 import android.os.Handler;
@@ -44,6 +43,8 @@
 import android.os.Trace;
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.os.VibrationAttributes;
+import android.os.VibrationEffect;
 import android.os.Vibrator;
 import android.telephony.TelephonyManager;
 import android.util.ArrayMap;
@@ -101,11 +102,6 @@
     // static instance of this thread
     private static final ShutdownThread sInstance = new ShutdownThread();
 
-    private static final AudioAttributes VIBRATION_ATTRIBUTES = new AudioAttributes.Builder()
-            .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
-            .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
-            .build();
-
     // Metrics that will be reported to tron after reboot
     private static final ArrayMap<String, Long> TRON_METRICS = new ArrayMap<>();
 
@@ -703,7 +699,10 @@
             // vibrate before shutting down
             Vibrator vibrator = new SystemVibrator(context);
             try {
-                vibrator.vibrate(SHUTDOWN_VIBRATE_MS, VIBRATION_ATTRIBUTES);
+                vibrator.vibrate(
+                        VibrationEffect.createOneShot(
+                                SHUTDOWN_VIBRATE_MS, VibrationEffect.DEFAULT_AMPLITUDE),
+                        VibrationAttributes.createForUsage(VibrationAttributes.USAGE_TOUCH));
             } catch (Exception e) {
                 // Failure to vibrate shouldn't interrupt shutdown.  Just log it.
                 Log.w(TAG, "Failed to vibrate during shutdown.", e);
diff --git a/services/core/java/com/android/server/recoverysystem/RecoverySystemService.java b/services/core/java/com/android/server/recoverysystem/RecoverySystemService.java
index 9d5173a..86c4985 100644
--- a/services/core/java/com/android/server/recoverysystem/RecoverySystemService.java
+++ b/services/core/java/com/android/server/recoverysystem/RecoverySystemService.java
@@ -906,10 +906,11 @@
         return RESUME_ON_REBOOT_REBOOT_ERROR_UNSPECIFIED;
     }
 
+    @android.annotation.EnforcePermission(android.Manifest.permission.RECOVERY)
     @Override // Binder call for the legacy rebootWithLskf
     public @ResumeOnRebootRebootErrorCode int rebootWithLskfAssumeSlotSwitch(String packageName,
             String reason) {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.RECOVERY, null);
+        rebootWithLskfAssumeSlotSwitch_enforcePermission();
         return rebootWithLskfImpl(packageName, reason, true);
     }
 
@@ -970,9 +971,10 @@
         }
     }
 
+    @android.annotation.EnforcePermission(android.Manifest.permission.RECOVERY)
     @Override
     public boolean allocateSpaceForUpdate(String packageFile) {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.RECOVERY, null);
+        allocateSpaceForUpdate_enforcePermission();
         if (!isUpdatableApexSupported()) {
             Log.i(TAG, "Updatable Apex not supported, "
                     + "allocateSpaceForUpdate does nothing.");
diff --git a/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java b/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java
index 7beb1ed..e437be8 100644
--- a/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java
+++ b/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java
@@ -105,36 +105,46 @@
     @Override
     public int onHealthCheckFailed(@Nullable VersionedPackage failedPackage,
             @FailureReasons int failureReason, int mitigationCount) {
-        // For native crashes, we will roll back any available rollbacks
+        boolean anyRollbackAvailable = !mContext.getSystemService(RollbackManager.class)
+                .getAvailableRollbacks().isEmpty();
+        int impact = PackageHealthObserverImpact.USER_IMPACT_LEVEL_0;
+
         if (failureReason == PackageWatchdog.FAILURE_REASON_NATIVE_CRASH
-                && !mContext.getSystemService(RollbackManager.class)
-                .getAvailableRollbacks().isEmpty()) {
-            return PackageHealthObserverImpact.USER_IMPACT_MEDIUM;
-        }
-        if (getAvailableRollback(failedPackage) == null) {
-            // Don't handle the notification, no rollbacks available for the package
-            return PackageHealthObserverImpact.USER_IMPACT_NONE;
-        } else {
+                && anyRollbackAvailable) {
+            // For native crashes, we will directly roll back any available rollbacks
+            // Note: For non-native crashes the rollback-all step has higher impact
+            impact = PackageHealthObserverImpact.USER_IMPACT_LEVEL_30;
+        } else if (mitigationCount == 1 && getAvailableRollback(failedPackage) != null) {
             // Rollback is available, we may get a callback into #execute
-            return PackageHealthObserverImpact.USER_IMPACT_MEDIUM;
+            impact = PackageHealthObserverImpact.USER_IMPACT_LEVEL_30;
+        } else if (mitigationCount > 1 && anyRollbackAvailable) {
+            // If any rollbacks are available, we will commit them
+            impact = PackageHealthObserverImpact.USER_IMPACT_LEVEL_70;
         }
+
+        return impact;
     }
 
     @Override
     public boolean execute(@Nullable VersionedPackage failedPackage,
             @FailureReasons int rollbackReason, int mitigationCount) {
         if (rollbackReason == PackageWatchdog.FAILURE_REASON_NATIVE_CRASH) {
-            mHandler.post(() -> rollbackAll());
+            mHandler.post(() -> rollbackAll(rollbackReason));
             return true;
         }
 
-        RollbackInfo rollback = getAvailableRollback(failedPackage);
-        if (rollback == null) {
-            Slog.w(TAG, "Expected rollback but no valid rollback found for " + failedPackage);
-            return false;
+        if (mitigationCount == 1) {
+            RollbackInfo rollback = getAvailableRollback(failedPackage);
+            if (rollback == null) {
+                Slog.w(TAG, "Expected rollback but no valid rollback found for " + failedPackage);
+                return false;
+            }
+            mHandler.post(() -> rollbackPackage(rollback, failedPackage, rollbackReason));
+        } else if (mitigationCount > 1) {
+            mHandler.post(() -> rollbackAll(rollbackReason));
         }
-        mHandler.post(() -> rollbackPackage(rollback, failedPackage, rollbackReason));
-        // Assume rollback executed successfully
+
+        // Assume rollbacks executed successfully
         return true;
     }
 
@@ -468,7 +478,7 @@
     }
 
     @WorkerThread
-    private void rollbackAll() {
+    private void rollbackAll(@FailureReasons int rollbackReason) {
         assertInWorkerThread();
         RollbackManager rollbackManager = mContext.getSystemService(RollbackManager.class);
         List<RollbackInfo> rollbacks = rollbackManager.getAvailableRollbacks();
@@ -487,7 +497,7 @@
 
         for (RollbackInfo rollback : rollbacks) {
             VersionedPackage sample = rollback.getPackages().get(0).getVersionRolledBackFrom();
-            rollbackPackage(rollback, sample, PackageWatchdog.FAILURE_REASON_NATIVE_CRASH);
+            rollbackPackage(rollback, sample, rollbackReason);
         }
     }
 }
diff --git a/services/core/java/com/android/server/security/FileIntegrity.java b/services/core/java/com/android/server/security/FileIntegrity.java
index 7b87d99..b8f187e 100644
--- a/services/core/java/com/android/server/security/FileIntegrity.java
+++ b/services/core/java/com/android/server/security/FileIntegrity.java
@@ -16,6 +16,8 @@
 
 package com.android.server.security;
 
+import static android.os.ParcelFileDescriptor.MODE_READ_ONLY;
+
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
 import android.os.ParcelFileDescriptor;
@@ -36,18 +38,26 @@
     private FileIntegrity() {}
 
     /**
-     * Enables fs-verity, if supported by the filesystem.
+     * Enables fs-verity, if supported by the filesystem. This operation is atomic, i.e. it's either
+     * enabled or not, even in case of power failure during or after the call.
      * @see <a href="https://www.kernel.org/doc/html/latest/filesystems/fsverity.html">
+     *
      * @hide
      */
     @SystemApi(client = SystemApi.Client.SYSTEM_SERVER)
     public static void setUpFsVerity(@NonNull File file) throws IOException {
-        VerityUtils.setUpFsverity(file.getAbsolutePath());
+        try (ParcelFileDescriptor pfd = ParcelFileDescriptor.open(file, MODE_READ_ONLY)) {
+            setUpFsVerity(pfd);
+        }
     }
 
     /**
-     * Enables fs-verity, if supported by the filesystem.
+     * Enables fs-verity, if supported by the filesystem. This operation is atomic, i.e. it's either
+     * enabled or not, even in case of power failure during or after the call.
      * @see <a href="https://www.kernel.org/doc/html/latest/filesystems/fsverity.html">
+     *
+     * @param parcelFileDescriptor an FD opened in {@link ParcelFileDescriptor#MODE_READ_ONLY}.
+     *
      * @hide
      */
     @SystemApi(client = SystemApi.Client.SYSTEM_SERVER)
diff --git a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
index b2f48d9..fdc2822 100644
--- a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
+++ b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
@@ -171,6 +171,8 @@
 import android.util.SparseIntArray;
 import android.util.StatsEvent;
 import android.util.proto.ProtoOutputStream;
+import android.uwb.UwbActivityEnergyInfo;
+import android.uwb.UwbManager;
 import android.view.Display;
 
 import com.android.internal.annotations.GuardedBy;
@@ -346,6 +348,7 @@
     private StorageManager mStorageManager;
     private WifiManager mWifiManager;
     private TelephonyManager mTelephony;
+    private UwbManager mUwbManager;
     private SubscriptionManager mSubscriptionManager;
     private NetworkStatsManager mNetworkStatsManager;
 
@@ -415,6 +418,7 @@
     private final Object mWifiActivityInfoLock = new Object();
     private final Object mModemActivityInfoLock = new Object();
     private final Object mBluetoothActivityInfoLock = new Object();
+    private final Object mUwbActivityInfoLock = new Object();
     private final Object mSystemElapsedRealtimeLock = new Object();
     private final Object mSystemUptimeLock = new Object();
     private final Object mProcessMemoryStateLock = new Object();
@@ -537,6 +541,10 @@
                         synchronized (mBluetoothActivityInfoLock) {
                             return pullBluetoothActivityInfoLocked(atomTag, data);
                         }
+                    case FrameworkStatsLog.UWB_ACTIVITY_INFO:
+                        synchronized (mUwbActivityInfoLock) {
+                            return pullUwbActivityInfoLocked(atomTag, data);
+                        }
                     case FrameworkStatsLog.SYSTEM_ELAPSED_REALTIME:
                         synchronized (mSystemElapsedRealtimeLock) {
                             return pullSystemElapsedRealtimeLocked(atomTag, data);
@@ -777,8 +785,12 @@
                 registerEventListeners();
             });
         } else if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) {
-            // Network stats related pullers can only be initialized after service is ready.
-            BackgroundThread.getHandler().post(() -> initAndRegisterNetworkStatsPullers());
+            BackgroundThread.getHandler().post(() -> {
+                // Network stats related pullers can only be initialized after service is ready.
+                initAndRegisterNetworkStatsPullers();
+                // For services that are not ready at boot phase PHASE_SYSTEM_SERVICES_READY
+                initAndRegisterDeferredPullers();
+            });
         }
     }
 
@@ -989,6 +1001,12 @@
         registerOemManagedBytesTransfer();
     }
 
+    private void initAndRegisterDeferredPullers() {
+        mUwbManager = mContext.getSystemService(UwbManager.class);
+
+        registerUwbActivityInfo();
+    }
+
     private IThermalService getIThermalService() {
         synchronized (mThermalLock) {
             if (mThermalService == null) {
@@ -2151,6 +2169,46 @@
         return StatsManager.PULL_SUCCESS;
     }
 
+    private void registerUwbActivityInfo() {
+        int tagId = FrameworkStatsLog.UWB_ACTIVITY_INFO;
+        mStatsManager.setPullAtomCallback(
+                tagId,
+                null, // use default PullAtomMetadata values
+                DIRECT_EXECUTOR,
+                mStatsCallbackImpl
+        );
+    }
+
+    int pullUwbActivityInfoLocked(int atomTag, List<StatsEvent> pulledData) {
+        final long token = Binder.clearCallingIdentity();
+        try {
+            SynchronousResultReceiver uwbReceiver = new SynchronousResultReceiver("uwb");
+            mUwbManager.getUwbActivityEnergyInfoAsync(Runnable::run,
+                    info -> {
+                        Bundle bundle = new Bundle();
+                        bundle.putParcelable(BatteryStats.RESULT_RECEIVER_CONTROLLER_KEY, info);
+                        uwbReceiver.send(0, bundle);
+                }
+            );
+            final UwbActivityEnergyInfo uwbInfo = awaitControllerInfo(uwbReceiver);
+            if (uwbInfo == null) {
+                return StatsManager.PULL_SKIP;
+            }
+            pulledData.add(
+                    FrameworkStatsLog.buildStatsEvent(atomTag,
+                            uwbInfo.getControllerTxDurationMillis(),
+                            uwbInfo.getControllerRxDurationMillis(),
+                            uwbInfo.getControllerIdleDurationMillis(),
+                            uwbInfo.getControllerWakeCount()));
+        } catch (RuntimeException e) {
+            Slog.e(TAG, "failed to getUwbActivityEnergyInfoAsync", e);
+            return StatsManager.PULL_SKIP;
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
+        return StatsManager.PULL_SUCCESS;
+    }
+
     private void registerSystemElapsedRealtime() {
         int tagId = FrameworkStatsLog.SYSTEM_ELAPSED_REALTIME;
         PullAtomMetadata metadata = new PullAtomMetadata.Builder()
diff --git a/services/core/java/com/android/server/timedetector/NetworkTimeUpdateService.java b/services/core/java/com/android/server/timedetector/NetworkTimeUpdateService.java
index e7c073c..49dec05 100644
--- a/services/core/java/com/android/server/timedetector/NetworkTimeUpdateService.java
+++ b/services/core/java/com/android/server/timedetector/NetworkTimeUpdateService.java
@@ -21,13 +21,9 @@
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
 import android.app.AlarmManager;
-import android.app.PendingIntent;
 import android.app.time.UnixEpochTime;
-import android.content.BroadcastReceiver;
 import android.content.ContentResolver;
 import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
 import android.database.ContentObserver;
 import android.net.ConnectivityManager;
 import android.net.Network;
@@ -73,10 +69,6 @@
     private static final String TAG = "NetworkTimeUpdateService";
     private static final boolean DBG = false;
 
-    private static final String ACTION_POLL =
-            "com.android.server.timedetector.NetworkTimeUpdateService.action.POLL";
-    private static final int POLL_REQUEST = 0;
-
     private final Object mLock = new Object();
     private final Context mContext;
     private final ConnectivityManager mCM;
@@ -113,16 +105,19 @@
         AlarmManager alarmManager = mContext.getSystemService(AlarmManager.class);
         TimeDetectorInternal timeDetectorInternal =
                 LocalServices.getService(TimeDetectorInternal.class);
-        // Broadcast alarms sent by system are immutable
-        Intent pollIntent = new Intent(ACTION_POLL, null).setPackage("android");
-        PendingIntent pendingPollIntent = PendingIntent.getBroadcast(mContext, POLL_REQUEST,
-                pollIntent, PendingIntent.FLAG_IMMUTABLE);
         mRefreshCallbacks = new Engine.RefreshCallbacks() {
+            private final AlarmManager.OnAlarmListener mOnAlarmListener =
+                    new ScheduledRefreshAlarmListener();
+
             @Override
             public void scheduleNextRefresh(@ElapsedRealtimeLong long elapsedRealtimeMillis) {
-                alarmManager.cancel(pendingPollIntent);
+                alarmManager.cancel(mOnAlarmListener);
+
+                String alarmTag = "NetworkTimeUpdateService.POLL";
+                Handler handler = null; // Use the main thread
                 alarmManager.set(
-                        AlarmManager.ELAPSED_REALTIME, elapsedRealtimeMillis, pendingPollIntent);
+                        AlarmManager.ELAPSED_REALTIME, elapsedRealtimeMillis, alarmTag,
+                        mOnAlarmListener, handler);
             }
 
             @Override
@@ -138,10 +133,6 @@
 
     /** Initialize the receivers and initiate the first NTP request */
     public void systemRunning() {
-        // Listen for scheduled refreshes.
-        ScheduledRefreshBroadcastReceiver receiver = new ScheduledRefreshBroadcastReceiver();
-        mContext.registerReceiver(receiver, new IntentFilter(ACTION_POLL));
-
         // Listen for network connectivity changes.
         NetworkConnectivityCallback networkConnectivityCallback = new NetworkConnectivityCallback();
         mCM.registerDefaultNetworkCallback(networkConnectivityCallback, mHandler);
@@ -214,13 +205,13 @@
         }
     }
 
-    private class ScheduledRefreshBroadcastReceiver extends BroadcastReceiver implements Runnable {
+    private class ScheduledRefreshAlarmListener implements AlarmManager.OnAlarmListener, Runnable {
 
         @Override
-        public void onReceive(Context context, Intent intent) {
-            // The BroadcastReceiver has to complete quickly or an ANR will be triggered by the
+        public void onAlarm() {
+            // The OnAlarmListener has to complete quickly or an ANR will be triggered by the
             // platform regardless of the receiver thread used. Instead of blocking the receiver
-            // thread, the long-running / blocking work is posted to mHandler to allow onReceive()
+            // thread, the long-running / blocking work is posted to mHandler to allow onAlarm()
             // to return immediately.
             mHandler.post(this);
         }
@@ -424,8 +415,14 @@
             logToDebugAndDumpsys("forceRefreshForTests: refreshSuccessful=" + refreshSuccessful);
 
             if (refreshSuccessful) {
-                makeNetworkTimeSuggestion(mNtpTrustedTime.getCachedTimeResult(),
-                        "EngineImpl.forceRefreshForTests()", refreshCallbacks);
+                TimeResult cachedTimeResult = mNtpTrustedTime.getCachedTimeResult();
+                if (cachedTimeResult == null) {
+                    logToDebugAndDumpsys(
+                            "forceRefreshForTests: cachedTimeResult unexpectedly null");
+                } else {
+                    makeNetworkTimeSuggestion(cachedTimeResult,
+                            "EngineImpl.forceRefreshForTests()", refreshCallbacks);
+                }
             }
             return refreshSuccessful;
         }
diff --git a/services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneProviderController.java b/services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneProviderController.java
index ed7ea00..36658b2 100644
--- a/services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneProviderController.java
+++ b/services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneProviderController.java
@@ -303,8 +303,7 @@
     private void reportSuggestionEvent(
             @NonNull GeolocationTimeZoneSuggestion suggestion, @NonNull String reason) {
         LocationTimeZoneAlgorithmStatus algorithmStatus = generateCurrentAlgorithmStatus();
-        LocationAlgorithmEvent event = new LocationAlgorithmEvent(
-                algorithmStatus, suggestion);
+        LocationAlgorithmEvent event = new LocationAlgorithmEvent(algorithmStatus, suggestion);
         event.addDebugInfo(reason);
         reportEvent(event);
     }
@@ -728,20 +727,35 @@
         // Start the uncertainty timeout if needed to ensure the controller will eventually make an
         // uncertain suggestion if no success event arrives in time to counteract it.
         if (!mUncertaintyTimeoutQueue.hasQueued()) {
-            debugLog("Starting uncertainty timeout: reason=" + reason);
+            if (STATE_UNCERTAIN.equals(mState.get())) {
+                // If the controller is already uncertain, there's no reason to start a timeout;
+                // just forward the suggestion immediately to make it obvious in the logs what has
+                // happened. Making a new suggestion potentially captures new LTZP status info.
+                GeolocationTimeZoneSuggestion suggestion =
+                        GeolocationTimeZoneSuggestion.createUncertainSuggestion(
+                                uncertaintyStartedElapsedMillis);
+                String debugInfo = "Uncertainty received from " + provider.getName() + ":"
+                        + " primary=" + mPrimaryProvider
+                        + ", secondary=" + mSecondaryProvider
+                        + ", uncertaintyStarted="
+                        + Duration.ofMillis(uncertaintyStartedElapsedMillis);
+                reportSuggestionEvent(suggestion, debugInfo);
+            } else {
+                debugLog("Starting uncertainty timeout: reason=" + reason);
 
-            Duration uncertaintyDelay = mEnvironment.getUncertaintyDelay();
-            mUncertaintyTimeoutQueue.runDelayed(
-                    () -> onProviderUncertaintyTimeout(
-                            provider, uncertaintyStartedElapsedMillis, uncertaintyDelay),
-                    uncertaintyDelay.toMillis());
+                Duration uncertaintyDelay = mEnvironment.getUncertaintyDelay();
+                mUncertaintyTimeoutQueue.runDelayed(
+                        () -> onProviderUncertaintyTimeout(
+                                provider, uncertaintyStartedElapsedMillis, uncertaintyDelay),
+                        uncertaintyDelay.toMillis());
+            }
         }
 
         if (provider == mPrimaryProvider) {
             // (Try to) start the secondary. It could already be started, or enabling might not
             // succeed if the provider has previously reported it is perm failed. The uncertainty
-            // timeout (set above) is used to ensure that an uncertain suggestion will be made if
-            // the secondary cannot generate a success event in time.
+            // timeout (may be set above) is used to ensure that an uncertain suggestion will be
+            // made if the secondary cannot generate a success event in time.
             tryStartProvider(mSecondaryProvider, mCurrentUserConfiguration);
         }
     }
diff --git a/services/core/java/com/android/server/vibrator/VibratorManagerService.java b/services/core/java/com/android/server/vibrator/VibratorManagerService.java
index cb7e54d..350a55d 100644
--- a/services/core/java/com/android/server/vibrator/VibratorManagerService.java
+++ b/services/core/java/com/android/server/vibrator/VibratorManagerService.java
@@ -298,20 +298,18 @@
         return controller.isVibratorInfoLoadSuccessful() ? info : null;
     }
 
+    @android.annotation.EnforcePermission(android.Manifest.permission.ACCESS_VIBRATOR_STATE)
     @Override // Binder call
     public boolean isVibrating(int vibratorId) {
-        mContext.enforceCallingOrSelfPermission(
-                android.Manifest.permission.ACCESS_VIBRATOR_STATE,
-                "isVibrating");
+        isVibrating_enforcePermission();
         VibratorController controller = mVibrators.get(vibratorId);
         return controller != null && controller.isVibrating();
     }
 
+    @android.annotation.EnforcePermission(android.Manifest.permission.ACCESS_VIBRATOR_STATE)
     @Override // Binder call
     public boolean registerVibratorStateListener(int vibratorId, IVibratorStateListener listener) {
-        mContext.enforceCallingOrSelfPermission(
-                android.Manifest.permission.ACCESS_VIBRATOR_STATE,
-                "registerVibratorStateListener");
+        registerVibratorStateListener_enforcePermission();
         VibratorController controller = mVibrators.get(vibratorId);
         if (controller == null) {
             return false;
@@ -319,12 +317,11 @@
         return controller.registerVibratorStateListener(listener);
     }
 
+    @android.annotation.EnforcePermission(android.Manifest.permission.ACCESS_VIBRATOR_STATE)
     @Override // Binder call
     public boolean unregisterVibratorStateListener(int vibratorId,
             IVibratorStateListener listener) {
-        mContext.enforceCallingOrSelfPermission(
-                android.Manifest.permission.ACCESS_VIBRATOR_STATE,
-                "unregisterVibratorStateListener");
+        unregisterVibratorStateListener_enforcePermission();
         VibratorController controller = mVibrators.get(vibratorId);
         if (controller == null) {
             return false;
@@ -412,7 +409,7 @@
             if (attrs.isFlagSet(VibrationAttributes.FLAG_INVALIDATE_SETTINGS_CACHE)) {
                 // Force update of user settings before checking if this vibration effect should
                 // be ignored or scaled.
-                mVibrationSettings.mSettingObserver.onChange(false);
+                mVibrationSettings.update();
             }
 
             synchronized (mLock) {
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index d4f151f..ea2765d 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -104,7 +104,6 @@
 import android.app.WaitResult;
 import android.app.WindowConfiguration;
 import android.compat.annotation.ChangeId;
-import android.compat.annotation.Disabled;
 import android.compat.annotation.EnabledSince;
 import android.content.IIntentSender;
 import android.content.Intent;
@@ -189,7 +188,7 @@
      * Feature flag for go/activity-security rules
      */
     @ChangeId
-    @Disabled
+    @EnabledSince(targetSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
     static final long ASM_RESTRICTIONS = 230590090L;
 
     private final ActivityTaskManagerService mService;
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 12fe6a0..d2fc393 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -5376,7 +5376,7 @@
             if (app != null && app.getPid() > 0) {
                 ArrayList<Integer> firstPids = new ArrayList<Integer>();
                 firstPids.add(app.getPid());
-                dumpStackTraces(tracesFile.getAbsolutePath(), firstPids, null, null, null);
+                dumpStackTraces(tracesFile.getAbsolutePath(), firstPids, null, null, null, null);
             }
 
             File lastTracesFile = null;
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index dde87b1..2156c6d 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -413,7 +413,7 @@
     private static final String DENSITY_OVERRIDE = "ro.config.density_override";
     private static final String SIZE_OVERRIDE = "ro.config.size_override";
 
-    private static final String PROPERTY_EMULATOR_CIRCULAR = "ro.emulator.circular";
+    private static final String PROPERTY_EMULATOR_CIRCULAR = "ro.boot.emulator.circular";
 
     static final int MY_PID = myPid();
     static final int MY_UID = myUid();
@@ -3217,15 +3217,13 @@
         }
     }
 
+    @android.annotation.EnforcePermission(android.Manifest.permission.DISABLE_KEYGUARD)
     /**
      * @see android.app.KeyguardManager#exitKeyguardSecurely
      */
     @Override
     public void exitKeyguardSecurely(final IOnKeyguardExitResult callback) {
-        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
-            != PackageManager.PERMISSION_GRANTED) {
-            throw new SecurityException("Requires DISABLE_KEYGUARD permission");
-        }
+        exitKeyguardSecurely_enforcePermission();
 
         if (callback == null) {
             throw new IllegalArgumentException("callback == null");
@@ -4382,13 +4380,11 @@
         }
     }
 
+    @android.annotation.EnforcePermission(android.Manifest.permission.MANAGE_APP_TOKENS)
     @Override
     public SurfaceControl addShellRoot(int displayId, IWindow client,
             @WindowManager.ShellRootLayer int shellRootLayer) {
-        if (mContext.checkCallingOrSelfPermission(MANAGE_APP_TOKENS)
-                != PackageManager.PERMISSION_GRANTED) {
-            throw new SecurityException("Must hold permission " + MANAGE_APP_TOKENS);
-        }
+        addShellRoot_enforcePermission();
         final long origId = Binder.clearCallingIdentity();
         try {
             synchronized (mGlobalLock) {
@@ -4403,13 +4399,11 @@
         }
     }
 
+    @android.annotation.EnforcePermission(android.Manifest.permission.MANAGE_APP_TOKENS)
     @Override
     public void setShellRootAccessibilityWindow(int displayId,
             @WindowManager.ShellRootLayer int shellRootLayer, IWindow target) {
-        if (mContext.checkCallingOrSelfPermission(MANAGE_APP_TOKENS)
-                != PackageManager.PERMISSION_GRANTED) {
-            throw new SecurityException("Must hold permission " + MANAGE_APP_TOKENS);
-        }
+        setShellRootAccessibilityWindow_enforcePermission();
         final long origId = Binder.clearCallingIdentity();
         try {
             synchronized (mGlobalLock) {
@@ -4428,13 +4422,11 @@
         }
     }
 
+    @android.annotation.EnforcePermission(android.Manifest.permission.MANAGE_APP_TOKENS)
     @Override
     public void setDisplayWindowInsetsController(
             int displayId, IDisplayWindowInsetsController insetsController) {
-        if (mContext.checkCallingOrSelfPermission(MANAGE_APP_TOKENS)
-                != PackageManager.PERMISSION_GRANTED) {
-            throw new SecurityException("Must hold permission " + MANAGE_APP_TOKENS);
-        }
+        setDisplayWindowInsetsController_enforcePermission();
         final long origId = Binder.clearCallingIdentity();
         try {
             synchronized (mGlobalLock) {
@@ -4449,13 +4441,11 @@
         }
     }
 
+    @android.annotation.EnforcePermission(android.Manifest.permission.MANAGE_APP_TOKENS)
     @Override
     public void updateDisplayWindowRequestedVisibleTypes(
             int displayId, @InsetsType int requestedVisibleTypes) {
-        if (mContext.checkCallingOrSelfPermission(MANAGE_APP_TOKENS)
-                != PackageManager.PERMISSION_GRANTED) {
-            throw new SecurityException("Must hold permission " + MANAGE_APP_TOKENS);
-        }
+        updateDisplayWindowRequestedVisibleTypes_enforcePermission();
         final long origId = Binder.clearCallingIdentity();
         try {
             synchronized (mGlobalLock) {
@@ -5664,12 +5654,10 @@
         }
     }
 
+    @android.annotation.EnforcePermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
     @Override
     public void setForcedDisplaySize(int displayId, int width, int height) {
-        if (mContext.checkCallingOrSelfPermission(WRITE_SECURE_SETTINGS)
-                != PackageManager.PERMISSION_GRANTED) {
-            throw new SecurityException("Must hold permission " + WRITE_SECURE_SETTINGS);
-        }
+        setForcedDisplaySize_enforcePermission();
 
         final long ident = Binder.clearCallingIdentity();
         try {
@@ -5684,12 +5672,10 @@
         }
     }
 
+    @android.annotation.EnforcePermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
     @Override
     public void setForcedDisplayScalingMode(int displayId, int mode) {
-        if (mContext.checkCallingOrSelfPermission(WRITE_SECURE_SETTINGS)
-                != PackageManager.PERMISSION_GRANTED) {
-            throw new SecurityException("Must hold permission " + WRITE_SECURE_SETTINGS);
-        }
+        setForcedDisplayScalingMode_enforcePermission();
 
         final long ident = Binder.clearCallingIdentity();
         try {
@@ -5772,12 +5758,10 @@
         return changed;
     }
 
+    @android.annotation.EnforcePermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
     @Override
     public void clearForcedDisplaySize(int displayId) {
-        if (mContext.checkCallingOrSelfPermission(WRITE_SECURE_SETTINGS)
-                != PackageManager.PERMISSION_GRANTED) {
-            throw new SecurityException("Must hold permission " + WRITE_SECURE_SETTINGS);
-        }
+        clearForcedDisplaySize_enforcePermission();
 
         final long ident = Binder.clearCallingIdentity();
         try {
@@ -5837,12 +5821,10 @@
         return -1;
     }
 
+    @android.annotation.EnforcePermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
     @Override
     public void setForcedDisplayDensityForUser(int displayId, int density, int userId) {
-        if (mContext.checkCallingOrSelfPermission(WRITE_SECURE_SETTINGS)
-                != PackageManager.PERMISSION_GRANTED) {
-            throw new SecurityException("Must hold permission " + WRITE_SECURE_SETTINGS);
-        }
+        setForcedDisplayDensityForUser_enforcePermission();
 
         final int targetUserId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
                 Binder.getCallingUid(), userId, false, true, "setForcedDisplayDensityForUser",
@@ -5865,12 +5847,10 @@
         }
     }
 
+    @android.annotation.EnforcePermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
     @Override
     public void clearForcedDisplayDensityForUser(int displayId, int userId) {
-        if (mContext.checkCallingOrSelfPermission(WRITE_SECURE_SETTINGS)
-                != PackageManager.PERMISSION_GRANTED) {
-            throw new SecurityException("Must hold permission " + WRITE_SECURE_SETTINGS);
-        }
+        clearForcedDisplayDensityForUser_enforcePermission();
 
         final int callingUserId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
                 Binder.getCallingUid(), userId, false, true, "clearForcedDisplayDensityForUser",
@@ -6365,12 +6345,9 @@
         }
     }
 
+    @android.annotation.EnforcePermission(android.Manifest.permission.STATUS_BAR)
     public void setNavBarVirtualKeyHapticFeedbackEnabled(boolean enabled) {
-        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR)
-                != PackageManager.PERMISSION_GRANTED) {
-            throw new SecurityException("Caller does not hold permission "
-                    + android.Manifest.permission.STATUS_BAR);
-        }
+        setNavBarVirtualKeyHapticFeedbackEnabled_enforcePermission();
 
         synchronized (mGlobalLock) {
             mPolicy.setNavBarVirtualKeyHapticFeedbackEnabledLw(enabled);
@@ -6410,11 +6387,10 @@
         }
     }
 
+    @android.annotation.EnforcePermission(android.Manifest.permission.RESTRICTED_VR_ACCESS)
     @Override
     public Region getCurrentImeTouchRegion() {
-        if (mContext.checkCallingOrSelfPermission(RESTRICTED_VR_ACCESS) != PERMISSION_GRANTED) {
-            throw new SecurityException("getCurrentImeTouchRegion is restricted to VR services");
-        }
+        getCurrentImeTouchRegion_enforcePermission();
         synchronized (mGlobalLock) {
             final Region r = new Region();
             // TODO(b/111080190): this method is only return the recent focused IME touch region,
diff --git a/services/core/java/com/android/server/wm/WindowOrganizerController.java b/services/core/java/com/android/server/wm/WindowOrganizerController.java
index 32d54d7..3f39e47 100644
--- a/services/core/java/com/android/server/wm/WindowOrganizerController.java
+++ b/services/core/java/com/android/server/wm/WindowOrganizerController.java
@@ -18,7 +18,7 @@
 
 import static android.Manifest.permission.START_TASKS_FROM_RECENTS;
 import static android.app.ActivityManager.isStartResultSuccessful;
-import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
 import static android.app.WindowConfiguration.WINDOW_CONFIG_BOUNDS;
 import static android.view.Display.DEFAULT_DISPLAY;
 import static android.window.TaskFragmentOperation.OP_TYPE_CLEAR_ADJACENT_TASK_FRAGMENTS;
@@ -553,9 +553,9 @@
                 // setWindowingMode call in force-hidden.
                 boolean forceHiddenForPip = false;
                 if (wc.asTask() != null && wc.inPinnedWindowingMode()
-                        && entry.getValue().getWindowingMode() == WINDOWING_MODE_UNDEFINED) {
-                    // We are in pip and going to undefined. Now search hierarchy ops to determine
-                    // whether we are removing pip or expanding pip.
+                        && entry.getValue().getWindowingMode() != WINDOWING_MODE_PINNED) {
+                    // We are going out of pip. Now search hierarchy ops to determine whether we
+                    // are removing pip or expanding pip.
                     for (int i = 0; i < hopSize; ++i) {
                         final WindowContainerTransaction.HierarchyOp hop = hops.get(i);
                         if (hop.getType() != HIERARCHY_OP_TYPE_REORDER) continue;
@@ -692,7 +692,7 @@
                 return effects;
             }
 
-            if (windowingMode == WindowConfiguration.WINDOWING_MODE_PINNED) {
+            if (windowingMode == WINDOWING_MODE_PINNED) {
                 // Do not directly put the container into PINNED mode as it may not support it or
                 // the app may not want to enter it. Instead, send a signal to request PIP
                 // mode to the app if they wish to support it below in #applyTaskChanges.
@@ -745,7 +745,7 @@
             tr.mDisplayContent.mPinnedTaskController.setEnterPipBounds(enterPipBounds);
         }
 
-        if (c.getWindowingMode() == WindowConfiguration.WINDOWING_MODE_PINNED
+        if (c.getWindowingMode() == WINDOWING_MODE_PINNED
                 && !tr.inPinnedWindowingMode()) {
             final ActivityRecord activity = tr.getTopNonFinishingActivity();
             if (activity != null) {
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 770e728..f01b0eb 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -16597,9 +16597,6 @@
         if (!mUserManager.isUserRunning(new UserHandle(deviceOwnerUserId))) {
             return STATUS_USER_NOT_RUNNING;
         }
-        if (mIsWatch && hasPaired(UserHandle.USER_SYSTEM)) {
-            return STATUS_HAS_PAIRED;
-        }
 
         boolean isHeadlessSystemUserMode = mInjector.userManagerIsHeadlessSystemUserMode();
 
@@ -16623,7 +16620,7 @@
 
         if (isAdb) {
             // If shell command runs after user setup completed check device status. Otherwise, OK.
-            if (mIsWatch || hasUserSetupCompleted(UserHandle.USER_SYSTEM)) {
+            if (hasUserSetupCompleted(UserHandle.USER_SYSTEM)) {
                 // DO can be setup only if there are no users which are neither created by default
                 // nor marked as FOR_TESTING
 
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 492d477..dbff90a 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -108,6 +108,8 @@
 import com.android.server.am.ActivityManagerService;
 import com.android.server.ambientcontext.AmbientContextManagerService;
 import com.android.server.appbinding.AppBindingService;
+import com.android.server.appop.AppOpMigrationHelper;
+import com.android.server.appop.AppOpMigrationHelperImpl;
 import com.android.server.art.ArtModuleServiceInitializer;
 import com.android.server.art.DexUseManagerLocal;
 import com.android.server.attention.AttentionManagerService;
@@ -173,6 +175,8 @@
 import com.android.server.pm.ShortcutService;
 import com.android.server.pm.UserManagerService;
 import com.android.server.pm.dex.OdsignStatsLogger;
+import com.android.server.pm.permission.PermissionMigrationHelper;
+import com.android.server.pm.permission.PermissionMigrationHelperImpl;
 import com.android.server.pm.verify.domain.DomainVerificationService;
 import com.android.server.policy.AppOpsPolicy;
 import com.android.server.policy.PermissionPolicyService;
@@ -1132,6 +1136,10 @@
 
         // Start AccessCheckingService which provides new implementation for permission and app op.
         t.traceBegin("StartAccessCheckingService");
+        LocalServices.addService(PermissionMigrationHelper.class,
+                new PermissionMigrationHelperImpl());
+        LocalServices.addService(AppOpMigrationHelper.class,
+                new AppOpMigrationHelperImpl());
         mSystemServiceManager.startService(AccessCheckingService.class);
         t.traceEnd();
 
diff --git a/services/permission/java/com/android/server/permission/access/AccessPersistence.kt b/services/permission/java/com/android/server/permission/access/AccessPersistence.kt
index a25b720..4182ecf 100644
--- a/services/permission/java/com/android/server/permission/access/AccessPersistence.kt
+++ b/services/permission/java/com/android/server/permission/access/AccessPersistence.kt
@@ -30,9 +30,9 @@
 import com.android.server.permission.access.collection.* // ktlint-disable no-wildcard-imports
 import com.android.server.permission.access.util.PermissionApex
 import com.android.server.permission.access.util.parseBinaryXml
-import com.android.server.permission.access.util.read
+import com.android.server.permission.access.util.readWithReserveCopy
 import com.android.server.permission.access.util.serializeBinaryXml
-import com.android.server.permission.access.util.writeInlined
+import com.android.server.permission.access.util.writeWithReserveCopy
 import java.io.File
 import java.io.FileNotFoundException
 
@@ -53,6 +53,9 @@
         writeHandler = WriteHandler(BackgroundThread.getHandler().looper)
     }
 
+    /**
+     * Reads the state either from the disk or migrate legacy data when the data files are missing.
+     */
     fun read(state: AccessState) {
         readSystemState(state)
         state.systemState.userIds.forEachIndexed { _, userId ->
@@ -61,28 +64,50 @@
     }
 
     private fun readSystemState(state: AccessState) {
-        systemFile.parse {
+        val fileExists = systemFile.parse {
             // This is the canonical way to call an extension function in a different class.
             // TODO(b/259469752): Use context receiver for this when it becomes stable.
             with(policy) { parseSystemState(state) }
         }
-    }
 
-    private fun readUserState(state: AccessState, userId: Int) {
-        getUserFile(userId).parse {
-            with(policy) { parseUserState(state, userId) }
+        if (!fileExists) {
+            policy.migrateSystemState(state)
+            state.systemState.apply {
+                requestWrite()
+                write(state, UserHandle.USER_ALL)
+            }
         }
     }
 
-    private inline fun File.parse(block: BinaryXmlPullParser.() -> Unit) {
+
+    private fun readUserState(state: AccessState, userId: Int) {
+        val fileExists = getUserFile(userId).parse {
+            with(policy) { parseUserState(state, userId) }
+        }
+
+        if (!fileExists) {
+            policy.migrateUserState(state, userId)
+            state.userStates[userId].apply {
+                requestWrite()
+                write(state, userId)
+            }
+        }
+    }
+
+    /**
+     * @return {@code true} if the file is successfully read from the disk; {@code false} if
+     * the file doesn't exist yet.
+     */
+    private inline fun File.parse(block: BinaryXmlPullParser.() -> Unit): Boolean =
         try {
-            AtomicFile(this).read { it.parseBinaryXml(block) }
+            AtomicFile(this).readWithReserveCopy { it.parseBinaryXml(block) }
+            true
         } catch (e: FileNotFoundException) {
             Log.i(LOG_TAG, "$this not found")
+            false
         } catch (e: Exception) {
             throw IllegalStateException("Failed to read $this", e)
         }
-    }
 
     fun write(state: AccessState) {
         state.systemState.write(state, UserHandle.USER_ALL)
@@ -154,7 +179,7 @@
 
     private inline fun File.serialize(block: BinaryXmlSerializer.() -> Unit) {
         try {
-            AtomicFile(this).writeInlined { it.serializeBinaryXml(block) }
+            AtomicFile(this).writeWithReserveCopy { it.serializeBinaryXml(block) }
         } catch (e: Exception) {
             Log.e(LOG_TAG, "Failed to serialize $this", e)
         }
diff --git a/services/permission/java/com/android/server/permission/access/AccessPolicy.kt b/services/permission/java/com/android/server/permission/access/AccessPolicy.kt
index 07a5e72..7e106b0 100644
--- a/services/permission/java/com/android/server/permission/access/AccessPolicy.kt
+++ b/services/permission/java/com/android/server/permission/access/AccessPolicy.kt
@@ -20,11 +20,15 @@
 import com.android.modules.utils.BinaryXmlPullParser
 import com.android.modules.utils.BinaryXmlSerializer
 import com.android.server.SystemConfig
+import com.android.server.permission.access.appop.AppIdAppOpPolicy
 import com.android.server.permission.access.appop.PackageAppOpPolicy
-import com.android.server.permission.access.appop.UidAppOpPolicy
 import com.android.server.permission.access.collection.* // ktlint-disable no-wildcard-imports
-import com.android.server.permission.access.permission.UidPermissionPolicy
+import com.android.server.permission.access.permission.AppIdPermissionPolicy
+import com.android.server.permission.access.util.attributeInt
+import com.android.server.permission.access.util.attributeInterned
 import com.android.server.permission.access.util.forEachTag
+import com.android.server.permission.access.util.getAttributeIntOrThrow
+import com.android.server.permission.access.util.getAttributeValueOrThrow
 import com.android.server.permission.access.util.tag
 import com.android.server.permission.access.util.tagName
 import com.android.server.pm.permission.PermissionAllowlist
@@ -37,8 +41,8 @@
         IndexedMap<String, IndexedMap<String, SchemePolicy>>().apply {
             fun addPolicy(policy: SchemePolicy) =
                 getOrPut(policy.subjectScheme) { IndexedMap() }.put(policy.objectScheme, policy)
-            addPolicy(UidPermissionPolicy())
-            addPolicy(UidAppOpPolicy())
+            addPolicy(AppIdPermissionPolicy())
+            addPolicy(AppIdAppOpPolicy())
             addPolicy(PackageAppOpPolicy())
         }
     )
@@ -49,7 +53,7 @@
         }
 
     fun GetStateScope.getDecision(subject: AccessUri, `object`: AccessUri): Int =
-        with(getSchemePolicy(subject, `object`)){ getDecision(subject, `object`) }
+        with(getSchemePolicy(subject, `object`)) { getDecision(subject, `object`) }
 
     fun MutateStateScope.setDecision(subject: AccessUri, `object`: AccessUri, decision: Int) {
         with(getSchemePolicy(subject, `object`)) { setDecision(subject, `object`, decision) }
@@ -107,6 +111,9 @@
         forEachSchemePolicy {
             with(it) { onUserAdded(userId) }
         }
+        newState.systemState.packageStates.forEach { (_, packageState) ->
+            upgradePackageVersion(packageState, userId)
+        }
     }
 
     fun MutateStateScope.onUserRemoved(userId: Int) {
@@ -147,6 +154,13 @@
         forEachSchemePolicy {
             with(it) { onStorageVolumeMounted(volumeUuid, isSystemUpdated) }
         }
+        packageStates.forEach { (_, packageState) ->
+            if (packageState.volumeUuid == volumeUuid) {
+                newState.systemState.userIds.forEachIndexed { _, userId ->
+                    upgradePackageVersion(packageState, userId)
+                }
+            }
+        }
     }
 
     fun MutateStateScope.onPackageAdded(
@@ -179,6 +193,9 @@
         forEachSchemePolicy {
             with(it) { onPackageAdded(packageState) }
         }
+        newState.systemState.userIds.forEachIndexed { _, userId ->
+            upgradePackageVersion(packageState, userId)
+        }
     }
 
     fun MutateStateScope.onPackageRemoved(
@@ -213,6 +230,10 @@
                 with(it) { onAppIdRemoved(appId) }
             }
         }
+        newState.userStates.forEachIndexed { _, _, userState ->
+            userState.packageVersions -= packageName
+            userState.requestWrite()
+        }
     }
 
     fun MutateStateScope.onPackageInstalled(
@@ -262,6 +283,51 @@
         }
     }
 
+    fun migrateSystemState(state: AccessState) {
+        forEachSchemePolicy {
+            with(it) { migrateSystemState(state) }
+        }
+    }
+
+    fun migrateUserState(state: AccessState, userId: Int) {
+        forEachSchemePolicy {
+            with(it) { migrateUserState(state, userId) }
+        }
+    }
+
+    private fun MutateStateScope.upgradePackageVersion(packageState: PackageState, userId: Int) {
+        if (packageState.androidPackage == null) {
+            return
+        }
+
+        val packageName = packageState.packageName
+        // The version would be latest when the package is new to the system, e.g. newly
+        // installed, first boot, or system apps added via OTA.
+        val version = newState.userStates[userId].packageVersions[packageName]
+        when {
+            version == null -> {
+                newState.userStates[userId].apply {
+                    packageVersions[packageName] = VERSION_LATEST
+                    requestWrite()
+                }
+            }
+            version < VERSION_LATEST -> {
+                forEachSchemePolicy {
+                    with(it) { upgradePackageState(packageState, userId, version) }
+                }
+                newState.userStates[userId].apply {
+                    packageVersions[packageName] = VERSION_LATEST
+                    requestWrite()
+                }
+            }
+            version == VERSION_LATEST -> {}
+            else -> Log.w(
+                LOG_TAG, "Unexpected version $version for package $packageName," +
+                    "latest version is $VERSION_LATEST"
+            )
+        }
+    }
+
     fun BinaryXmlPullParser.parseSystemState(state: AccessState) {
         forEachTag {
             when (tagName) {
@@ -290,8 +356,13 @@
             when (tagName) {
                 TAG_ACCESS -> {
                     forEachTag {
-                        forEachSchemePolicy {
-                            with(it) { parseUserState(state, userId) }
+                        when (tagName) {
+                            TAG_PACKAGE_VERSIONS -> parsePackageVersions(state, userId)
+                            else -> {
+                                forEachSchemePolicy {
+                                    with(it) { parseUserState(state, userId) }
+                                }
+                            }
                         }
                     }
                 }
@@ -305,11 +376,53 @@
         }
     }
 
+    private fun BinaryXmlPullParser.parsePackageVersions(state: AccessState, userId: Int) {
+        val userState = state.userStates[userId]
+        forEachTag {
+            when (tagName) {
+                TAG_PACKAGE -> parsePackageVersion(userState)
+                else -> Log.w(
+                    LOG_TAG,
+                    "Ignoring unknown tag $name when parsing package versions for user $userId"
+                )
+            }
+        }
+        userState.packageVersions.retainAllIndexed { _, packageName, _ ->
+            val hasPackage = packageName in state.systemState.packageStates
+            if (!hasPackage) {
+                Log.w(
+                    LOG_TAG,
+                    "Dropping unknown $packageName when parsing package versions for user $userId"
+                )
+            }
+            hasPackage
+        }
+    }
+
+    private fun BinaryXmlPullParser.parsePackageVersion(userState: UserState) {
+        val packageName = getAttributeValueOrThrow(ATTR_NAME).intern()
+        val version = getAttributeIntOrThrow(ATTR_VERSION)
+        userState.packageVersions[packageName] = version
+    }
+
     fun BinaryXmlSerializer.serializeUserState(state: AccessState, userId: Int) {
         tag(TAG_ACCESS) {
             forEachSchemePolicy {
                 with(it) { serializeUserState(state, userId) }
             }
+
+            serializeVersions(state.userStates[userId])
+        }
+    }
+
+    private fun BinaryXmlSerializer.serializeVersions(userState: UserState) {
+        tag(TAG_PACKAGE_VERSIONS) {
+            userState.packageVersions.forEachIndexed { _, packageName, version ->
+                tag(TAG_PACKAGE) {
+                    attributeInterned(ATTR_NAME, packageName)
+                    attributeInt(ATTR_VERSION, version)
+                }
+            }
         }
     }
 
@@ -327,7 +440,14 @@
     companion object {
         private val LOG_TAG = AccessPolicy::class.java.simpleName
 
+        internal const val VERSION_LATEST = 14
+
         private const val TAG_ACCESS = "access"
+        private const val TAG_PACKAGE_VERSIONS = "package-versions"
+        private const val TAG_PACKAGE = "package"
+
+        private const val ATTR_NAME = "name"
+        private const val ATTR_VERSION = "version"
     }
 }
 
@@ -371,6 +491,16 @@
 
     open fun MutateStateScope.onSystemReady() {}
 
+    open fun migrateSystemState(state: AccessState) {}
+
+    open fun migrateUserState(state: AccessState, userId: Int) {}
+
+    open fun MutateStateScope.upgradePackageState(
+        packageState: PackageState,
+        userId: Int,
+        version: Int
+    ) {}
+
     open fun BinaryXmlPullParser.parseSystemState(state: AccessState) {}
 
     open fun BinaryXmlSerializer.serializeSystemState(state: AccessState) {}
diff --git a/services/permission/java/com/android/server/permission/access/AccessState.kt b/services/permission/java/com/android/server/permission/access/AccessState.kt
index 5532311..ea5411b 100644
--- a/services/permission/java/com/android/server/permission/access/AccessState.kt
+++ b/services/permission/java/com/android/server/permission/access/AccessState.kt
@@ -97,23 +97,27 @@
 }
 
 class UserState private constructor(
+    // packageName -> version, this version is used permissions/app-ops states upgrade.
+    val packageVersions: IndexedMap<String, Int>,
     // A map of (appId to a map of (permissionName to permissionFlags))
-    val uidPermissionFlags: IntMap<IndexedMap<String, Int>>,
+    val appIdPermissionFlags: IntMap<IndexedMap<String, Int>>,
     // appId -> opName -> opCode
-    val uidAppOpModes: IntMap<IndexedMap<String, Int>>,
+    val appIdAppOpModes: IntMap<IndexedMap<String, Int>>,
     // packageName -> opName -> opCode
-    val packageAppOpModes: IndexedMap<String, IndexedMap<String, Int>>
+    val packageAppOpModes: IndexedMap<String, IndexedMap<String, Int>>,
 ) : WritableState() {
     constructor() : this(
+        IndexedMap(),
         IntMap(),
         IntMap(),
-        IndexedMap()
+        IndexedMap(),
     )
 
     fun copy(): UserState = UserState(
-        uidPermissionFlags.copy { it.copy { it } },
-        uidAppOpModes.copy { it.copy { it } },
-        packageAppOpModes.copy { it.copy { it } }
+        packageVersions.copy { it },
+        appIdPermissionFlags.copy { it.copy { it } },
+        appIdAppOpModes.copy { it.copy { it } },
+        packageAppOpModes.copy { it.copy { it } },
     )
 }
 
diff --git a/services/permission/java/com/android/server/permission/access/appop/AppIdAppOpMigration.kt b/services/permission/java/com/android/server/permission/access/appop/AppIdAppOpMigration.kt
new file mode 100644
index 0000000..71e4f2a
--- /dev/null
+++ b/services/permission/java/com/android/server/permission/access/appop/AppIdAppOpMigration.kt
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.permission.access.appop
+
+import com.android.server.LocalServices
+import com.android.server.appop.AppOpMigrationHelper
+import com.android.server.permission.access.AccessState
+import com.android.server.permission.access.collection.* // ktlint-disable no-wildcard-imports
+import com.android.server.permission.access.util.PackageVersionMigration
+
+class AppIdAppOpMigration {
+    fun migrateUserState(state: AccessState, userId: Int) {
+        val legacyAppOpsManager = LocalServices.getService(AppOpMigrationHelper::class.java)!!
+        val legacyAppIdAppOpModes = legacyAppOpsManager.getLegacyAppIdAppOpModes(userId)
+        val appIdAppOpModes = state.userStates[userId].appIdAppOpModes
+        val version = PackageVersionMigration.getVersion(userId)
+        legacyAppIdAppOpModes.forEach { (appId, legacyAppOpModes) ->
+            val appOpModes = appIdAppOpModes.getOrPut(appId) { IndexedMap() }
+            legacyAppOpModes.forEach { (appOpName, appOpMode) ->
+                appOpModes[appOpName] = appOpMode
+            }
+
+            state.systemState.appIds[appId].forEachIndexed { _, packageName ->
+                state.userStates[userId].packageVersions[packageName] = version
+            }
+        }
+    }
+}
diff --git a/services/permission/java/com/android/server/permission/access/appop/UidAppOpPersistence.kt b/services/permission/java/com/android/server/permission/access/appop/AppIdAppOpPersistence.kt
similarity index 79%
rename from services/permission/java/com/android/server/permission/access/appop/UidAppOpPersistence.kt
rename to services/permission/java/com/android/server/permission/access/appop/AppIdAppOpPersistence.kt
index 7a965d4..c29f30c8 100644
--- a/services/permission/java/com/android/server/permission/access/appop/UidAppOpPersistence.kt
+++ b/services/permission/java/com/android/server/permission/access/appop/AppIdAppOpPersistence.kt
@@ -28,15 +28,15 @@
 import com.android.server.permission.access.util.tag
 import com.android.server.permission.access.util.tagName
 
-class UidAppOpPersistence : BaseAppOpPersistence() {
+class AppIdAppOpPersistence : BaseAppOpPersistence() {
     override fun BinaryXmlPullParser.parseUserState(state: AccessState, userId: Int) {
         when (tagName) {
-            TAG_UID_APP_OPS -> parseUidAppOps(state, userId)
+            TAG_APP_ID_APP_OPS -> parseAppIdAppOps(state, userId)
             else -> {}
         }
     }
 
-    private fun BinaryXmlPullParser.parseUidAppOps(state: AccessState, userId: Int) {
+    private fun BinaryXmlPullParser.parseAppIdAppOps(state: AccessState, userId: Int) {
         val userState = state.userStates[userId]
         forEachTag {
             when (tagName) {
@@ -44,7 +44,7 @@
                 else -> Log.w(LOG_TAG, "Ignoring unknown tag $name when parsing app-op state")
             }
         }
-        userState.uidAppOpModes.retainAllIndexed { _, appId, _ ->
+        userState.appIdAppOpModes.retainAllIndexed { _, appId, _ ->
             val hasAppId = appId in state.systemState.appIds
             if (!hasAppId) {
                 Log.w(LOG_TAG, "Dropping unknown app ID $appId when parsing app-op state")
@@ -56,17 +56,17 @@
     private fun BinaryXmlPullParser.parseAppId(userState: UserState) {
         val appId = getAttributeIntOrThrow(ATTR_ID)
         val appOpModes = IndexedMap<String, Int>()
-        userState.uidAppOpModes[appId] = appOpModes
+        userState.appIdAppOpModes[appId] = appOpModes
         parseAppOps(appOpModes)
     }
 
     override fun BinaryXmlSerializer.serializeUserState(state: AccessState, userId: Int) {
-        serializeUidAppOps(state.userStates[userId])
+        serializeAppIdAppOps(state.userStates[userId])
     }
 
-    private fun BinaryXmlSerializer.serializeUidAppOps(userState: UserState) {
-        tag(TAG_UID_APP_OPS) {
-            userState.uidAppOpModes.forEachIndexed { _, appId, appOpModes ->
+    private fun BinaryXmlSerializer.serializeAppIdAppOps(userState: UserState) {
+        tag(TAG_APP_ID_APP_OPS) {
+            userState.appIdAppOpModes.forEachIndexed { _, appId, appOpModes ->
                 serializeAppId(appId, appOpModes)
             }
         }
@@ -83,10 +83,10 @@
     }
 
     companion object {
-        private val LOG_TAG = UidAppOpPersistence::class.java.simpleName
+        private val LOG_TAG = AppIdAppOpPersistence::class.java.simpleName
 
         private const val TAG_APP_ID = "app-id"
-        private const val TAG_UID_APP_OPS = "uid-app-ops"
+        private const val TAG_APP_ID_APP_OPS = "app-id-app-ops"
 
         private const val ATTR_ID = "id"
     }
diff --git a/services/permission/java/com/android/server/permission/access/appop/UidAppOpPolicy.kt b/services/permission/java/com/android/server/permission/access/appop/AppIdAppOpPolicy.kt
similarity index 82%
rename from services/permission/java/com/android/server/permission/access/appop/UidAppOpPolicy.kt
rename to services/permission/java/com/android/server/permission/access/appop/AppIdAppOpPolicy.kt
index 0ba9a1e..bd94955 100644
--- a/services/permission/java/com/android/server/permission/access/appop/UidAppOpPolicy.kt
+++ b/services/permission/java/com/android/server/permission/access/appop/AppIdAppOpPolicy.kt
@@ -17,14 +17,20 @@
 package com.android.server.permission.access.appop
 
 import android.app.AppOpsManager
+import com.android.server.permission.access.AccessState
 import com.android.server.permission.access.AccessUri
 import com.android.server.permission.access.AppOpUri
 import com.android.server.permission.access.GetStateScope
 import com.android.server.permission.access.MutateStateScope
 import com.android.server.permission.access.UidUri
 import com.android.server.permission.access.collection.* // ktlint-disable no-wildcard-imports
+import com.android.server.pm.pkg.PackageState
 
-class UidAppOpPolicy : BaseAppOpPolicy(UidAppOpPersistence()) {
+class AppIdAppOpPolicy : BaseAppOpPolicy(AppIdAppOpPersistence()) {
+    private val migration = AppIdAppOpMigration()
+
+    private val upgrade = AppIdAppOpUpgrade(this)
+
     @Volatile
     private var onAppOpModeChangedListeners = IndexedListSet<OnAppOpModeChangedListener>()
     private val onAppOpModeChangedListenersLock = Any()
@@ -54,18 +60,18 @@
 
     override fun MutateStateScope.onAppIdRemoved(appId: Int) {
         newState.userStates.forEachIndexed { _, _, userState ->
-            userState.uidAppOpModes -= appId
+            userState.appIdAppOpModes -= appId
             userState.requestWrite()
             // Skip notifying the change listeners since the app ID no longer exists.
         }
     }
 
     fun GetStateScope.getAppOpModes(appId: Int, userId: Int): IndexedMap<String, Int>? =
-        state.userStates[userId].uidAppOpModes[appId]
+        state.userStates[userId].appIdAppOpModes[appId]
 
     fun MutateStateScope.removeAppOpModes(appId: Int, userId: Int): Boolean {
         val userState = newState.userStates[userId]
-        val isChanged = userState.uidAppOpModes.removeReturnOld(appId) != null
+        val isChanged = userState.appIdAppOpModes.removeReturnOld(appId) != null
         if (isChanged) {
             userState.requestWrite()
         }
@@ -73,7 +79,7 @@
     }
 
     fun GetStateScope.getAppOpMode(appId: Int, userId: Int, appOpName: String): Int =
-        state.userStates[userId].uidAppOpModes[appId]
+        state.userStates[userId].appIdAppOpModes[appId]
             .getWithDefault(appOpName, AppOpsManager.opToDefaultMode(appOpName))
 
     fun MutateStateScope.setAppOpMode(
@@ -83,8 +89,8 @@
         mode: Int
     ): Boolean {
         val userState = newState.userStates[userId]
-        val uidAppOpModes = userState.uidAppOpModes
-        var appOpModes = uidAppOpModes[appId]
+        val appIdAppOpModes = userState.appIdAppOpModes
+        var appOpModes = appIdAppOpModes[appId]
         val defaultMode = AppOpsManager.opToDefaultMode(appOpName)
         val oldMode = appOpModes.getWithDefault(appOpName, defaultMode)
         if (oldMode == mode) {
@@ -92,11 +98,11 @@
         }
         if (appOpModes == null) {
             appOpModes = IndexedMap()
-            uidAppOpModes[appId] = appOpModes
+            appIdAppOpModes[appId] = appOpModes
         }
         appOpModes.putWithDefault(appOpName, mode, defaultMode)
         if (appOpModes.isEmpty()) {
-            uidAppOpModes -= appId
+            appIdAppOpModes -= appId
         }
         userState.requestWrite()
         onAppOpModeChangedListeners.forEachIndexed { _, it ->
@@ -117,6 +123,18 @@
         }
     }
 
+    override fun migrateUserState(state: AccessState, userId: Int) {
+        with(migration) { migrateUserState(state, userId) }
+    }
+
+    override fun MutateStateScope.upgradePackageState(
+        packageState: PackageState,
+        userId: Int,
+        version: Int,
+    ) {
+        with(upgrade) { upgradePackageState(packageState, userId, version) }
+    }
+
     /**
      * Listener for app op mode changes.
      */
diff --git a/services/permission/java/com/android/server/permission/access/appop/AppIdAppOpUpgrade.kt b/services/permission/java/com/android/server/permission/access/appop/AppIdAppOpUpgrade.kt
new file mode 100644
index 0000000..4bd36f4
--- /dev/null
+++ b/services/permission/java/com/android/server/permission/access/appop/AppIdAppOpUpgrade.kt
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.permission.access.appop
+
+import android.app.AppOpsManager
+import com.android.server.permission.access.MutateStateScope
+import com.android.server.pm.pkg.PackageState
+
+class AppIdAppOpUpgrade(private val policy: AppIdAppOpPolicy) {
+    fun MutateStateScope.upgradePackageState(
+        packageState: PackageState,
+        userId: Int,
+        version: Int,
+    ) {
+        if (version == 0) {
+            return
+        }
+
+        if (version <= 2) {
+            with(policy) {
+                val appOpMode = getAppOpMode(
+                    packageState.appId, userId, AppOpsManager.OPSTR_RUN_IN_BACKGROUND
+                )
+                setAppOpMode(
+                    packageState.appId, userId, AppOpsManager.OPSTR_RUN_ANY_IN_BACKGROUND, appOpMode
+                )
+            }
+        }
+        if (version <= 13) {
+            val permissionName = AppOpsManager.opToPermission(AppOpsManager.OP_SCHEDULE_EXACT_ALARM)
+            if (permissionName in packageState.androidPackage!!.requestedPermissions) {
+                with(policy) {
+                    val appOpMode = getAppOpMode(
+                        packageState.appId, userId, AppOpsManager.OPSTR_SCHEDULE_EXACT_ALARM
+                    )
+                    val defaultAppOpMode =
+                        AppOpsManager.opToDefaultMode(AppOpsManager.OP_SCHEDULE_EXACT_ALARM)
+                    if (appOpMode == defaultAppOpMode) {
+                        setAppOpMode(
+                            packageState.appId, userId, AppOpsManager.OPSTR_SCHEDULE_EXACT_ALARM,
+                            AppOpsManager.MODE_ALLOWED
+                        )
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/services/permission/java/com/android/server/permission/access/appop/AppOpService.kt b/services/permission/java/com/android/server/permission/access/appop/AppOpService.kt
index af85eba..17c92ac 100644
--- a/services/permission/java/com/android/server/permission/access/appop/AppOpService.kt
+++ b/services/permission/java/com/android/server/permission/access/appop/AppOpService.kt
@@ -16,30 +16,21 @@
 
 package com.android.server.permission.access.appop
 
-import android.Manifest
-import android.annotation.UserIdInt
-import android.app.AppGlobals
 import android.app.AppOpsManager
-import android.content.pm.PackageManager
-import android.os.Binder
 import android.os.Handler
-import android.os.RemoteException
 import android.os.UserHandle
-import android.util.SparseBooleanArray
 import android.util.SparseIntArray
 import com.android.internal.annotations.VisibleForTesting
 import com.android.internal.util.ArrayUtils
-import com.android.internal.util.function.pooled.PooledLambda
 import com.android.server.appop.AppOpsCheckingServiceInterface
-import com.android.server.appop.OnOpModeChangedListener
 import com.android.server.permission.access.AccessCheckingService
 import com.android.server.permission.access.AppOpUri
 import com.android.server.permission.access.PackageUri
 import com.android.server.permission.access.UidUri
-import com.android.server.permission.access.collection.* // ktlint-disable no-wildcard-imports
-import com.android.server.permission.access.util.hasBits
-import libcore.util.EmptyArray
-import java.io.PrintWriter
+import com.android.server.permission.access.collection.IndexedMap
+import com.android.server.permission.access.collection.IntBooleanMap
+import com.android.server.permission.access.collection.IntMap
+import com.android.server.permission.access.collection.forEachIndexed
 
 class AppOpService(
     private val service: AccessCheckingService
@@ -47,7 +38,7 @@
     private val packagePolicy = service.getSchemePolicy(PackageUri.SCHEME, AppOpUri.SCHEME)
         as PackageAppOpPolicy
     private val uidPolicy = service.getSchemePolicy(UidUri.SCHEME, AppOpUri.SCHEME)
-        as UidAppOpPolicy
+        as AppIdAppOpPolicy
 
     private val context = service.context
     private lateinit var handler: Handler
@@ -184,308 +175,23 @@
         // and we have our own persistence.
     }
 
-    // code -> listeners
-    private val opModeWatchers = IntMap<IndexedSet<OnOpModeChangedListener>>()
-
-    // packageName -> listeners
-    private val packageModeWatchers = IndexedMap<String, IndexedSet<OnOpModeChangedListener>>()
-
-    override fun startWatchingOpModeChanged(changedListener: OnOpModeChangedListener, op: Int) {
-        synchronized(lock) {
-            opModeWatchers.getOrPut(op) { IndexedSet() } += changedListener
-        }
-    }
-
-    override fun startWatchingPackageModeChanged(
-        changedListener: OnOpModeChangedListener,
-        packageName: String
-    ) {
-        synchronized(lock) {
-            packageModeWatchers.getOrPut(packageName) { IndexedSet() } += changedListener
-        }
-    }
-
-    override fun removeListener(changedListener: OnOpModeChangedListener) {
-        synchronized(lock) {
-            opModeWatchers.removeAllIndexed { _, _, listeners ->
-                listeners -= changedListener
-                listeners.isEmpty()
-            }
-            packageModeWatchers.removeAllIndexed { _, _, listeners ->
-                listeners -= changedListener
-                listeners.isEmpty()
-            }
-        }
-    }
-
-    override fun getOpModeChangedListeners(op: Int): IndexedSet<OnOpModeChangedListener> {
-        synchronized(lock) {
-            val listeners = opModeWatchers[op]
-            return if (listeners == null) {
-                IndexedSet()
-            } else {
-                IndexedSet(listeners)
-            }
-        }
-    }
-
-    override fun getPackageModeChangedListeners(
-        packageName: String
-    ): IndexedSet<OnOpModeChangedListener> {
-        synchronized(lock) {
-            val listeners = packageModeWatchers[packageName]
-            return if (listeners == null) {
-                IndexedSet()
-            } else {
-                IndexedSet(listeners)
-            }
-        }
-    }
-
-    override fun notifyWatchersOfChange(op: Int, uid: Int) {
-        val listeners = getOpModeChangedListeners(op)
-        listeners.forEachIndexed { _, listener ->
-            notifyOpChanged(listener, op, uid, null)
-        }
-    }
-
-    override fun notifyOpChanged(
-        changedListener: OnOpModeChangedListener,
-        op: Int,
-        uid: Int,
-        packageName: String?
-    ) {
-        if (uid != UID_ANY &&
-            changedListener.watchingUid >= 0 &&
-            changedListener.watchingUid != uid
-        ) {
-            return
-        }
-
-        // See CALL_BACK_ON_CHANGED_LISTENER_WITH_SWITCHED_OP_CHANGE
-        val switchedCodes = when (changedListener.watchedOpCode) {
-            ALL_OPS -> switchedOps.get(op)
-            AppOpsManager.OP_NONE -> intArrayOf(op)
-            else -> intArrayOf(changedListener.watchedOpCode)
-        }
-
-        for (switchedCode in switchedCodes) {
-            // There are features watching for mode changes such as window manager
-            // and location manager which are in our process. The callbacks in these
-            // features may require permissions our remote caller does not have.
-            val identity = Binder.clearCallingIdentity()
-            try {
-                if (!shouldIgnoreCallback(switchedCode, changedListener)) {
-                    changedListener.onOpModeChanged(switchedCode, uid, packageName)
-                }
-            } catch (e: RemoteException) {
-                /* ignore */
-            } finally {
-                Binder.restoreCallingIdentity(identity)
-            }
-        }
-    }
-
-    private fun shouldIgnoreCallback(op: Int, listener: OnOpModeChangedListener): Boolean {
-        // If it's a restricted read op, ignore it if watcher doesn't have manage ops permission,
-        // as watcher should not use this to signal if the value is changed.
-        return AppOpsManager.opRestrictsRead(op) && context.checkPermission(
-            Manifest.permission.MANAGE_APPOPS,
-            listener.callingPid,
-            listener.callingUid
-        ) != PackageManager.PERMISSION_GRANTED
-    }
-
-    /**
-     * Construct a map from each listener (listening to the given op, uid) to all of its associated
-     * packageNames (by reverse-indexing opModeWatchers and packageModeWatchers), then invoke
-     * notifyOpChanged for each listener.
-     */
-    override fun notifyOpChangedForAllPkgsInUid(
-        op: Int,
-        uid: Int,
-        onlyForeground: Boolean,
-        callbackToIgnore: OnOpModeChangedListener?
-    ) {
-        val uidPackageNames = getPackagesForUid(uid)
-        val callbackSpecs = IndexedMap<OnOpModeChangedListener, IndexedSet<String>>()
-
-        fun associateListenerWithPackageNames(
-            listener: OnOpModeChangedListener,
-            packageNames: Array<String>
-        ) {
-            val listenerIsForeground =
-                listener.flags.hasBits(AppOpsManager.WATCH_FOREGROUND_CHANGES)
-            if (onlyForeground && !listenerIsForeground) {
-                return
-            }
-            val changedPackages = callbackSpecs.getOrPut(listener) { IndexedSet() }
-            changedPackages.addAll(packageNames)
-        }
-
-        synchronized(lock) {
-            // Collect all listeners from opModeWatchers and pckageModeWatchers
-            val listeners = opModeWatchers[op]
-            listeners?.forEachIndexed { _, listener ->
-                associateListenerWithPackageNames(listener, uidPackageNames)
-            }
-            uidPackageNames.forEachIndexed { _, uidPackageName ->
-                val packageListeners = packageModeWatchers[uidPackageName]
-                packageListeners?.forEachIndexed { _, listener ->
-                    associateListenerWithPackageNames(listener, arrayOf(uidPackageName))
-                }
-            }
-            // Remove ignored listeners
-            if (callbackToIgnore != null) {
-                callbackSpecs.remove(callbackToIgnore)
-            }
-        }
-
-        // For each (listener, packageName) pair, invoke notifyOpChanged
-        callbackSpecs.forEachIndexed { _, listener, reportedPackageNames ->
-            reportedPackageNames.forEachIndexed { _, reportedPackageName ->
-                handler.sendMessage(
-                    PooledLambda.obtainMessage(
-                        AppOpService::notifyOpChanged, this, listener,
-                        op, uid, reportedPackageName
-                    )
-                )
-            }
-        }
-    }
-
-    private fun getPackagesForUid(uid: Int): Array<String> {
-        // Very early during boot the package manager is not yet or not yet fully started. At this
-        // time there are no packages yet.
-        return try {
-            AppGlobals.getPackageManager()?.getPackagesForUid(uid) ?: EmptyArray.STRING
-        } catch (e: RemoteException) {
-            EmptyArray.STRING
-        }
-    }
-
-    override fun evalForegroundUidOps(
-        uid: Int,
-        foregroundOps: SparseBooleanArray?
-    ): SparseBooleanArray? {
-        synchronized(lock) {
-            val uidModes = getUidModes(uid)
-            return evalForegroundOps(uidModes, foregroundOps)
-        }
-    }
-
-    override fun evalForegroundPackageOps(
-        packageName: String,
-        foregroundOps: SparseBooleanArray?,
-        @UserIdInt userId: Int
-    ): SparseBooleanArray? {
-        synchronized(lock) {
-            val ops = service.getState { getPackageModes(packageName, userId) }
-            return evalForegroundOps(ops, foregroundOps)
-        }
-    }
-
-    private fun evalForegroundOps(
-        ops: IndexedMap<String, Int>?,
-        foregroundOps: SparseBooleanArray?
-    ): SparseBooleanArray? {
-        var foregroundOps = foregroundOps
-        ops?.forEachIndexed { _, opName, opMode ->
-            if (opMode == AppOpsManager.MODE_FOREGROUND) {
-                if (foregroundOps == null) {
-                    foregroundOps = SparseBooleanArray()
-                }
-                evalForegroundWatchers(opName, foregroundOps!!)
-            }
-        }
-        return foregroundOps
-    }
-
-    private fun evalForegroundWatchers(opName: String, foregroundOps: SparseBooleanArray) {
-        val opCode = AppOpsManager.strOpToOp(opName)
-        val listeners = opModeWatchers[opCode]
-        val hasForegroundListeners = foregroundOps[opCode] || listeners?.anyIndexed { _, listener ->
-            listener.flags.hasBits(AppOpsManager.WATCH_FOREGROUND_CHANGES)
-        } ?: false
-        foregroundOps.put(opCode, hasForegroundListeners)
-    }
-
-    override fun dumpListeners(
-        dumpOp: Int,
-        dumpUid: Int,
-        dumpPackage: String?,
-        printWriter: PrintWriter
-    ): Boolean {
-        var needSep = false
-        if (opModeWatchers.size() > 0) {
-            var printedHeader = false
-            opModeWatchers.forEachIndexed { _, op, modeChangedListenerSet ->
-                if (dumpOp >= 0 && dumpOp != op) {
-                    return@forEachIndexed // continue
-                }
-                val opName = AppOpsManager.opToName(op)
-                var printedOpHeader = false
-                modeChangedListenerSet.forEachIndexed listenerLoop@ { listenerIndex, listener ->
-                    with(printWriter) {
-                        if (dumpPackage != null &&
-                            dumpUid != UserHandle.getAppId(listener.watchingUid)) {
-                            return@listenerLoop // continue
-                        }
-                        needSep = true
-                        if (!printedHeader) {
-                            println("  Op mode watchers:")
-                            printedHeader = true
-                        }
-                        if (!printedOpHeader) {
-                            print("    Op ")
-                            print(opName)
-                            println(":")
-                            printedOpHeader = true
-                        }
-                        print("      #")
-                        print(listenerIndex)
-                        print(opName)
-                        print(": ")
-                        println(listener.toString())
-                    }
+    override fun getForegroundOps(uid: Int): IntBooleanMap {
+        return IntBooleanMap().apply {
+            getUidModes(uid)?.forEachIndexed { _, code, mode ->
+                if (mode == AppOpsManager.MODE_FOREGROUND) {
+                    put(AppOpsManager.strOpToOp(code), true)
                 }
             }
         }
+    }
 
-        if (packageModeWatchers.size > 0 && dumpOp < 0) {
-            var printedHeader = false
-            packageModeWatchers.forEachIndexed { _, packageName, listeners ->
-                with(printWriter) {
-                    if (dumpPackage != null && dumpPackage != packageName) {
-                        return@forEachIndexed // continue
-                    }
-                    needSep = true
-                    if (!printedHeader) {
-                        println("  Package mode watchers:")
-                        printedHeader = true
-                    }
-                    print("    Pkg ")
-                    print(packageName)
-                    println(":")
-                    listeners.forEachIndexed { listenerIndex, listener ->
-                        print("      #")
-                        print(listenerIndex)
-                        print(": ")
-                        println(listener.toString())
-                    }
+    override fun getForegroundOps(packageName: String, userId: Int): IntBooleanMap {
+        return IntBooleanMap().apply {
+            getPackageModes(packageName, userId)?.forEachIndexed { _, code, mode ->
+                if (mode == AppOpsManager.MODE_FOREGROUND) {
+                    put(AppOpsManager.strOpToOp(code), true)
                 }
             }
         }
-        return needSep
-    }
-
-    companion object {
-        private val LOG_TAG = AppOpService::class.java.simpleName
-
-        // Constant meaning that any UID should be matched when dispatching callbacks
-        private const val UID_ANY = -2
-
-        // If watchedOpCode==ALL_OPS, notify for ops affected by the switch-op
-        private const val ALL_OPS = -2
     }
 }
diff --git a/services/permission/java/com/android/server/permission/access/appop/PackageAppOpMigration.kt b/services/permission/java/com/android/server/permission/access/appop/PackageAppOpMigration.kt
new file mode 100644
index 0000000..c9651b2
--- /dev/null
+++ b/services/permission/java/com/android/server/permission/access/appop/PackageAppOpMigration.kt
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.permission.access.appop
+
+import com.android.server.LocalServices
+import com.android.server.appop.AppOpMigrationHelper
+import com.android.server.permission.access.AccessState
+import com.android.server.permission.access.collection.* // ktlint-disable no-wildcard-imports
+import com.android.server.permission.access.util.PackageVersionMigration
+
+class PackageAppOpMigration {
+    fun migrateUserState(state: AccessState, userId: Int) {
+        val legacyAppOpsManager = LocalServices.getService(AppOpMigrationHelper::class.java)!!
+        val legacyPackageAppOpModes = legacyAppOpsManager.getLegacyPackageAppOpModes(userId)
+        val packageAppOpModes = state.userStates[userId].packageAppOpModes
+        val version = PackageVersionMigration.getVersion(userId)
+        legacyPackageAppOpModes.forEach { (packageName, legacyAppOpModes) ->
+            val appOpModes = packageAppOpModes.getOrPut(packageName) { IndexedMap() }
+            legacyAppOpModes.forEach { (appOpName, appOpMode) ->
+                appOpModes[appOpName] = appOpMode
+            }
+            state.userStates[userId].packageVersions[packageName] = version
+        }
+    }
+}
diff --git a/services/permission/java/com/android/server/permission/access/appop/PackageAppOpPolicy.kt b/services/permission/java/com/android/server/permission/access/appop/PackageAppOpPolicy.kt
index 7d3578d..b4c4796 100644
--- a/services/permission/java/com/android/server/permission/access/appop/PackageAppOpPolicy.kt
+++ b/services/permission/java/com/android/server/permission/access/appop/PackageAppOpPolicy.kt
@@ -17,14 +17,20 @@
 package com.android.server.permission.access.appop
 
 import android.app.AppOpsManager
+import com.android.server.permission.access.AccessState
 import com.android.server.permission.access.AccessUri
 import com.android.server.permission.access.AppOpUri
 import com.android.server.permission.access.GetStateScope
 import com.android.server.permission.access.MutateStateScope
 import com.android.server.permission.access.PackageUri
 import com.android.server.permission.access.collection.* // ktlint-disable no-wildcard-imports
+import com.android.server.pm.pkg.PackageState
 
 class PackageAppOpPolicy : BaseAppOpPolicy(PackageAppOpPersistence()) {
+    private val migration = PackageAppOpMigration()
+
+    private val upgrade = PackageAppOpUpgrade(this)
+
     @Volatile
     private var onAppOpModeChangedListeners = IndexedListSet<OnAppOpModeChangedListener>()
     private val onAppOpModeChangedListenersLock = Any()
@@ -117,6 +123,18 @@
         }
     }
 
+    override fun migrateUserState(state: AccessState, userId: Int) {
+        with(migration) { migrateUserState(state, userId) }
+    }
+
+    override fun MutateStateScope.upgradePackageState(
+        packageState: PackageState,
+        userId: Int,
+        version: Int,
+    ) {
+        with(upgrade) { upgradePackageState(packageState, userId, version) }
+    }
+
     /**
      * Listener for app op mode changes.
      */
diff --git a/services/permission/java/com/android/server/permission/access/appop/PackageAppOpUpgrade.kt b/services/permission/java/com/android/server/permission/access/appop/PackageAppOpUpgrade.kt
new file mode 100644
index 0000000..fdf2b64
--- /dev/null
+++ b/services/permission/java/com/android/server/permission/access/appop/PackageAppOpUpgrade.kt
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.permission.access.appop
+
+import android.app.AppOpsManager
+import com.android.server.permission.access.MutateStateScope
+import com.android.server.pm.pkg.PackageState
+
+class PackageAppOpUpgrade(private val policy: PackageAppOpPolicy) {
+    fun MutateStateScope.upgradePackageState(
+        packageState: PackageState,
+        userId: Int,
+        version: Int,
+    ) {
+        if (version == 0) {
+            return
+        }
+
+        if (version <= 2) {
+            with(policy) {
+                val appOpMode = getAppOpMode(
+                    packageState.packageName, userId, AppOpsManager.OPSTR_RUN_IN_BACKGROUND
+                )
+                setAppOpMode(
+                    packageState.packageName, userId, AppOpsManager.OPSTR_RUN_ANY_IN_BACKGROUND,
+                    appOpMode
+                )
+            }
+        }
+    }
+}
diff --git a/services/permission/java/com/android/server/permission/access/permission/AppIdPermissionMigration.kt b/services/permission/java/com/android/server/permission/access/permission/AppIdPermissionMigration.kt
new file mode 100644
index 0000000..b2a27b2
--- /dev/null
+++ b/services/permission/java/com/android/server/permission/access/permission/AppIdPermissionMigration.kt
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.permission.access.permission
+
+import android.util.Log
+import com.android.server.LocalServices
+import com.android.server.permission.access.AccessState
+import com.android.server.permission.access.collection.* // ktlint-disable no-wildcard-imports
+import com.android.server.permission.access.util.PackageVersionMigration
+import com.android.server.pm.permission.PermissionMigrationHelper
+
+/**
+ * This class migrate legacy permissions to unified permission subsystem
+ */
+class AppIdPermissionMigration {
+    internal fun migrateSystemState(state: AccessState) {
+        val legacyPermissionsManager =
+            LocalServices.getService(PermissionMigrationHelper::class.java)!!
+        migratePermissions(state.systemState.permissions,
+            legacyPermissionsManager.legacyPermissions)
+        migratePermissions(state.systemState.permissionTrees,
+            legacyPermissionsManager.legacyPermissionTrees, true)
+    }
+
+    private fun migratePermissions(
+        permissions: IndexedMap<String, Permission>,
+        legacyPermissions: Map<String, PermissionMigrationHelper.LegacyPermission>,
+        isPermissionTree: Boolean = false
+    ) {
+        legacyPermissions.forEach { (_, legacyPermission) ->
+            val permission = Permission(
+                legacyPermission.permissionInfo, false, legacyPermission.type, 0
+            )
+            permissions[permission.name] = permission
+            if (DEBUG_MIGRATION) {
+                Log.v(LOG_TAG, "Migrated permission: ${permission.name}, type: " +
+                    "${permission.type}, appId: ${permission.appId}, protectionLevel: " +
+                    "${permission.protectionLevel}, tree: $isPermissionTree"
+                )
+            }
+        }
+    }
+
+    internal fun migrateUserState(state: AccessState, userId: Int) {
+        val permissionMigrationHelper =
+            LocalServices.getService(PermissionMigrationHelper::class.java)!!
+        val permissionStates = permissionMigrationHelper.getLegacyPermissionStates(userId)
+        val version = PackageVersionMigration.getVersion(userId)
+
+        permissionStates.forEach { (appId, permissionStates) ->
+            migratePermissionStates(appId, state, permissionStates, userId)
+            state.systemState.appIds[appId].forEachIndexed { _, packageName ->
+                state.userStates[userId].packageVersions[packageName] = version
+            }
+        }
+    }
+
+    private fun migratePermissionStates(
+        appId: Int,
+        state: AccessState,
+        legacyPermissionStates: Map<String, PermissionMigrationHelper.LegacyPermissionState>,
+        userId: Int
+    ) {
+        val permissionFlags =
+            state.userStates[userId].appIdPermissionFlags.getOrPut(appId) { IndexedMap() }
+
+        legacyPermissionStates.forEach forEachPermission@ { (permissionName, permissionState) ->
+            val permission = state.systemState.permissions[permissionName]
+                ?: return@forEachPermission
+
+            var flags = when {
+                permission.isNormal -> if (permissionState.isGranted) {
+                    PermissionFlags.INSTALL_GRANTED
+                } else {
+                    PermissionFlags.INSTALL_REVOKED
+                }
+                permission.isSignature || permission.isInternal ->
+                    if (permissionState.isGranted) {
+                        if (permission.isDevelopment || permission.isRole) {
+                            PermissionFlags.PROTECTION_GRANTED or PermissionFlags.RUNTIME_GRANTED
+                        } else {
+                            PermissionFlags.PROTECTION_GRANTED
+                        }
+                    } else {
+                        0
+                    }
+                permission.isRuntime ->
+                    if (permissionState.isGranted) PermissionFlags.RUNTIME_GRANTED else 0
+                else -> 0
+            }
+            flags = PermissionFlags.updateFlags(
+                permission, flags, permissionState.flags, permissionState.flags
+            )
+            permissionFlags[permissionName] = flags
+
+            if (DEBUG_MIGRATION) {
+                val oldFlagString = PermissionFlags.apiFlagsToString(permissionState.flags)
+                val newFlagString = PermissionFlags.toString(flags)
+                val oldGrantState = permissionState.isGranted
+                val newGrantState = PermissionFlags.isPermissionGranted(flags)
+                val flagsMismatch = permissionState.flags != PermissionFlags.toApiFlags(flags)
+                Log.v(
+                    LOG_TAG, "Migrated appId: $appId, permission: " +
+                        "${permission.name}, user: $userId, oldGrantState: $oldGrantState" +
+                        ", oldFlags: $oldFlagString, newFlags: $newFlagString, grantMismatch: " +
+                        "${oldGrantState != newGrantState}, flagsMismatch: $flagsMismatch"
+                )
+            }
+        }
+    }
+
+    companion object {
+        private val LOG_TAG = AppIdPermissionMigration::class.java.simpleName
+
+        private const val DEBUG_MIGRATION = false
+    }
+}
diff --git a/services/permission/java/com/android/server/permission/access/permission/UidPermissionPersistence.kt b/services/permission/java/com/android/server/permission/access/permission/AppIdPermissionPersistence.kt
similarity index 86%
rename from services/permission/java/com/android/server/permission/access/permission/UidPermissionPersistence.kt
rename to services/permission/java/com/android/server/permission/access/permission/AppIdPermissionPersistence.kt
index 35cdbce..552dda1 100644
--- a/services/permission/java/com/android/server/permission/access/permission/UidPermissionPersistence.kt
+++ b/services/permission/java/com/android/server/permission/access/permission/AppIdPermissionPersistence.kt
@@ -37,7 +37,7 @@
 import com.android.server.permission.access.util.tag
 import com.android.server.permission.access.util.tagName
 
-class UidPermissionPersistence {
+class AppIdPermissionPersistence {
     fun BinaryXmlPullParser.parseSystemState(state: AccessState) {
         val systemState = state.systemState
         when (tagName) {
@@ -126,12 +126,12 @@
 
     fun BinaryXmlPullParser.parseUserState(state: AccessState, userId: Int) {
         when (tagName) {
-            TAG_PERMISSIONS -> parsePermissionFlags(state, userId)
+            TAG_APP_ID_PERMISSIONS -> parseAppIdPermissions(state, userId)
             else -> {}
         }
     }
 
-    private fun BinaryXmlPullParser.parsePermissionFlags(state: AccessState, userId: Int) {
+    private fun BinaryXmlPullParser.parseAppIdPermissions(state: AccessState, userId: Int) {
         val userState = state.userStates[userId]
         forEachTag {
             when (tagName) {
@@ -139,7 +139,7 @@
                 else -> Log.w(LOG_TAG, "Ignoring unknown tag $name when parsing permission state")
             }
         }
-        userState.uidPermissionFlags.retainAllIndexed { _, appId, _ ->
+        userState.appIdPermissionFlags.retainAllIndexed { _, appId, _ ->
             val hasAppId = appId in state.systemState.appIds
             if (!hasAppId) {
                 Log.w(LOG_TAG, "Dropping unknown app ID $appId when parsing permission state")
@@ -151,34 +151,34 @@
     private fun BinaryXmlPullParser.parseAppId(userState: UserState) {
         val appId = getAttributeIntOrThrow(ATTR_ID)
         val permissionFlags = IndexedMap<String, Int>()
-        userState.uidPermissionFlags[appId] = permissionFlags
-        parseAppIdPermissions(permissionFlags)
+        userState.appIdPermissionFlags[appId] = permissionFlags
+        parsePermissionStates(permissionFlags)
     }
 
-    private fun BinaryXmlPullParser.parseAppIdPermissions(
+    private fun BinaryXmlPullParser.parsePermissionStates(
         permissionFlags: IndexedMap<String, Int>
     ) {
         forEachTag {
             when (tagName) {
-                TAG_PERMISSION -> parseAppIdPermission(permissionFlags)
+                TAG_PERMISSION -> parsePermissionState(permissionFlags)
                 else -> Log.w(LOG_TAG, "Ignoring unknown tag $name when parsing permission state")
             }
         }
     }
 
-    private fun BinaryXmlPullParser.parseAppIdPermission(permissionFlags: IndexedMap<String, Int>) {
+    private fun BinaryXmlPullParser.parsePermissionState(permissionFlags: IndexedMap<String, Int>) {
         val name = getAttributeValueOrThrow(ATTR_NAME).intern()
         val flags = getAttributeIntOrThrow(ATTR_FLAGS)
         permissionFlags[name] = flags
     }
 
     fun BinaryXmlSerializer.serializeUserState(state: AccessState, userId: Int) {
-        serializePermissionFlags(state.userStates[userId])
+        serializeAppIdPermissions(state.userStates[userId])
     }
 
-    private fun BinaryXmlSerializer.serializePermissionFlags(userState: UserState) {
-        tag(TAG_PERMISSIONS) {
-            userState.uidPermissionFlags.forEachIndexed { _, appId, permissionFlags ->
+    private fun BinaryXmlSerializer.serializeAppIdPermissions(userState: UserState) {
+        tag(TAG_APP_ID_PERMISSIONS) {
+            userState.appIdPermissionFlags.forEachIndexed { _, appId, permissionFlags ->
                 serializeAppId(appId, permissionFlags)
             }
         }
@@ -190,19 +190,19 @@
     ) {
         tag(TAG_APP_ID) {
             attributeInt(ATTR_ID, appId)
-            serializeAppIdPermissions(permissionFlags)
+            serializePermissionStates(permissionFlags)
         }
     }
 
-    private fun BinaryXmlSerializer.serializeAppIdPermissions(
+    private fun BinaryXmlSerializer.serializePermissionStates(
         permissionFlags: IndexedMap<String, Int>
     ) {
         permissionFlags.forEachIndexed { _, name, flags ->
-            serializeAppIdPermission(name, flags)
+            serializePermissionState(name, flags)
         }
     }
 
-    private fun BinaryXmlSerializer.serializeAppIdPermission(name: String, flags: Int) {
+    private fun BinaryXmlSerializer.serializePermissionState(name: String, flags: Int) {
         tag(TAG_PERMISSION) {
             attributeInterned(ATTR_NAME, name)
             attributeInt(ATTR_FLAGS, flags)
@@ -210,9 +210,10 @@
     }
 
     companion object {
-        private val LOG_TAG = UidPermissionPersistence::class.java.simpleName
+        private val LOG_TAG = AppIdPermissionPersistence::class.java.simpleName
 
         private const val TAG_APP_ID = "app-id"
+        private const val TAG_APP_ID_PERMISSIONS = "app-id-permissions"
         private const val TAG_PERMISSION = "permission"
         private const val TAG_PERMISSIONS = "permissions"
         private const val TAG_PERMISSION_TREES = "permission-trees"
diff --git a/services/permission/java/com/android/server/permission/access/permission/UidPermissionPolicy.kt b/services/permission/java/com/android/server/permission/access/permission/AppIdPermissionPolicy.kt
similarity index 93%
rename from services/permission/java/com/android/server/permission/access/permission/UidPermissionPolicy.kt
rename to services/permission/java/com/android/server/permission/access/permission/AppIdPermissionPolicy.kt
index 5a7b37a..1177735 100644
--- a/services/permission/java/com/android/server/permission/access/permission/UidPermissionPolicy.kt
+++ b/services/permission/java/com/android/server/permission/access/permission/AppIdPermissionPolicy.kt
@@ -45,8 +45,12 @@
 import com.android.server.pm.pkg.AndroidPackage
 import com.android.server.pm.pkg.PackageState
 
-class UidPermissionPolicy : SchemePolicy() {
-    private val persistence = UidPermissionPersistence()
+class AppIdPermissionPolicy : SchemePolicy() {
+    private val persistence = AppIdPermissionPersistence()
+
+    private val migration = AppIdPermissionMigration()
+
+    private val upgrade = AppIdPermissionUpgrade(this)
 
     @Volatile
     private var onPermissionFlagsChangedListeners =
@@ -124,7 +128,7 @@
 
     override fun MutateStateScope.onAppIdRemoved(appId: Int) {
         newState.userStates.forEachValueIndexed { _, userState ->
-            userState.uidPermissionFlags -= appId
+            userState.appIdPermissionFlags -= appId
             userState.requestWrite()
             // Skip notifying the change listeners since the app ID no longer exists.
         }
@@ -209,16 +213,15 @@
         appId: Int,
         userId: Int
     ) {
-        resetRuntimePermissions(packageName, appId, userId)
+        resetRuntimePermissions(packageName, userId)
     }
 
-    fun MutateStateScope.resetRuntimePermissions(
-        packageName: String,
-        appId: Int,
-        userId: Int
-    ) {
-        val androidPackage = newState.systemState.packageStates[packageName]?.androidPackage
-            ?: return
+    fun MutateStateScope.resetRuntimePermissions(packageName: String, userId: Int) {
+        // It's okay to skip resetting permissions for packages that are removed,
+        // because their states will be trimmed in onPackageRemoved()/onAppIdRemoved()
+        val packageState = newState.systemState.packageStates[packageName] ?: return
+        val androidPackage = packageState.androidPackage ?: return
+        val appId = packageState.appId
         androidPackage.requestedPermissions.forEachIndexed { _, permissionName ->
             val permission = newState.systemState.permissions[permissionName]
                 ?: return@forEachIndexed
@@ -446,7 +449,7 @@
                     return@forEachIndexed
                 }
             } else {
-                if (oldPermission != null) {
+                if (oldPermission != null && oldPermission.isReconciled) {
                     val isPermissionGroupChanged = newPermissionInfo.isRuntime &&
                         newPermissionInfo.group != null &&
                         newPermissionInfo.group != oldPermission.groupName
@@ -595,7 +598,7 @@
             requestedPermissions += it.androidPackage!!.requestedPermissions
         }
         newState.userStates.forEachIndexed { _, userId, userState ->
-            userState.uidPermissionFlags[appId]?.forEachReversedIndexed { _, permissionName, _ ->
+            userState.appIdPermissionFlags[appId]?.forEachReversedIndexed { _, permissionName, _ ->
                 if (permissionName !in requestedPermissions) {
                     setPermissionFlags(appId, userId, permissionName, 0)
                 }
@@ -607,7 +610,7 @@
         // If the app is updated, and has scoped storage permissions, then it is possible that the
         // app updated in an attempt to get unscoped storage. If so, revoke all storage permissions.
         newState.userStates.forEachIndexed { _, userId, userState ->
-            userState.uidPermissionFlags[appId]?.forEachReversedIndexed {
+            userState.appIdPermissionFlags[appId]?.forEachReversedIndexed {
                 _, permissionName, oldFlags ->
                 if (permissionName !in STORAGE_AND_MEDIA_PERMISSIONS || oldFlags == 0) {
                     return@forEachReversedIndexed
@@ -628,6 +631,8 @@
                     !oldIsRequestLegacyExternalStorage && newIsRequestLegacyExternalStorage
                 if ((isNewlyRequestingLegacyExternalStorage || isTargetSdkVersionDowngraded) &&
                     oldFlags.hasBits(PermissionFlags.RUNTIME_GRANTED)) {
+                    Log.v(LOG_TAG, "Revoking storage permission: $permissionName for appId: " +
+                            " $appId and user: $userId")
                     val newFlags = oldFlags andInv (
                         PermissionFlags.RUNTIME_GRANTED or USER_SETTABLE_MASK
                     )
@@ -766,6 +771,7 @@
             setPermissionFlags(appId, userId, permissionName, newFlags)
         } else if (permission.isRuntime) {
             var newFlags = oldFlags and PermissionFlags.MASK_RUNTIME
+            val wasRevoked = newFlags != 0 && !PermissionFlags.isPermissionGranted(newFlags)
             if (getAppIdTargetSdkVersion(appId, permissionName) < Build.VERSION_CODES.M) {
                 if (permission.isRuntimeOnly) {
                     // Different from the old implementation, which simply skips a runtime-only
@@ -775,6 +781,9 @@
                     newFlags = newFlags and PermissionFlags.MASK_EXEMPT
                 } else {
                     newFlags = newFlags or PermissionFlags.LEGACY_GRANTED
+                    if (wasRevoked) {
+                        newFlags = newFlags or PermissionFlags.APP_OP_REVOKED
+                    }
                     // Explicitly check against the old state to determine if this permission is
                     // new.
                     val isNewPermission =
@@ -805,16 +814,23 @@
                     (isImplicitPermission && isAnySourcePermissionNonRuntime)
                 if (shouldGrantByImplicit) {
                     newFlags = newFlags or PermissionFlags.IMPLICIT_GRANTED
+                    if (wasRevoked) {
+                        newFlags = newFlags or PermissionFlags.APP_OP_REVOKED
+                    }
                 } else {
                     newFlags = newFlags andInv PermissionFlags.IMPLICIT_GRANTED
-                }
-                if ((wasGrantedByLegacy || wasGrantedByImplicit) && !shouldGrantByImplicit) {
-                    // The permission was granted from a compatibility grant or an implicit grant,
-                    // however this flag might still be set if the user denied this permission in
-                    // the settings. Hence upon app upgrade and when this permission is no longer
-                    // LEGACY_GRANTED or IMPLICIT_GRANTED and we revoke the permission, we want to
-                    // remove this flag so that the app can request the permission again.
-                    newFlags = newFlags andInv PermissionFlags.APP_OP_REVOKED
+                    if ((wasGrantedByLegacy || wasGrantedByImplicit) &&
+                        newFlags.hasBits(PermissionFlags.APP_OP_REVOKED)) {
+                        // The permission was granted from a compatibility grant or an implicit
+                        // grant, however this flag might still be set if the user denied this
+                        // permission in the settings. Hence upon app upgrade and when this
+                        // permission is no longer LEGACY_GRANTED or IMPLICIT_GRANTED and we revoke
+                        // the permission, we want to remove this flag so that the app can request
+                        // the permission again.
+                        newFlags = newFlags andInv (
+                            PermissionFlags.RUNTIME_GRANTED or PermissionFlags.APP_OP_REVOKED
+                        )
+                    }
                 }
                 val hasImplicitFlag = newFlags.hasBits(PermissionFlags.IMPLICIT)
                 if (!isImplicitPermission && hasImplicitFlag) {
@@ -842,15 +858,29 @@
                 }
             }
 
-            val isExempt = newFlags.hasAnyBit(PermissionFlags.MASK_EXEMPT)
-            val isHardRestricted = permission.isHardRestricted && !isExempt
-            newFlags = if (isHardRestricted) {
+            val wasExempt = newFlags.hasAnyBit(PermissionFlags.MASK_EXEMPT)
+            val wasRestricted = newFlags.hasAnyBit(PermissionFlags.MASK_RESTRICTED)
+            val isExempt = if (permission.isHardOrSoftRestricted && !wasExempt && !wasRestricted) {
+                // All restricted permissions start as exempt. If there's an installer for the
+                // package, we will drop this UPGRADE_EXEMPT flag when we receive the
+                // onPackageInstalled() callback and set up the INSTALLER_EXEMPT flags.
+                // UPGRADE_EXEMPT is chosen instead of other flags because it is the same flag that
+                // was assigned to pre-installed apps in RuntimePermissionsUpgradeController, and to
+                // apps with missing permission state.
+                // This way we make sure both pre-installed apps, and apps updated/installed after
+                // a rollback snapshot is taken, can get the allowlist for permissions that won't be
+                // allowlisted otherwise.
+                newFlags = newFlags or PermissionFlags.UPGRADE_EXEMPT
+                true
+            } else {
+                wasExempt
+            }
+            newFlags = if (permission.isHardRestricted && !isExempt) {
                 newFlags or PermissionFlags.RESTRICTION_REVOKED
             } else {
                 newFlags andInv PermissionFlags.RESTRICTION_REVOKED
             }
-            val isSoftRestricted = permission.isSoftRestricted && !isExempt
-            newFlags = if (isSoftRestricted) {
+            newFlags = if (permission.isSoftRestricted && !isExempt) {
                 newFlags or PermissionFlags.SOFT_RESTRICTED
             } else {
                 newFlags andInv PermissionFlags.SOFT_RESTRICTED
@@ -1313,7 +1343,7 @@
     }
 
     fun GetStateScope.getUidPermissionFlags(appId: Int, userId: Int): IndexedMap<String, Int>? =
-        state.userStates[userId]?.uidPermissionFlags?.get(appId)
+        state.userStates[userId]?.appIdPermissionFlags?.get(appId)
 
     fun GetStateScope.getPermissionFlags(
         appId: Int,
@@ -1333,7 +1363,7 @@
         userId: Int,
         permissionName: String
     ): Int =
-        state.userStates[userId]?.uidPermissionFlags?.get(appId).getWithDefault(permissionName, 0)
+        state.userStates[userId]?.appIdPermissionFlags?.get(appId).getWithDefault(permissionName, 0)
 
     fun MutateStateScope.setPermissionFlags(
         appId: Int,
@@ -1351,8 +1381,8 @@
         flagValues: Int
     ): Boolean {
         val userState = newState.userStates[userId]
-        val uidPermissionFlags = userState.uidPermissionFlags
-        var permissionFlags = uidPermissionFlags[appId]
+        val appIdPermissionFlags = userState.appIdPermissionFlags
+        var permissionFlags = appIdPermissionFlags[appId]
         val oldFlags = permissionFlags.getWithDefault(permissionName, 0)
         val newFlags = (oldFlags andInv flagMask) or (flagValues and flagMask)
         if (oldFlags == newFlags) {
@@ -1360,11 +1390,11 @@
         }
         if (permissionFlags == null) {
             permissionFlags = IndexedMap()
-            uidPermissionFlags[appId] = permissionFlags
+            appIdPermissionFlags[appId] = permissionFlags
         }
         permissionFlags.putWithDefault(permissionName, newFlags, 0)
         if (permissionFlags.isEmpty()) {
-            uidPermissionFlags -= appId
+            appIdPermissionFlags -= appId
         }
         userState.requestWrite()
         onPermissionFlagsChangedListeners.forEachIndexed { _, it ->
@@ -1385,8 +1415,24 @@
         }
     }
 
+    override fun migrateSystemState(state: AccessState) {
+        migration.migrateSystemState(state)
+    }
+
+    override fun migrateUserState(state: AccessState, userId: Int) {
+        migration.migrateUserState(state, userId)
+    }
+
+    override fun MutateStateScope.upgradePackageState(
+        packageState: PackageState,
+        userId: Int,
+        version: Int
+    ) {
+        with(upgrade) { upgradePermissions(packageState, userId, version) }
+    }
+
     companion object {
-        private val LOG_TAG = UidPermissionPolicy::class.java.simpleName
+        private val LOG_TAG = AppIdPermissionPolicy::class.java.simpleName
 
         private const val PLATFORM_PACKAGE_NAME = "android"
 
diff --git a/services/permission/java/com/android/server/permission/access/permission/AppIdPermissionUpgrade.kt b/services/permission/java/com/android/server/permission/access/permission/AppIdPermissionUpgrade.kt
new file mode 100644
index 0000000..9e70800
--- /dev/null
+++ b/services/permission/java/com/android/server/permission/access/permission/AppIdPermissionUpgrade.kt
@@ -0,0 +1,224 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.permission.access.permission
+
+import android.Manifest
+import android.os.Build
+import android.util.Log
+import com.android.server.permission.access.MutateStateScope
+import com.android.server.permission.access.collection.* // ktlint-disable no-wildcard-imports
+import com.android.server.permission.access.util.andInv
+import com.android.server.permission.access.util.hasAnyBit
+import com.android.server.permission.access.util.hasBits
+import com.android.server.pm.pkg.PackageState
+
+class AppIdPermissionUpgrade(private val policy: AppIdPermissionPolicy) {
+    /**
+     * Upgrade the package permissions, if needed.
+     *
+     * @param version package version
+     *
+     * @see [com.android.server.permission.access.util.PackageVersionMigration.getVersion]
+     */
+    fun MutateStateScope.upgradePermissions(
+        packageState: PackageState,
+        userId: Int,
+        version: Int
+    ) {
+        val packageName = packageState.packageName
+        if (version == 0 || version == 1) {
+            Log.v(LOG_TAG, "No version available for package: $packageName.")
+            return
+        }
+
+        // Upgrade from Pie
+        if (version == 2 || version == 3) {
+            Log.v(
+                LOG_TAG, "Allowlisting and upgrading background location permission for " +
+                    "package: $packageName, version: $version, user:$userId"
+            )
+            allowlistRestrictedPermissions(packageState, userId)
+            upgradeBackgroundLocationPermission(packageState, userId)
+        }
+        if (version <= 10) {
+            Log.v(
+                LOG_TAG, "Upgrading access media location permission for package: $packageName" +
+                    ", version: $version, user: $userId"
+            )
+            upgradeAccessMediaLocationPermission(packageState, userId)
+        }
+        // Enable isAtLeastT check, when moving subsystem to mainline.
+        if (version <= 12 /*&& SdkLevel.isAtLeastT()*/) {
+            Log.v(
+                LOG_TAG, "Upgrading scoped permissions for package: $packageName" +
+                    ", version: $version, user: $userId"
+            )
+            upgradeAuralVisualMediaPermissions(packageState, userId)
+        }
+        // Add a new upgrade step: if (packageVersion <= LATEST_VERSION) { .... }
+        // Also increase LATEST_VERSION
+    }
+
+    private fun MutateStateScope.allowlistRestrictedPermissions(
+        packageState: PackageState,
+        userId: Int
+    ) {
+        packageState.androidPackage!!.requestedPermissions.forEach { permissionName ->
+            if (permissionName in LEGACY_RESTRICTED_PERMISSIONS) {
+                with(policy) {
+                    updatePermissionFlags(
+                        packageState.appId, userId, permissionName,
+                        PermissionFlags.UPGRADE_EXEMPT, PermissionFlags.UPGRADE_EXEMPT
+                    )
+                }
+            }
+        }
+    }
+
+    private fun MutateStateScope.upgradeBackgroundLocationPermission(
+        packageState: PackageState,
+        userId: Int
+    ) {
+        val androidPackage = packageState.androidPackage!!
+        if (Manifest.permission.ACCESS_BACKGROUND_LOCATION in androidPackage.requestedPermissions) {
+            val permissionFlags =
+                state.userStates[userId].appIdPermissionFlags[packageState.appId]
+            val fineLocationFlags = permissionFlags[Manifest.permission.ACCESS_FINE_LOCATION] ?: 0
+            val coarseLocationFlags =
+                permissionFlags[Manifest.permission.ACCESS_COARSE_LOCATION] ?: 0
+            val isForegroundLocationGranted = PermissionFlags.isAppOpGranted(fineLocationFlags) ||
+                PermissionFlags.isAppOpGranted(coarseLocationFlags)
+            if (isForegroundLocationGranted) {
+                grantRuntimePermission(
+                    packageState, userId, Manifest.permission.ACCESS_BACKGROUND_LOCATION
+                )
+            }
+        }
+    }
+
+    private fun MutateStateScope.upgradeAccessMediaLocationPermission(
+        packageState: PackageState,
+        userId: Int
+    ) {
+        val androidPackage = packageState.androidPackage!!
+        if (Manifest.permission.ACCESS_MEDIA_LOCATION in androidPackage.requestedPermissions) {
+            val permissionFlags = state.userStates[userId].appIdPermissionFlags[packageState.appId]
+            val flags = permissionFlags[Manifest.permission.READ_EXTERNAL_STORAGE] ?: 0
+            if (PermissionFlags.isAppOpGranted(flags)) {
+                grantRuntimePermission(
+                    packageState, userId, Manifest.permission.ACCESS_MEDIA_LOCATION
+                )
+            }
+        }
+    }
+
+    private fun MutateStateScope.upgradeAuralVisualMediaPermissions(
+        packageState: PackageState,
+        userId: Int
+    ) {
+        val androidPackage = packageState.androidPackage!!
+        if (androidPackage.targetSdkVersion < Build.VERSION_CODES.TIRAMISU) {
+            return
+        }
+
+        val requestedPermissionNames = androidPackage.requestedPermissions
+        val permissionFlags = state.userStates[userId].appIdPermissionFlags[packageState.appId]
+        val isStorageUserGranted = requestedPermissionNames.anyIndexed { _, permissionName ->
+            val flags = permissionFlags[permissionName] ?: 0
+            permissionName in STORAGE_PERMISSIONS && PermissionFlags.isAppOpGranted(flags) &&
+                flags.hasBits(PermissionFlags.USER_SET)
+        }
+        if (isStorageUserGranted) {
+            requestedPermissionNames.forEachIndexed { _, permissionName ->
+                if (permissionName in AURAL_VISUAL_MEDIA_PERMISSIONS) {
+                    grantRuntimePermission(packageState, userId, permissionName)
+                }
+            }
+        }
+    }
+
+    private fun MutateStateScope.grantRuntimePermission(
+        packageState: PackageState,
+        userId: Int,
+        permissionName: String
+    ) {
+        Log.v(
+            LOG_TAG, "Granting runtime permission for package: ${packageState.packageName}, " +
+                "permission: $permissionName, userId: $userId"
+        )
+        val permission = state.systemState.permissions[permissionName]!!
+        if (packageState.getUserStateOrDefault(userId).isInstantApp && !permission.isInstant) {
+            return
+        }
+
+        val appId = packageState.appId
+        val permissionFlags = state.userStates[userId].appIdPermissionFlags[appId]
+        var flags = permissionFlags[permission.name] ?: 0
+        if (flags.hasAnyBit(MASK_ANY_FIXED)) {
+            Log.v(
+                LOG_TAG,
+                "Not allowed to grant $permissionName to package ${packageState.packageName}"
+            )
+            return
+        }
+
+        flags = flags or PermissionFlags.RUNTIME_GRANTED
+        flags = flags andInv (
+            PermissionFlags.APP_OP_REVOKED or
+            PermissionFlags.IMPLICIT or
+            PermissionFlags.LEGACY_GRANTED or
+            PermissionFlags.HIBERNATION or
+            PermissionFlags.ONE_TIME
+        )
+        with(policy) {
+            setPermissionFlags(appId, userId, permissionName, flags)
+        }
+    }
+
+    companion object {
+        private val LOG_TAG = AppIdPermissionUpgrade::class.java.simpleName
+
+        private const val MASK_ANY_FIXED =
+            PermissionFlags.USER_SET or PermissionFlags.USER_FIXED or
+            PermissionFlags.POLICY_FIXED or PermissionFlags.SYSTEM_FIXED
+
+        private val LEGACY_RESTRICTED_PERMISSIONS = indexedSetOf(
+            Manifest.permission.ACCESS_BACKGROUND_LOCATION,
+            Manifest.permission.READ_EXTERNAL_STORAGE,
+            Manifest.permission.WRITE_EXTERNAL_STORAGE,
+            Manifest.permission.SEND_SMS,
+            Manifest.permission.RECEIVE_SMS,
+            Manifest.permission.RECEIVE_WAP_PUSH,
+            Manifest.permission.RECEIVE_MMS,
+            Manifest.permission.READ_CELL_BROADCASTS,
+            Manifest.permission.READ_CALL_LOG,
+            Manifest.permission.WRITE_CALL_LOG,
+            Manifest.permission.PROCESS_OUTGOING_CALLS
+        )
+
+        private val STORAGE_PERMISSIONS = indexedSetOf(
+            Manifest.permission.READ_EXTERNAL_STORAGE,
+            Manifest.permission.WRITE_EXTERNAL_STORAGE
+        )
+        private val AURAL_VISUAL_MEDIA_PERMISSIONS = indexedSetOf(
+            Manifest.permission.READ_MEDIA_AUDIO,
+            Manifest.permission.READ_MEDIA_IMAGES,
+            Manifest.permission.READ_MEDIA_VIDEO,
+            Manifest.permission.READ_MEDIA_VISUAL_USER_SELECTED
+        )
+    }
+}
diff --git a/services/permission/java/com/android/server/permission/access/permission/Permission.kt b/services/permission/java/com/android/server/permission/access/permission/Permission.kt
index 714480c..39b4eaf 100644
--- a/services/permission/java/com/android/server/permission/access/permission/Permission.kt
+++ b/services/permission/java/com/android/server/permission/access/permission/Permission.kt
@@ -140,9 +140,7 @@
         get() = permissionInfo.flags.hasBits(PermissionInfo.FLAG_SOFT_RESTRICTED)
 
     inline val isHardOrSoftRestricted: Boolean
-        get() = permissionInfo.flags.hasBits(
-            PermissionInfo.FLAG_HARD_RESTRICTED or PermissionInfo.FLAG_SOFT_RESTRICTED
-        )
+        get() = isHardRestricted || isSoftRestricted
 
     inline val isImmutablyRestricted: Boolean
         get() = permissionInfo.flags.hasBits(PermissionInfo.FLAG_IMMUTABLY_RESTRICTED)
diff --git a/services/permission/java/com/android/server/permission/access/permission/PermissionFlags.kt b/services/permission/java/com/android/server/permission/access/permission/PermissionFlags.kt
index 48658ff..550d148 100644
--- a/services/permission/java/com/android/server/permission/access/permission/PermissionFlags.kt
+++ b/services/permission/java/com/android/server/permission/access/permission/PermissionFlags.kt
@@ -22,6 +22,7 @@
 import android.os.Build
 import android.permission.PermissionManager
 import com.android.server.permission.access.util.andInv
+import com.android.server.permission.access.util.flagsToString
 import com.android.server.permission.access.util.hasAnyBit
 import com.android.server.permission.access.util.hasBits
 
@@ -137,7 +138,7 @@
      * For example, this flag may be set in
      * [com.android.server.pm.permission.DefaultPermissionGrantPolicy].
      *
-     * @see PackageManager.FLAG_PERMISSION_SYSTEM_FIXED
+     * @see PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT
      */
     const val PREGRANT = 1 shl 9
 
@@ -317,6 +318,11 @@
      */
     const val MASK_EXEMPT = INSTALLER_EXEMPT or SYSTEM_EXEMPT or UPGRADE_EXEMPT
 
+    /**
+     * Mask for all permission flags about permission restriction.
+     */
+    const val MASK_RESTRICTED = RESTRICTION_REVOKED or SOFT_RESTRICTED
+
     fun isPermissionGranted(flags: Int): Boolean {
         if (flags.hasBits(INSTALL_GRANTED)) {
             return true
@@ -477,4 +483,38 @@
         }
         return flags
     }
+
+    fun flagToString(flag: Int): String =
+        when (flag) {
+            INSTALL_GRANTED -> "INSTALL_GRANTED"
+            INSTALL_REVOKED -> "INSTALL_REVOKED"
+            PROTECTION_GRANTED -> "PROTECTION_GRANTED"
+            ROLE -> "ROLE"
+            RUNTIME_GRANTED -> "RUNTIME_GRANTED"
+            USER_SET -> "USER_SET"
+            USER_FIXED -> "USER_FIXED"
+            POLICY_FIXED -> "POLICY_FIXED"
+            SYSTEM_FIXED -> "SYSTEM_FIXED"
+            PREGRANT -> "PREGRANT"
+            LEGACY_GRANTED -> "LEGACY_GRANTED"
+            IMPLICIT_GRANTED -> "IMPLICIT_GRANTED"
+            IMPLICIT -> "IMPLICIT"
+            USER_SENSITIVE_WHEN_GRANTED -> "USER_SENSITIVE_WHEN_GRANTED"
+            USER_SENSITIVE_WHEN_REVOKED -> "USER_SENSITIVE_WHEN_REVOKED"
+            INSTALLER_EXEMPT -> "INSTALLER_EXEMPT"
+            SYSTEM_EXEMPT -> "SYSTEM_EXEMPT"
+            UPGRADE_EXEMPT -> "UPGRADE_EXEMPT"
+            RESTRICTION_REVOKED -> "RESTRICTION_REVOKED"
+            SOFT_RESTRICTED -> "SOFT_RESTRICTED"
+            APP_OP_REVOKED -> "APP_OP_REVOKED"
+            ONE_TIME -> "ONE_TIME"
+            HIBERNATION -> "HIBERNATION"
+            USER_SELECTED -> "USER_SELECTED"
+            else -> "0x${flag.toUInt().toString(16).uppercase()}"
+        }
+
+    fun toString(flags: Int): String = flags.flagsToString { flagToString(it) }
+
+    fun apiFlagsToString(apiFlags: Int): String =
+        apiFlags.flagsToString { PackageManager.permissionFlagToString(it) }
 }
diff --git a/services/permission/java/com/android/server/permission/access/permission/PermissionService.kt b/services/permission/java/com/android/server/permission/access/permission/PermissionService.kt
index de7dc3b..9146a05 100644
--- a/services/permission/java/com/android/server/permission/access/permission/PermissionService.kt
+++ b/services/permission/java/com/android/server/permission/access/permission/PermissionService.kt
@@ -65,7 +65,7 @@
 import com.android.server.permission.access.MutateStateScope
 import com.android.server.permission.access.PermissionUri
 import com.android.server.permission.access.UidUri
-import com.android.server.permission.access.appop.UidAppOpPolicy
+import com.android.server.permission.access.appop.AppIdAppOpPolicy
 import com.android.server.permission.access.collection.* // ktlint-disable no-wildcard-imports
 import com.android.server.permission.access.util.andInv
 import com.android.server.permission.access.util.hasAnyBit
@@ -101,7 +101,7 @@
     private val service: AccessCheckingService
 ) : PermissionManagerServiceInterface {
     private val policy =
-        service.getSchemePolicy(UidUri.SCHEME, PermissionUri.SCHEME) as UidPermissionPolicy
+        service.getSchemePolicy(UidUri.SCHEME, PermissionUri.SCHEME) as AppIdPermissionPolicy
 
     private val context = service.context
     private lateinit var metricsLogger: MetricsLogger
@@ -142,6 +142,12 @@
         userManagerInternal = LocalServices.getService(UserManagerInternal::class.java)
         userManagerService = UserManagerService.getInstance()
 
+        // The package info cache is the cache for package and permission information.
+        // Disable the package info and package permission caches locally but leave the
+        // checkPermission cache active.
+        PackageManager.invalidatePackageInfoCache();
+        PermissionManager.disablePackageNamePermissionCache();
+
         handlerThread = ServiceThread(LOG_TAG, Process.THREAD_PRIORITY_BACKGROUND, true)
             .apply { start() }
         handler = Handler(handlerThread.looper)
@@ -930,7 +936,8 @@
         permissionName: String,
         isGranted: Boolean
     ) {
-        val appOpPolicy = service.getSchemePolicy(UidUri.SCHEME, AppOpUri.SCHEME) as UidAppOpPolicy
+        val appOpPolicy = service.getSchemePolicy(UidUri.SCHEME, AppOpUri.SCHEME) as
+            AppIdAppOpPolicy
         val appOpName = AppOpsManager.permissionToOp(permissionName)
         val mode = if (isGranted) AppOpsManager.MODE_ALLOWED else AppOpsManager.MODE_ERRORED
         with(appOpPolicy) { setAppOpMode(packageState.appId, userId, appOpName, mode) }
@@ -1569,27 +1576,31 @@
                         return@forEachIndexed
                     }
 
-                    val wasAllowlisted = oldFlags.hasAnyBit(PermissionFlags.MASK_EXEMPT)
-                    val isAllowlisted = newFlags.hasAnyBit(PermissionFlags.MASK_EXEMPT)
+                    val isExempt = newFlags.hasAnyBit(PermissionFlags.MASK_EXEMPT)
 
                     // If the permission is policy fixed as granted but it is no longer
                     // on any of the allowlists we need to clear the policy fixed flag
                     // as allowlisting trumps policy i.e. policy cannot grant a non
                     // grantable permission.
                     if (oldFlags.hasBits(PermissionFlags.POLICY_FIXED)) {
-                        if (!isAllowlisted && wasGranted) {
+                        if (!isExempt && wasGranted) {
                             mask = mask or PermissionFlags.POLICY_FIXED
                             newFlags = newFlags andInv PermissionFlags.POLICY_FIXED
                         }
                     }
 
-                    // If we are allowlisting an app that does not support runtime permissions
-                    // we need to make sure it goes through the permission review UI at launch.
-                    if (androidPackage.targetSdkVersion < Build.VERSION_CODES.M &&
-                        !wasAllowlisted && isAllowlisted) {
-                        mask = mask or PermissionFlags.IMPLICIT
-                        newFlags = newFlags or PermissionFlags.IMPLICIT
+                    newFlags = if (permission.isHardRestricted && !isExempt) {
+                        newFlags or PermissionFlags.RESTRICTION_REVOKED
+                    } else {
+                        newFlags andInv PermissionFlags.RESTRICTION_REVOKED
                     }
+                    newFlags = if (permission.isSoftRestricted && !isExempt) {
+                        newFlags or PermissionFlags.SOFT_RESTRICTED
+                    } else {
+                        newFlags andInv PermissionFlags.SOFT_RESTRICTED
+                    }
+                    mask = mask or PermissionFlags.RESTRICTION_REVOKED or
+                        PermissionFlags.SOFT_RESTRICTED
 
                     updatePermissionFlags(
                         appId, userId, requestedPermission, mask, newFlags
@@ -1600,11 +1611,23 @@
     }
 
     override fun resetRuntimePermissions(androidPackage: AndroidPackage, userId: Int) {
-        // TODO("Not yet implemented")
+        service.mutateState {
+            with(policy) {
+                resetRuntimePermissions(androidPackage.packageName, userId)
+            }
+        }
     }
 
     override fun resetRuntimePermissionsForUser(userId: Int) {
-        // TODO("Not yet implemented")
+        packageManagerLocal.withUnfilteredSnapshot().use { snapshot ->
+            service.mutateState {
+                snapshot.packageStates.forEach { (_, packageState) ->
+                    with(policy) {
+                        resetRuntimePermissions(packageState.packageName, userId)
+                    }
+                }
+            }
+        }
     }
 
     override fun addOnPermissionsChangeListener(listener: IOnPermissionsChangeListener) {
@@ -1856,6 +1879,18 @@
         params: PermissionManagerServiceInternal.PackageInstalledParams,
         userId: Int
     ) {
+        if (params === PermissionManagerServiceInternal.PackageInstalledParams.DEFAULT) {
+            // TODO: We should actually stop calling onPackageInstalled() when we are passing
+            //  PackageInstalledParams.DEFAULT in InstallPackageHelper, because there's actually no
+            //  installer in those  cases of system app installs, and the default params won't
+            //  allowlist any permissions which means the original UPGRADE_EXEMPT will be dropped
+            //  without any INSTALLER_EXEMPT added. However, we can't do that right now because the
+            //  old permission subsystem still depends on this method being called to set up the
+            //  permission state for the first time (which we are doing in onPackageAdded() or
+            //  onStorageVolumeMounted() now).
+            return
+        }
+
         synchronized(mountedStorageVolumes) {
             if (androidPackage.volumeUuid !in mountedStorageVolumes) {
                 // Wait for the storage volume to be mounted and batch the state mutation there.
@@ -1881,6 +1916,14 @@
                 packageManagerInternal.getPackageStateInternal(androidPackage.packageName)!!
             addAllowlistedRestrictedPermissionsUnchecked(androidPackage, packageState.appId,
                 params.allowlistedRestrictedPermissions, userId)
+            if (!packageState.isSystem()) {
+                // Drop UPGRADE_EXEMPT for all permissions requested by this package since there's
+                // an installer and the installer has made a decision.
+                setAllowlistedRestrictedPermissionsUnchecked(
+                    androidPackage, packageState.appId, emptyList(),
+                    PackageManager.FLAG_PERMISSION_WHITELIST_UPGRADE, userId
+                )
+            }
             setRequestedPermissionStates(packageState, userId, params.permissionStates)
         }
     }
@@ -2090,7 +2133,7 @@
      * Callback invoked when interesting actions have been taken on a permission.
      */
     private inner class OnPermissionFlagsChangedListener :
-        UidPermissionPolicy.OnPermissionFlagsChangedListener() {
+        AppIdPermissionPolicy.OnPermissionFlagsChangedListener() {
         private var isPermissionFlagsChanged = false
 
         private val runtimePermissionChangedUids = IntSet()
diff --git a/services/permission/java/com/android/server/permission/access/util/AtomicFileExtensions.kt b/services/permission/java/com/android/server/permission/access/util/AtomicFileExtensions.kt
index 984dfb5..2c29332 100644
--- a/services/permission/java/com/android/server/permission/access/util/AtomicFileExtensions.kt
+++ b/services/permission/java/com/android/server/permission/access/util/AtomicFileExtensions.kt
@@ -16,17 +16,54 @@
 
 package com.android.server.permission.access.util
 
+import android.os.FileUtils
 import android.util.AtomicFile
+import android.util.Log
+import java.io.File
 import java.io.FileInputStream
+import java.io.FileNotFoundException
 import java.io.FileOutputStream
 import java.io.IOException
 
 /**
- * Read from an [AtomicFile] and close everything safely when done.
+ * Read from an [AtomicFile], fallback to reserve file to read the data.
+ */
+@Throws(Exception::class)
+inline fun AtomicFile.readWithReserveCopy(block: (FileInputStream) -> Unit) {
+    try {
+        openRead().use(block)
+    } catch (e: FileNotFoundException) {
+        throw e
+    } catch (e: Exception) {
+        Log.wtf("AccessPersistence", "Failed to read $this", e)
+        val reserveFile = File(baseFile.parentFile, baseFile.name + ".reservecopy")
+        try {
+            AtomicFile(reserveFile).openRead().use(block)
+        } catch (e2: Exception) {
+            Log.e("AccessPersistence", "Failed to read $reserveFile", e2)
+            throw e
+        }
+    }
+}
+
+/**
+ * Write to actual file and reserve file.
  */
 @Throws(IOException::class)
-inline fun AtomicFile.read(block: (FileInputStream) -> Unit) {
-    openRead().use(block)
+inline fun AtomicFile.writeWithReserveCopy(block: (FileOutputStream) -> Unit) {
+    val reserveFile = File(baseFile.parentFile, baseFile.name + ".reservecopy")
+    reserveFile.delete()
+    writeInlined(block)
+    try {
+        FileInputStream(baseFile).use { inputStream ->
+            FileOutputStream(reserveFile).use { outputStream ->
+                FileUtils.copy(inputStream, outputStream)
+                outputStream.fd.sync()
+            }
+        }
+    } catch (e: Exception) {
+        Log.e("AccessPersistence", "Failed to write $reserveFile", e)
+    }
 }
 
 /**
diff --git a/services/permission/java/com/android/server/permission/access/util/IntExtensions.kt b/services/permission/java/com/android/server/permission/access/util/IntExtensions.kt
index e71d7a1..bc3328c 100644
--- a/services/permission/java/com/android/server/permission/access/util/IntExtensions.kt
+++ b/services/permission/java/com/android/server/permission/access/util/IntExtensions.kt
@@ -21,3 +21,19 @@
 fun Int.hasBits(bits: Int): Boolean = this and bits == bits
 
 infix fun Int.andInv(other: Int): Int = this and other.inv()
+
+inline fun Int.flagsToString(flagToString: (Int) -> String): String {
+    var flags = this
+    return buildString {
+        append("[")
+        while (flags != 0) {
+            val flag = 1 shl flags.countTrailingZeroBits()
+            flags = flags andInv flag
+            append(flagToString(flag))
+            if (flags != 0) {
+                append('|')
+            }
+        }
+        append("]")
+    }
+}
diff --git a/services/permission/java/com/android/server/permission/access/util/PackageVersionMigration.kt b/services/permission/java/com/android/server/permission/access/util/PackageVersionMigration.kt
new file mode 100644
index 0000000..b4b185f
--- /dev/null
+++ b/services/permission/java/com/android/server/permission/access/util/PackageVersionMigration.kt
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.permission.access.util
+
+import android.util.Log
+import com.android.server.LocalServices
+import com.android.server.appop.AppOpMigrationHelper
+import com.android.server.permission.access.AccessPolicy
+import com.android.server.pm.permission.PermissionMigrationHelper
+
+object PackageVersionMigration {
+    /**
+     * This function returns a unified version for permissions and app-ops, this
+     * version is assigned to all migrated packages during OTA upgrade. Later this version is used
+     * in determining the upgrade steps for a package.
+     */
+    internal fun getVersion(userId: Int): Int {
+        val permissionMigrationHelper =
+            LocalServices.getService(PermissionMigrationHelper::class.java)
+        val permissionVersion = permissionMigrationHelper.getLegacyPermissionsVersion(userId)
+
+        val appOpMigrationHelper = LocalServices.getService(AppOpMigrationHelper::class.java)
+        val appOpVersion = appOpMigrationHelper.legacyAppOpVersion
+
+        return when {
+            // Both files don't exist.
+            permissionVersion == 0 && appOpVersion == -2 -> 0
+            // Permission file doesn't exit, app op file exist w/o version.
+            permissionVersion == 0 && appOpVersion == -1 -> 1
+            // Both file exist but w/o any version.
+            permissionVersion == -1 && appOpVersion == -1 -> 2
+            // Permission file exist w/o version, app op file has version as 1.
+            permissionVersion == -1 && appOpVersion == 1 -> 3
+            // merging combination of versions based on released android version
+            // permissions version 1-8 were released in Q, 9 in S and 10 in T
+            // app ops version 1 was released in P, 3 in U.
+            permissionVersion == 1 && appOpVersion == 1 -> 4
+            permissionVersion == 2 && appOpVersion == 1 -> 5
+            permissionVersion == 3 && appOpVersion == 1 -> 6
+            permissionVersion == 4 && appOpVersion == 1 -> 7
+            permissionVersion == 5 && appOpVersion == 1 -> 8
+            permissionVersion == 6 && appOpVersion == 1 -> 9
+            permissionVersion == 7 && appOpVersion == 1 -> 10
+            permissionVersion == 8 && appOpVersion == 1 -> 11
+            permissionVersion == 9 && appOpVersion == 1 -> 12
+            permissionVersion == 10 && appOpVersion == 1 -> 13
+            permissionVersion == 10 && appOpVersion == 3 -> AccessPolicy.VERSION_LATEST
+            else -> {
+                Log.w(
+                    "PackageVersionMigration", "Version combination not recognized, permission" +
+                        "version: $permissionVersion, app-op version: $appOpVersion"
+                )
+                AccessPolicy.VERSION_LATEST
+            }
+        }
+    }
+}
diff --git a/services/robotests/backup/Android.bp b/services/robotests/backup/Android.bp
index 506e156..e04dd68 100644
--- a/services/robotests/backup/Android.bp
+++ b/services/robotests/backup/Android.bp
@@ -36,6 +36,7 @@
         "services.backup",
         "services.core",
         "services.net",
+        "service-permission.stubs.system_server",
     ],
 
     libs: ["android.net.ipsec.ike.stubs.system"],
diff --git a/services/robotests/backup/src/com/android/server/backup/FullBackupJobTest.java b/services/robotests/backup/src/com/android/server/backup/FullBackupJobTest.java
index c8797e2..da0adb5 100644
--- a/services/robotests/backup/src/com/android/server/backup/FullBackupJobTest.java
+++ b/services/robotests/backup/src/com/android/server/backup/FullBackupJobTest.java
@@ -19,10 +19,13 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.Mockito.when;
+import static org.robolectric.Shadows.shadowOf;
 
 import android.annotation.UserIdInt;
+import android.app.job.JobInfo;
 import android.app.job.JobScheduler;
 import android.content.Context;
+import android.content.pm.PackageManager;
 import android.os.Handler;
 import android.os.UserHandle;
 import android.platform.test.annotations.Presubmit;
@@ -87,6 +90,25 @@
     }
 
     @Test
+    public void testSchedule_notWatch_requiresDeviceIdle() {
+        shadowOf(mContext.getPackageManager())
+                .setSystemFeature(PackageManager.FEATURE_WATCH, false);
+        FullBackupJob.schedule(mUserOneId, mContext, 0, mUserBackupManagerService);
+
+        JobInfo pendingJob = mShadowJobScheduler.getPendingJob(getJobIdForUserId(mUserOneId));
+        assertThat(pendingJob.isRequireDeviceIdle()).isTrue();
+    }
+
+    @Test
+    public void testSchedule_isWatch_doesNotRequireDeviceIdle() {
+        shadowOf(mContext.getPackageManager()).setSystemFeature(PackageManager.FEATURE_WATCH, true);
+        FullBackupJob.schedule(mUserOneId, mContext, 0, mUserBackupManagerService);
+
+        JobInfo pendingJob = mShadowJobScheduler.getPendingJob(getJobIdForUserId(mUserOneId));
+        assertThat(pendingJob.isRequireDeviceIdle()).isFalse();
+    }
+
+    @Test
     public void testCancel_afterCancelling_jobDoesntExist() {
         FullBackupJob.schedule(mUserOneId, mContext, 0, mUserBackupManagerService);
         FullBackupJob.schedule(mUserTwoId, mContext, 0, mUserBackupManagerService);
diff --git a/services/tests/InputMethodSystemServerTests/Android.bp b/services/tests/InputMethodSystemServerTests/Android.bp
index 07ddda3..36446f6 100644
--- a/services/tests/InputMethodSystemServerTests/Android.bp
+++ b/services/tests/InputMethodSystemServerTests/Android.bp
@@ -41,6 +41,7 @@
         "mockito-target-extended-minus-junit4",
         "platform-test-annotations",
         "services.core",
+        "service-permission.stubs.system_server",
         "servicestests-core-utils",
         "servicestests-utils-mockito-extended",
         "truth-prebuilt",
@@ -88,6 +89,7 @@
         "mockito-target-extended-minus-junit4",
         "platform-test-annotations",
         "services.core",
+        "service-permission.stubs.system_server",
         "servicestests-core-utils",
         "servicestests-utils-mockito-extended",
         "truth-prebuilt",
diff --git a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodManagerServiceTestBase.java b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodManagerServiceTestBase.java
index 9829e57..3d29ed5 100644
--- a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodManagerServiceTestBase.java
+++ b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodManagerServiceTestBase.java
@@ -34,6 +34,7 @@
 import android.app.ActivityManagerInternal;
 import android.content.Context;
 import android.content.pm.PackageManagerInternal;
+import android.content.res.Configuration;
 import android.hardware.display.DisplayManagerInternal;
 import android.hardware.input.IInputManager;
 import android.hardware.input.InputManager;
@@ -121,6 +122,7 @@
     protected IInputMethodInvoker mMockInputMethodInvoker;
     protected InputMethodManagerService mInputMethodManagerService;
     protected ServiceThread mServiceThread;
+    protected boolean mIsLargeScreen;
 
     @BeforeClass
     public static void setupClass() {
@@ -145,6 +147,8 @@
         spyOn(mContext);
 
         mTargetSdkVersion = mContext.getApplicationInfo().targetSdkVersion;
+        mIsLargeScreen = mContext.getResources().getConfiguration()
+                .isLayoutSizeAtLeast(Configuration.SCREENLAYOUT_SIZE_LARGE);
         mCallingUserId = UserHandle.getCallingUserId();
         mEditorInfo = new EditorInfo();
         mEditorInfo.packageName = TEST_EDITOR_PKG_NAME;
diff --git a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodManagerServiceWindowGainedFocusTest.java b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodManagerServiceWindowGainedFocusTest.java
index c6b355c..cea65b5 100644
--- a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodManagerServiceWindowGainedFocusTest.java
+++ b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodManagerServiceWindowGainedFocusTest.java
@@ -124,7 +124,8 @@
 
         switch (mSoftInputState) {
             case SOFT_INPUT_STATE_UNSPECIFIED:
-                boolean showSoftInput = mSoftInputAdjustment == SOFT_INPUT_ADJUST_RESIZE;
+                boolean showSoftInput =
+                        (mSoftInputAdjustment == SOFT_INPUT_ADJUST_RESIZE) || mIsLargeScreen;
                 verifyShowSoftInput(
                         showSoftInput /* setVisible */, showSoftInput /* showSoftInput */);
                 // Soft input was hidden by default, so it doesn't need to call
@@ -165,7 +166,8 @@
 
         switch (mSoftInputState) {
             case SOFT_INPUT_STATE_UNSPECIFIED:
-                boolean hideSoftInput = mSoftInputAdjustment != SOFT_INPUT_ADJUST_RESIZE;
+                boolean hideSoftInput =
+                        (mSoftInputAdjustment != SOFT_INPUT_ADJUST_RESIZE) && !mIsLargeScreen;
                 verifyShowSoftInput(false /* setVisible */, false /* showSoftInput */);
                 // Soft input was hidden by default, so it doesn't need to call
                 // {@code IMS#hideSoftInput()}.
diff --git a/services/tests/InputMethodSystemServerTests/test-apps/SimpleTestIme/res/values/dimens.xml b/services/tests/InputMethodSystemServerTests/test-apps/SimpleTestIme/res/values/dimens.xml
index 1a4959e..5d91bd2 100644
--- a/services/tests/InputMethodSystemServerTests/test-apps/SimpleTestIme/res/values/dimens.xml
+++ b/services/tests/InputMethodSystemServerTests/test-apps/SimpleTestIme/res/values/dimens.xml
@@ -16,9 +16,9 @@
   -->
 
 <resources>
-    <dimen name="text_size_normal">24dp</dimen>
+    <dimen name="text_size_normal">20dp</dimen>
     <dimen name="text_size_symbol">14dp</dimen>
 
-    <dimen name="keyboard_header_height">40dp</dimen>
-    <dimen name="keyboard_row_height">50dp</dimen>
+    <dimen name="keyboard_header_height">30dp</dimen>
+    <dimen name="keyboard_row_height">40dp</dimen>
 </resources>
\ No newline at end of file
diff --git a/services/tests/PackageManagerComponentOverrideTests/Android.bp b/services/tests/PackageManagerComponentOverrideTests/Android.bp
index 19fdf60..bc36970 100644
--- a/services/tests/PackageManagerComponentOverrideTests/Android.bp
+++ b/services/tests/PackageManagerComponentOverrideTests/Android.bp
@@ -29,12 +29,13 @@
 android_test {
     name: "PackageManagerComponentOverrideTests",
     srcs: [
-        "src/**/*.kt"
+        "src/**/*.kt",
     ],
     static_libs: [
         "androidx.test.runner",
         "mockito-target-extended-minus-junit4",
         "services.core",
+        "service-permission.stubs.system_server",
         "servicestests-utils-mockito-extended",
         "testng", // TODO: remove once Android migrates to JUnit 4.12, which provides assertThrows
         "truth-prebuilt",
diff --git a/services/tests/PackageManagerServiceTests/server/Android.bp b/services/tests/PackageManagerServiceTests/server/Android.bp
index 1146271..92e4560 100644
--- a/services/tests/PackageManagerServiceTests/server/Android.bp
+++ b/services/tests/PackageManagerServiceTests/server/Android.bp
@@ -43,7 +43,6 @@
         "ShortcutManagerTestUtils",
         "truth-prebuilt",
         "testables",
-        "ub-uiautomator",
         "platformprotosnano",
         "framework-protos",
         "hamcrest-library",
diff --git a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/AppsFilterImplTest.java b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/AppsFilterImplTest.java
index 7909ba4..d5cd6ef9 100644
--- a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/AppsFilterImplTest.java
+++ b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/AppsFilterImplTest.java
@@ -224,7 +224,6 @@
 
         MockitoAnnotations.initMocks(this);
         when(mSnapshot.getPackageStates()).thenAnswer(x -> mExisting);
-        when(mSnapshot.getAllSharedUsers()).thenReturn(mSharedUserSettings);
         when(mSnapshot.getUserInfos()).thenReturn(USER_INFO_LIST);
         when(mSnapshot.getSharedUser(anyInt())).thenAnswer(invocation -> {
             final int sharedUserAppId = invocation.getArgument(0);
diff --git a/services/tests/mockingservicestests/src/com/android/server/RescuePartyTest.java b/services/tests/mockingservicestests/src/com/android/server/RescuePartyTest.java
index 1a75170..7b771af 100644
--- a/services/tests/mockingservicestests/src/com/android/server/RescuePartyTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/RescuePartyTest.java
@@ -567,36 +567,36 @@
 
         // Ensure that no action is taken for cases where the failure reason is unknown
         assertEquals(observer.onHealthCheckFailed(null, PackageWatchdog.FAILURE_REASON_UNKNOWN, 1),
-                PackageHealthObserverImpact.USER_IMPACT_NONE);
+                PackageHealthObserverImpact.USER_IMPACT_LEVEL_0);
 
         // Ensure the correct user impact is returned for each mitigation count.
         assertEquals(observer.onHealthCheckFailed(null,
                 PackageWatchdog.FAILURE_REASON_APP_NOT_RESPONDING, 1),
-                PackageHealthObserverImpact.USER_IMPACT_LOW);
+                PackageHealthObserverImpact.USER_IMPACT_LEVEL_10);
 
         assertEquals(observer.onHealthCheckFailed(null,
                 PackageWatchdog.FAILURE_REASON_APP_NOT_RESPONDING, 2),
-                PackageHealthObserverImpact.USER_IMPACT_LOW);
+                PackageHealthObserverImpact.USER_IMPACT_LEVEL_10);
 
         assertEquals(observer.onHealthCheckFailed(null,
                 PackageWatchdog.FAILURE_REASON_APP_NOT_RESPONDING, 3),
-                PackageHealthObserverImpact.USER_IMPACT_HIGH);
+                PackageHealthObserverImpact.USER_IMPACT_LEVEL_50);
 
         assertEquals(observer.onHealthCheckFailed(null,
                 PackageWatchdog.FAILURE_REASON_APP_NOT_RESPONDING, 4),
-                PackageHealthObserverImpact.USER_IMPACT_HIGH);
+                PackageHealthObserverImpact.USER_IMPACT_LEVEL_50);
     }
 
     @Test
     public void testBootLoopLevels() {
         RescuePartyObserver observer = RescuePartyObserver.getInstance(mMockContext);
 
-        assertEquals(observer.onBootLoop(0), PackageHealthObserverImpact.USER_IMPACT_NONE);
-        assertEquals(observer.onBootLoop(1), PackageHealthObserverImpact.USER_IMPACT_LOW);
-        assertEquals(observer.onBootLoop(2), PackageHealthObserverImpact.USER_IMPACT_LOW);
-        assertEquals(observer.onBootLoop(3), PackageHealthObserverImpact.USER_IMPACT_HIGH);
-        assertEquals(observer.onBootLoop(4), PackageHealthObserverImpact.USER_IMPACT_HIGH);
-        assertEquals(observer.onBootLoop(5), PackageHealthObserverImpact.USER_IMPACT_HIGH);
+        assertEquals(observer.onBootLoop(0), PackageHealthObserverImpact.USER_IMPACT_LEVEL_0);
+        assertEquals(observer.onBootLoop(1), PackageHealthObserverImpact.USER_IMPACT_LEVEL_10);
+        assertEquals(observer.onBootLoop(2), PackageHealthObserverImpact.USER_IMPACT_LEVEL_10);
+        assertEquals(observer.onBootLoop(3), PackageHealthObserverImpact.USER_IMPACT_LEVEL_50);
+        assertEquals(observer.onBootLoop(4), PackageHealthObserverImpact.USER_IMPACT_LEVEL_50);
+        assertEquals(observer.onBootLoop(5), PackageHealthObserverImpact.USER_IMPACT_LEVEL_100);
     }
 
     @Test
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/AsyncProcessStartTest.java b/services/tests/mockingservicestests/src/com/android/server/am/AsyncProcessStartTest.java
index 7c5d96e..70ee4f4 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/AsyncProcessStartTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/AsyncProcessStartTest.java
@@ -200,7 +200,7 @@
             return null;
         }).when(thread).bindApplication(
                 any(), any(),
-                any(), any(),
+                any(), any(), anyBoolean(),
                 any(), any(),
                 any(), any(),
                 any(),
@@ -260,7 +260,7 @@
                 /* expectedStartSeq */ 0, /* procAttached */ false);
 
         app.getThread().bindApplication(PACKAGE, appInfo,
-                null, null,
+                null, null, false,
                 null,
                 null,
                 null, null,
diff --git a/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsLegacyRestrictionsTest.java b/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsLegacyRestrictionsTest.java
index 021d01c..1973428 100644
--- a/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsLegacyRestrictionsTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsLegacyRestrictionsTest.java
@@ -57,7 +57,7 @@
     Handler mHandler;
 
     @Mock
-    AppOpsCheckingServiceInterface mLegacyAppOpsService;
+    AppOpsRestrictions.AppOpsRestrictionRemovedListener mRestrictionRemovedListener;
 
     AppOpsRestrictions mAppOpsRestrictions;
 
@@ -75,7 +75,8 @@
             r.run();
             return true;
         });
-        mAppOpsRestrictions = new AppOpsRestrictionsImpl(mContext, mHandler, mLegacyAppOpsService);
+        mAppOpsRestrictions = new AppOpsRestrictionsImpl(mContext, mHandler,
+                mRestrictionRemovedListener);
     }
 
     @After
@@ -271,7 +272,7 @@
     public void testNotify() {
         mAppOpsRestrictions.setUserRestriction(mClientToken, mUserId1, mOpCode1, true, null);
         mAppOpsRestrictions.clearUserRestrictions(mClientToken);
-        Mockito.verify(mLegacyAppOpsService, Mockito.times(1))
-                .notifyWatchersOfChange(mOpCode1, UID_ANY);
+        Mockito.verify(mRestrictionRemovedListener, Mockito.times(1))
+                .onAppOpsRestrictionRemoved(mOpCode1);
     }
 }
diff --git a/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsServiceTest.java
index 44ec26e..12853cd 100644
--- a/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsServiceTest.java
@@ -23,6 +23,7 @@
 import static android.app.AppOpsManager.OP_READ_SMS;
 import static android.app.AppOpsManager.OP_WIFI_SCAN;
 import static android.app.AppOpsManager.OP_WRITE_SMS;
+import static android.os.UserHandle.getAppId;
 import static android.os.UserHandle.getUserId;
 
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
@@ -108,6 +109,7 @@
         mAppOpsService = new AppOpsService(mRecentAccessesFile, mStorageFile, mHandler,
                 spy(sContext));
         mAppOpsService.mHistoricalRegistry.systemReady(sContext.getContentResolver());
+        mAppOpsService.prepareInternalCallbacks();
 
         // Always approve all permission checks
         doNothing().when(mAppOpsService.mContext).enforcePermission(anyString(), anyInt(),
@@ -184,6 +186,16 @@
         // Mock behavior to use specific Settings.Global.APPOP_HISTORY_PARAMETERS
         doReturn(null).when(() -> Settings.Global.getString(any(ContentResolver.class),
                 eq(Settings.Global.APPOP_HISTORY_PARAMETERS)));
+
+        prepareInstallInvocation(mockPackageManagerInternal);
+    }
+
+    private void prepareInstallInvocation(PackageManagerInternal mockPackageManagerInternal) {
+        when(mockPackageManagerInternal.getPackageList(any())).thenAnswer(invocation -> {
+            PackageManagerInternal.PackageListObserver observer = invocation.getArgument(0);
+            observer.onPackageAdded(sMyPackageName, getAppId(mMyUid));
+            return null;
+        });
     }
 
     @Test
diff --git a/services/tests/mockingservicestests/src/com/android/server/location/altitude/AltitudeConverterTest.java b/services/tests/mockingservicestests/src/com/android/server/location/altitude/AltitudeConverterTest.java
index 0d9aeb5..8d9a6c5 100644
--- a/services/tests/mockingservicestests/src/com/android/server/location/altitude/AltitudeConverterTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/location/altitude/AltitudeConverterTest.java
@@ -49,10 +49,10 @@
 
     @Test
     public void testAddMslAltitudeToLocation_expectedBehavior() throws IOException {
-        // Interpolates between bffffc, 955554, and 000004.
+        // Interpolates in boundary region (bffffc).
         Location location = new Location("");
-        location.setLatitude(-35.246789);
-        location.setLongitude(-44.962683);
+        location.setLatitude(-35.334815);
+        location.setLongitude(-45);
         location.setAltitude(-1);
         location.setVerticalAccuracyMeters(1);
         // Requires data to be loaded from raw assets.
@@ -61,43 +61,27 @@
         assertThat(location.hasMslAltitudeAccuracy()).isFalse();
         // Loads data from raw assets.
         mAltitudeConverter.addMslAltitudeToLocation(mContext, location);
-        assertThat(location.getMslAltitudeMeters()).isWithin(2).of(5.1076);
+        assertThat(location.getMslAltitudeMeters()).isWithin(2).of(5.0622);
         assertThat(location.getMslAltitudeAccuracyMeters()).isGreaterThan(1f);
         assertThat(location.getMslAltitudeAccuracyMeters()).isLessThan(1.1f);
 
-        // Again interpolates between bffffc, 955554, and 000004.
+        // Again interpolates at same location to assert no loading from raw assets. Also checks
+        // behavior w.r.t. invalid vertical accuracy.
         location = new Location("");
-        location.setLatitude(-35.246789);
-        location.setLongitude(-44.962683);
-        location.setAltitude(-1);
-        location.setVerticalAccuracyMeters(1);
-        // Requires no data to be loaded from raw assets.
-        assertThat(mAltitudeConverter.addMslAltitudeToLocation(location)).isTrue();
-        assertThat(location.getMslAltitudeMeters()).isWithin(2).of(5.1076);
-        assertThat(location.getMslAltitudeAccuracyMeters()).isGreaterThan(1f);
-        assertThat(location.getMslAltitudeAccuracyMeters()).isLessThan(1.1f);
-        // Results in same outcome.
-        mAltitudeConverter.addMslAltitudeToLocation(mContext, location);
-        assertThat(location.getMslAltitudeMeters()).isWithin(2).of(5.1076);
-        assertThat(location.getMslAltitudeAccuracyMeters()).isGreaterThan(1f);
-        assertThat(location.getMslAltitudeAccuracyMeters()).isLessThan(1.1f);
-
-        // Interpolate between 955554, 000004, 00000c, and 95554c - no vertical accuracy.
-        location = new Location("");
-        location.setLatitude(-35.176383);
-        location.setLongitude(-44.962683);
+        location.setLatitude(-35.334815);
+        location.setLongitude(-45);
         location.setAltitude(-1);
         location.setVerticalAccuracyMeters(-1); // Invalid vertical accuracy
         // Requires no data to be loaded from raw assets.
         assertThat(mAltitudeConverter.addMslAltitudeToLocation(location)).isTrue();
-        assertThat(location.getMslAltitudeMeters()).isWithin(2).of(5.1919);
+        assertThat(location.getMslAltitudeMeters()).isWithin(2).of(5.0622);
         assertThat(location.hasMslAltitudeAccuracy()).isFalse();
         // Results in same outcome.
         mAltitudeConverter.addMslAltitudeToLocation(mContext, location);
-        assertThat(location.getMslAltitudeMeters()).isWithin(2).of(5.1919);
+        assertThat(location.getMslAltitudeMeters()).isWithin(2).of(5.0622);
         assertThat(location.hasMslAltitudeAccuracy()).isFalse();
 
-        // Interpolates somewhere else more interesting, i.e., Hawaii.
+        // Interpolates out of boundary region, e.g., Hawaii.
         location = new Location("");
         location.setLatitude(19.545519);
         location.setLongitude(-155.998774);
@@ -112,6 +96,29 @@
         assertThat(location.getMslAltitudeMeters()).isWithin(2).of(-19.2359);
         assertThat(location.getMslAltitudeAccuracyMeters()).isGreaterThan(1f);
         assertThat(location.getMslAltitudeAccuracyMeters()).isLessThan(1.1f);
+
+        // The following round out test coverage for boundary regions.
+
+        location = new Location("");
+        location.setLatitude(-35.229154);
+        location.setLongitude(44.925335);
+        location.setAltitude(-1);
+        mAltitudeConverter.addMslAltitudeToLocation(mContext, location);
+        assertThat(location.getMslAltitudeMeters()).isWithin(2).of(-34.1913);
+
+        location = new Location("");
+        location.setLatitude(-35.334815);
+        location.setLongitude(45);
+        location.setAltitude(-1);
+        mAltitudeConverter.addMslAltitudeToLocation(mContext, location);
+        assertThat(location.getMslAltitudeMeters()).isWithin(2).of(-34.2258);
+
+        location = new Location("");
+        location.setLatitude(35.229154);
+        location.setLongitude(-44.925335);
+        location.setAltitude(-1);
+        mAltitudeConverter.addMslAltitudeToLocation(mContext, location);
+        assertThat(location.getMslAltitudeMeters()).isWithin(2).of(-11.0691);
     }
 
     @Test
@@ -122,15 +129,15 @@
 
         location.setLatitude(Double.NaN);
         assertThrows(IllegalArgumentException.class,
-                () -> mAltitudeConverter.addMslAltitudeToLocation(location));
+                () -> mAltitudeConverter.addMslAltitudeToLocation(mContext, location));
 
         location.setLatitude(91);
         assertThrows(IllegalArgumentException.class,
-                () -> mAltitudeConverter.addMslAltitudeToLocation(location));
+                () -> mAltitudeConverter.addMslAltitudeToLocation(mContext, location));
 
         location.setLatitude(-91);
         assertThrows(IllegalArgumentException.class,
-                () -> mAltitudeConverter.addMslAltitudeToLocation(location));
+                () -> mAltitudeConverter.addMslAltitudeToLocation(mContext, location));
     }
 
     @Test
@@ -141,15 +148,15 @@
 
         location.setLongitude(Double.NaN);
         assertThrows(IllegalArgumentException.class,
-                () -> mAltitudeConverter.addMslAltitudeToLocation(location));
+                () -> mAltitudeConverter.addMslAltitudeToLocation(mContext, location));
 
         location.setLongitude(181);
         assertThrows(IllegalArgumentException.class,
-                () -> mAltitudeConverter.addMslAltitudeToLocation(location));
+                () -> mAltitudeConverter.addMslAltitudeToLocation(mContext, location));
 
         location.setLongitude(-181);
         assertThrows(IllegalArgumentException.class,
-                () -> mAltitudeConverter.addMslAltitudeToLocation(location));
+                () -> mAltitudeConverter.addMslAltitudeToLocation(mContext, location));
     }
 
     @Test
@@ -159,14 +166,14 @@
         location.setLongitude(-44.962683);
 
         assertThrows(IllegalArgumentException.class,
-                () -> mAltitudeConverter.addMslAltitudeToLocation(location));
+                () -> mAltitudeConverter.addMslAltitudeToLocation(mContext, location));
 
         location.setAltitude(Double.NaN);
         assertThrows(IllegalArgumentException.class,
-                () -> mAltitudeConverter.addMslAltitudeToLocation(location));
+                () -> mAltitudeConverter.addMslAltitudeToLocation(mContext, location));
 
         location.setAltitude(Double.POSITIVE_INFINITY);
         assertThrows(IllegalArgumentException.class,
-                () -> mAltitudeConverter.addMslAltitudeToLocation(location));
+                () -> mAltitudeConverter.addMslAltitudeToLocation(mContext, location));
     }
 }
diff --git a/services/tests/mockingservicestests/src/com/android/server/location/injector/FakeEmergencyHelper.java b/services/tests/mockingservicestests/src/com/android/server/location/injector/FakeEmergencyHelper.java
index 2cf57da..7ee411b 100644
--- a/services/tests/mockingservicestests/src/com/android/server/location/injector/FakeEmergencyHelper.java
+++ b/services/tests/mockingservicestests/src/com/android/server/location/injector/FakeEmergencyHelper.java
@@ -27,6 +27,7 @@
 
     public void setInEmergency(boolean inEmergency) {
         mInEmergency = inEmergency;
+        dispatchEmergencyStateChanged();
     }
 
     @Override
diff --git a/services/tests/mockingservicestests/src/com/android/server/location/provider/LocationProviderManagerTest.java b/services/tests/mockingservicestests/src/com/android/server/location/provider/LocationProviderManagerTest.java
index 7dc1935..293003d 100644
--- a/services/tests/mockingservicestests/src/com/android/server/location/provider/LocationProviderManagerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/location/provider/LocationProviderManagerTest.java
@@ -80,8 +80,12 @@
 import android.os.RemoteException;
 import android.os.WorkSource;
 import android.platform.test.annotations.Presubmit;
+import android.provider.DeviceConfig;
+import android.provider.Settings;
 import android.util.Log;
 
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.filters.MediumTest;
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
@@ -174,6 +178,8 @@
         doReturn(mResources).when(mContext).getResources();
         doReturn(mPackageManager).when(mContext).getPackageManager();
         doReturn(mPowerManager).when(mContext).getSystemService(PowerManager.class);
+        doReturn(ApplicationProvider.getApplicationContext()).when(
+                mContext).getApplicationContext();
         doReturn(mWakeLock).when(mPowerManager).newWakeLock(anyInt(), anyString());
         doReturn(PackageManager.PERMISSION_DENIED)
                 .when(mContext)
@@ -210,6 +216,8 @@
 
     @After
     public void tearDown() throws Exception {
+        DeviceConfig.resetToDefaults(Settings.RESET_MODE_PACKAGE_DEFAULTS,
+                DeviceConfig.NAMESPACE_LOCATION);
         LocalServices.removeServiceForTest(LocationManagerInternal.class);
 
         // some test failures may leave the fg thread stuck, interrupt until we get out of it
@@ -1339,6 +1347,144 @@
         assertThat(mManager.isVisibleToCaller()).isFalse();
     }
 
+    @MediumTest
+    @Test
+    public void testEnableMsl_expectedBehavior() throws Exception {
+        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_LOCATION,
+                "enable_location_provider_manager_msl", Boolean.toString(true), false);
+
+        // Create a random location and set provider location to cache necessary MSL assets.
+        Location loc = createLocation(NAME, mRandom);
+        loc.setAltitude(mRandom.nextDouble());
+        loc.setVerticalAccuracyMeters(mRandom.nextFloat());
+        mProvider.setProviderLocation(LocationResult.wrap(loc));
+        Thread.sleep(1000);
+
+        // Register listener and reset provider location to capture.
+        ILocationListener listener = createMockLocationListener();
+        LocationRequest request = new LocationRequest.Builder(0).setWorkSource(WORK_SOURCE).build();
+        mPassive.registerLocationRequest(request, IDENTITY, PERMISSION_FINE, listener);
+        mProvider.setProviderLocation(LocationResult.wrap(loc));
+        ArgumentCaptor<List<Location>> captor = ArgumentCaptor.forClass(List.class);
+        verify(listener).onLocationChanged(captor.capture(), nullable(IRemoteCallback.class));
+
+        // Assert that MSL fields are populated.
+        Location actual = captor.getValue().get(0);
+        assertThat(actual.hasMslAltitude()).isTrue();
+        assertThat(actual.hasMslAltitudeAccuracy()).isTrue();
+    }
+
+    @MediumTest
+    @Test
+    public void testEnableMsl_noVerticalAccuracy() throws Exception {
+        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_LOCATION,
+                "enable_location_provider_manager_msl", Boolean.toString(true), false);
+
+        // Create a random location and set provider location to cache necessary MSL assets.
+        Location loc = createLocation(NAME, mRandom);
+        loc.setAltitude(mRandom.nextDouble());
+        loc.setVerticalAccuracyMeters(mRandom.nextFloat());
+        mProvider.setProviderLocation(LocationResult.wrap(loc));
+        Thread.sleep(1000);
+
+        // Register listener and reset provider location with no vertical accuracy to capture.
+        ILocationListener listener = createMockLocationListener();
+        LocationRequest request = new LocationRequest.Builder(0).setWorkSource(WORK_SOURCE).build();
+        mPassive.registerLocationRequest(request, IDENTITY, PERMISSION_FINE, listener);
+        loc.removeVerticalAccuracy();
+        mProvider.setProviderLocation(LocationResult.wrap(loc));
+        ArgumentCaptor<List<Location>> captor = ArgumentCaptor.forClass(List.class);
+        verify(listener).onLocationChanged(captor.capture(), nullable(IRemoteCallback.class));
+
+        // Assert that only the MSL accuracy field is populated.
+        Location actual = captor.getValue().get(0);
+        assertThat(actual.hasMslAltitude()).isTrue();
+        assertThat(actual.hasMslAltitudeAccuracy()).isFalse();
+    }
+
+    @MediumTest
+    @Test
+    public void testEnableMsl_noAltitude() throws Exception {
+        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_LOCATION,
+                "enable_location_provider_manager_msl", Boolean.toString(true), false);
+
+        // Create a random location and set provider location to cache necessary MSL assets.
+        Location loc = createLocation(NAME, mRandom);
+        loc.setAltitude(mRandom.nextDouble());
+        loc.setVerticalAccuracyMeters(mRandom.nextFloat());
+        mProvider.setProviderLocation(LocationResult.wrap(loc));
+        Thread.sleep(1000);
+
+        // Register listener and reset provider location with no altitude to capture.
+        ILocationListener listener = createMockLocationListener();
+        LocationRequest request = new LocationRequest.Builder(0).setWorkSource(WORK_SOURCE).build();
+        mPassive.registerLocationRequest(request, IDENTITY, PERMISSION_FINE, listener);
+        loc.removeAltitude();
+        mProvider.setProviderLocation(LocationResult.wrap(loc));
+        ArgumentCaptor<List<Location>> captor = ArgumentCaptor.forClass(List.class);
+        verify(listener).onLocationChanged(captor.capture(), nullable(IRemoteCallback.class));
+
+        // Assert that no MSL fields are populated.
+        Location actual = captor.getValue().get(0);
+        assertThat(actual.hasMslAltitude()).isFalse();
+        assertThat(actual.hasMslAltitudeAccuracy()).isFalse();
+    }
+
+    @MediumTest
+    @Test
+    public void testEnableMsl_invalidAltitude() throws Exception {
+        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_LOCATION,
+                "enable_location_provider_manager_msl", Boolean.toString(true), false);
+
+        // Create a random location and set provider location to cache necessary MSL assets.
+        Location loc = createLocation(NAME, mRandom);
+        loc.setAltitude(mRandom.nextDouble());
+        loc.setVerticalAccuracyMeters(mRandom.nextFloat());
+        mProvider.setProviderLocation(LocationResult.wrap(loc));
+        Thread.sleep(1000);
+
+        // Register listener and reset provider location with invalid altitude to capture.
+        ILocationListener listener = createMockLocationListener();
+        LocationRequest request = new LocationRequest.Builder(0).setWorkSource(WORK_SOURCE).build();
+        mPassive.registerLocationRequest(request, IDENTITY, PERMISSION_FINE, listener);
+        loc.setAltitude(Double.POSITIVE_INFINITY);
+        mProvider.setProviderLocation(LocationResult.wrap(loc));
+        ArgumentCaptor<List<Location>> captor = ArgumentCaptor.forClass(List.class);
+        verify(listener).onLocationChanged(captor.capture(), nullable(IRemoteCallback.class));
+
+        // Assert that no MSL fields are populated.
+        Location actual = captor.getValue().get(0);
+        assertThat(actual.hasMslAltitude()).isFalse();
+        assertThat(actual.hasMslAltitudeAccuracy()).isFalse();
+    }
+
+    @MediumTest
+    @Test
+    public void testDisableMsl_expectedBehavior() throws Exception {
+        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_LOCATION,
+                "enable_location_provider_manager_msl", Boolean.toString(false), false);
+
+        // Create a random location and set provider location to cache necessary MSL assets.
+        Location loc = createLocation(NAME, mRandom);
+        loc.setAltitude(mRandom.nextDouble());
+        loc.setVerticalAccuracyMeters(mRandom.nextFloat());
+        mProvider.setProviderLocation(LocationResult.wrap(loc));
+        Thread.sleep(1000);
+
+        // Register listener and reset provider location to capture.
+        ILocationListener listener = createMockLocationListener();
+        LocationRequest request = new LocationRequest.Builder(0).setWorkSource(WORK_SOURCE).build();
+        mPassive.registerLocationRequest(request, IDENTITY, PERMISSION_FINE, listener);
+        mProvider.setProviderLocation(LocationResult.wrap(loc));
+        ArgumentCaptor<List<Location>> captor = ArgumentCaptor.forClass(List.class);
+        verify(listener).onLocationChanged(captor.capture(), nullable(IRemoteCallback.class));
+
+        // Assert that no MSL fields are populated.
+        Location actual = captor.getValue().get(0);
+        assertThat(actual.hasMslAltitude()).isFalse();
+        assertThat(actual.hasMslAltitudeAccuracy()).isFalse();
+    }
+
     private ILocationListener createMockLocationListener() {
         return spy(new ILocationListener.Stub() {
             @Override
diff --git a/services/tests/mockingservicestests/src/com/android/server/rollback/RollbackPackageHealthObserverTest.java b/services/tests/mockingservicestests/src/com/android/server/rollback/RollbackPackageHealthObserverTest.java
new file mode 100644
index 0000000..541b077
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/rollback/RollbackPackageHealthObserverTest.java
@@ -0,0 +1,248 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.rollback;
+
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.pm.VersionedPackage;
+import android.content.rollback.PackageRollbackInfo;
+import android.content.rollback.RollbackInfo;
+import android.content.rollback.RollbackManager;
+import android.util.Log;
+import android.util.Xml;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.dx.mockito.inline.extended.ExtendedMockito;
+import com.android.server.PackageWatchdog;
+import com.android.server.SystemConfig;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.junit.runner.RunWith;
+import org.mockito.Answers;
+import org.mockito.Mock;
+import org.mockito.MockitoSession;
+import org.mockito.quality.Strictness;
+import org.mockito.stubbing.Answer;
+import org.xmlpull.v1.XmlPullParser;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.List;
+import java.util.Scanner;
+
+
+@RunWith(AndroidJUnit4.class)
+public class RollbackPackageHealthObserverTest {
+    @Mock
+    private Context mMockContext;
+    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+    private PackageWatchdog mMockPackageWatchdog;
+    @Mock
+    RollbackManager mRollbackManager;
+    @Mock
+    RollbackInfo mRollbackInfo;
+    @Mock
+    PackageRollbackInfo mPackageRollbackInfo;
+
+    private MockitoSession mSession;
+    private static final String APP_A = "com.package.a";
+    private static final long VERSION_CODE = 1L;
+    private static final String LOG_TAG = "RollbackPackageHealthObserverTest";
+
+    private SystemConfig mSysConfig;
+
+    @Rule public TemporaryFolder mTemporaryFolder = new TemporaryFolder();
+
+    @Before
+    public void setup() {
+        mSysConfig = new SystemConfigTestClass();
+
+        mSession = ExtendedMockito.mockitoSession()
+                .initMocks(this)
+                .strictness(Strictness.LENIENT)
+                .spyStatic(PackageWatchdog.class)
+                .startMocking();
+
+        // Mock PackageWatchdog
+        doAnswer((Answer<PackageWatchdog>) invocationOnMock -> mMockPackageWatchdog)
+                .when(() -> PackageWatchdog.getInstance(mMockContext));
+
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        mSession.finishMocking();
+    }
+
+    /**
+     * Subclass of SystemConfig without running the constructor.
+     */
+    private class SystemConfigTestClass extends SystemConfig {
+        SystemConfigTestClass() {
+            super(false);
+        }
+    }
+
+    @Test
+    public void testHealthCheckLevels() {
+        RollbackPackageHealthObserver observer =
+                spy(new RollbackPackageHealthObserver(mMockContext));
+        VersionedPackage testFailedPackage = new VersionedPackage(APP_A, VERSION_CODE);
+
+
+        when(mMockContext.getSystemService(RollbackManager.class)).thenReturn(mRollbackManager);
+
+        // Crashes with no rollbacks available
+        assertEquals(PackageWatchdog.PackageHealthObserverImpact.USER_IMPACT_LEVEL_0,
+                observer.onHealthCheckFailed(null,
+                        PackageWatchdog.FAILURE_REASON_NATIVE_CRASH, 1));
+        assertEquals(PackageWatchdog.PackageHealthObserverImpact.USER_IMPACT_LEVEL_0,
+                observer.onHealthCheckFailed(null,
+                        PackageWatchdog.FAILURE_REASON_APP_CRASH, 1));
+
+        // Make the rollbacks available
+        when(mRollbackManager.getAvailableRollbacks()).thenReturn(List.of(mRollbackInfo));
+        when(mRollbackInfo.getPackages()).thenReturn(List.of(mPackageRollbackInfo));
+        when(mPackageRollbackInfo.getVersionRolledBackFrom()).thenReturn(testFailedPackage);
+
+        // native crash
+        assertEquals(PackageWatchdog.PackageHealthObserverImpact.USER_IMPACT_LEVEL_30,
+                observer.onHealthCheckFailed(null,
+                        PackageWatchdog.FAILURE_REASON_NATIVE_CRASH, 1));
+        // non-native crash
+        assertEquals(PackageWatchdog.PackageHealthObserverImpact.USER_IMPACT_LEVEL_30,
+                observer.onHealthCheckFailed(testFailedPackage,
+                        PackageWatchdog.FAILURE_REASON_APP_CRASH, 1));
+        // Second non-native crash again
+        assertEquals(PackageWatchdog.PackageHealthObserverImpact.USER_IMPACT_LEVEL_70,
+                observer.onHealthCheckFailed(testFailedPackage,
+                        PackageWatchdog.FAILURE_REASON_APP_CRASH, 2));
+        // Subsequent crashes when rollbacks have completed
+        when(mRollbackManager.getAvailableRollbacks()).thenReturn(List.of());
+        assertEquals(PackageWatchdog.PackageHealthObserverImpact.USER_IMPACT_LEVEL_0,
+                observer.onHealthCheckFailed(testFailedPackage,
+                        PackageWatchdog.FAILURE_REASON_APP_CRASH, 3));
+    }
+
+    /**
+     * Test that isAutomaticRollbackDenied works correctly when packages that are not
+     * denied are sent.
+     */
+    @Test
+    public void isRollbackAllowedTest_false() throws IOException {
+        final String contents =
+                "<config>\n"
+                + "    <automatic-rollback-denylisted-app package=\"com.android.vending\" />\n"
+                + "</config>";
+        final File folder = createTempSubfolder("folder");
+        createTempFile(folder, "automatic-rollback-denylisted-app.xml", contents);
+
+        readPermissions(folder, /* Grant all permission flags */ ~0);
+
+        assertThat(RollbackPackageHealthObserver.isAutomaticRollbackDenied(mSysConfig,
+                new VersionedPackage("com.test.package", 1))).isEqualTo(false);
+    }
+
+    /**
+     * Test that isAutomaticRollbackDenied works correctly when packages that are
+     * denied are sent.
+     */
+    @Test
+    public void isRollbackAllowedTest_true() throws IOException {
+        final String contents =
+                "<config>\n"
+                + "    <automatic-rollback-denylisted-app package=\"com.android.vending\" />\n"
+                + "</config>";
+        final File folder = createTempSubfolder("folder");
+        createTempFile(folder, "automatic-rollback-denylisted-app.xml", contents);
+
+        readPermissions(folder, /* Grant all permission flags */ ~0);
+
+        assertThat(RollbackPackageHealthObserver.isAutomaticRollbackDenied(mSysConfig,
+                new VersionedPackage("com.android.vending", 1))).isEqualTo(true);
+    }
+
+    /**
+     * Test that isAutomaticRollbackDenied works correctly when no config is present
+     */
+    @Test
+    public void isRollbackAllowedTest_noConfig() throws IOException {
+        final File folder = createTempSubfolder("folder");
+
+        readPermissions(folder, /* Grant all permission flags */ ~0);
+
+        assertThat(RollbackPackageHealthObserver.isAutomaticRollbackDenied(mSysConfig,
+                new VersionedPackage("com.android.vending", 1))).isEqualTo(false);
+    }
+
+    /**
+     * Creates folderName/fileName in the mTemporaryFolder and fills it with the contents.
+     *
+     * @param folder   pre-existing subdirectory of mTemporaryFolder to put the file
+     * @param fileName name of the file (e.g. filename.xml) to create
+     * @param contents contents to write to the file
+     * @return the newly created file
+     */
+    private File createTempFile(File folder, String fileName, String contents)
+            throws IOException {
+        File file = new File(folder, fileName);
+        BufferedWriter bw = new BufferedWriter(new FileWriter(file));
+        bw.write(contents);
+        bw.close();
+
+        // Print to logcat for test debugging.
+        Log.d(LOG_TAG, "Contents of file " + file.getAbsolutePath());
+        Scanner input = new Scanner(file);
+        while (input.hasNextLine()) {
+            Log.d(LOG_TAG, input.nextLine());
+        }
+
+        return file;
+    }
+
+    private void readPermissions(File libraryDir, int permissionFlag) {
+        final XmlPullParser parser = Xml.newPullParser();
+        mSysConfig.readPermissions(parser, libraryDir, permissionFlag);
+    }
+
+    /**
+     * Creates folderName/fileName in the mTemporaryFolder and fills it with the contents.
+     *
+     * @param folderName subdirectory of mTemporaryFolder to put the file, creating if needed
+     * @return the folder
+     */
+    private File createTempSubfolder(String folderName)
+            throws IOException {
+        File folder = new File(mTemporaryFolder.getRoot(), folderName);
+        folder.mkdirs();
+        return folder;
+    }
+}
diff --git a/services/tests/servicestests/Android.bp b/services/tests/servicestests/Android.bp
index 6f26a5f..627e9d7 100644
--- a/services/tests/servicestests/Android.bp
+++ b/services/tests/servicestests/Android.bp
@@ -36,6 +36,7 @@
         "services.net",
         "services.people",
         "services.usage",
+        "service-permission.stubs.system_server",
         "guava",
         "guava-android-testlib",
         "androidx.test.core",
diff --git a/services/tests/servicestests/src/com/android/server/am/AnrHelperTest.java b/services/tests/servicestests/src/com/android/server/am/AnrHelperTest.java
index 9578993..acdfee9 100644
--- a/services/tests/servicestests/src/com/android/server/am/AnrHelperTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/AnrHelperTest.java
@@ -26,6 +26,7 @@
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.timeout;
 import static org.mockito.Mockito.verify;
@@ -48,8 +49,10 @@
 import java.io.File;
 import java.lang.reflect.Field;
 import java.lang.reflect.Modifier;
+import java.util.concurrent.Callable;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Future;
 import java.util.concurrent.TimeUnit;
 
 /**
@@ -63,8 +66,9 @@
     private AnrHelper mAnrHelper;
 
     private ProcessRecord mAnrApp;
-    private ExecutorService mExecutorService;
+    private ExecutorService mAuxExecutorService;
 
+    private Future<File> mEarlyDumpFuture;
     @Rule
     public ServiceThreadRule mServiceThreadRule = new ServiceThreadRule();
 
@@ -91,9 +95,12 @@
                         return mServiceThreadRule.getThread().getThreadHandler();
                     }
                 }, mServiceThreadRule.getThread());
-            mExecutorService = mock(ExecutorService.class);
+            mAuxExecutorService = mock(ExecutorService.class);
+            final ExecutorService earlyDumpExecutorService = mock(ExecutorService.class);
+            mEarlyDumpFuture = mock(Future.class);
+            doReturn(mEarlyDumpFuture).when(earlyDumpExecutorService).submit(any(Callable.class));
 
-            mAnrHelper = new AnrHelper(service, mExecutorService);
+            mAnrHelper = new AnrHelper(service, mAuxExecutorService, earlyDumpExecutorService);
         });
     }
 
@@ -125,8 +132,8 @@
 
         verify(mAnrApp.mErrorState, timeout(TIMEOUT_MS)).appNotResponding(
                 eq(activityShortComponentName), eq(appInfo), eq(parentShortComponentName),
-                eq(parentProcess), eq(aboveSystem), eq(timeoutRecord), eq(mExecutorService),
-                eq(false) /* onlyDumpSelf */, eq(false) /*isContinuousAnr*/);
+                eq(parentProcess), eq(aboveSystem), eq(timeoutRecord), eq(mAuxExecutorService),
+                eq(false) /* onlyDumpSelf */, eq(false) /*isContinuousAnr*/, eq(mEarlyDumpFuture));
     }
 
     @Test
@@ -139,7 +146,7 @@
             processingLatch.await();
             return null;
         }).when(mAnrApp.mErrorState).appNotResponding(anyString(), any(), any(), any(),
-                anyBoolean(), any(), any(), anyBoolean(), anyBoolean());
+                anyBoolean(), any(), any(), anyBoolean(), anyBoolean(), any());
         final ApplicationInfo appInfo = new ApplicationInfo();
         final TimeoutRecord timeoutRecord = TimeoutRecord.forInputDispatchWindowUnresponsive(
                 "annotation");
@@ -162,7 +169,7 @@
         processingLatch.countDown();
         // There is only one ANR reported.
         verify(mAnrApp.mErrorState, timeout(TIMEOUT_MS).only()).appNotResponding(
-                anyString(), any(), any(), any(), anyBoolean(), any(), eq(mExecutorService),
-                anyBoolean(), anyBoolean());
+                anyString(), any(), any(), any(), anyBoolean(), any(), eq(mAuxExecutorService),
+                anyBoolean(), anyBoolean(), any());
     }
 }
diff --git a/services/tests/servicestests/src/com/android/server/am/ProcessRecordTests.java b/services/tests/servicestests/src/com/android/server/am/ProcessRecordTests.java
index 6350e22..d92b9f8 100644
--- a/services/tests/servicestests/src/com/android/server/am/ProcessRecordTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/ProcessRecordTests.java
@@ -203,6 +203,6 @@
         processErrorState.appNotResponding(null /* activityShortComponentName */, null /* aInfo */,
                 null /* parentShortComponentName */, null /* parentProcess */,
                 false /* aboveSystem */, timeoutRecord, mExecutorService, false /* onlyDumpSelf */,
-                false /*isContinuousAnr*/);
+                false /*isContinuousAnr*/, null);
     }
 }
diff --git a/services/tests/servicestests/src/com/android/server/appop/AppOpsNotedWatcherTest.java b/services/tests/servicestests/src/com/android/server/appop/AppOpsNotedWatcherTest.java
index 47fdcb6..b5229d8 100644
--- a/services/tests/servicestests/src/com/android/server/appop/AppOpsNotedWatcherTest.java
+++ b/services/tests/servicestests/src/com/android/server/appop/AppOpsNotedWatcherTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.server.appops;
+package com.android.server.appop;
 
 import static org.mockito.Mockito.eq;
 import static org.mockito.Mockito.inOrder;
diff --git a/services/tests/servicestests/src/com/android/server/attention/AttentionManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/attention/AttentionManagerServiceTest.java
index 897b91e..3475c8f 100644
--- a/services/tests/servicestests/src/com/android/server/attention/AttentionManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/attention/AttentionManagerServiceTest.java
@@ -71,6 +71,7 @@
 @SmallTest
 public class AttentionManagerServiceTest {
     private static final double PROXIMITY_SUCCESS_STATE = 1.0;
+
     private AttentionManagerService mSpyAttentionManager;
     private final int mTimeout = 1000;
     private final Object mLock = new Object();
@@ -125,8 +126,19 @@
     }
 
     @Test
+    public void testRegisterProximityUpdates_returnFalseWhenProximityDisabled() {
+        mSpyAttentionManager.mIsServiceEnabled = true;
+        mSpyAttentionManager.mIsProximityEnabled = false;
+
+        assertThat(mSpyAttentionManager.onStartProximityUpdates(
+                mMockProximityUpdateCallbackInternal))
+                .isFalse();
+    }
+
+    @Test
     public void testRegisterProximityUpdates_returnFalseWhenServiceUnavailable() {
         mSpyAttentionManager.mIsServiceEnabled = true;
+        mSpyAttentionManager.mIsProximityEnabled = true;
         doReturn(false).when(mSpyAttentionManager).isServiceAvailable();
 
         assertThat(mSpyAttentionManager.onStartProximityUpdates(
@@ -138,6 +150,7 @@
     public void testRegisterProximityUpdates_returnFalseWhenPowerManagerNotInteract()
             throws RemoteException {
         mSpyAttentionManager.mIsServiceEnabled = true;
+        mSpyAttentionManager.mIsProximityEnabled = true;
         doReturn(true).when(mSpyAttentionManager).isServiceAvailable();
         doReturn(false).when(mMockIPowerManager).isInteractive();
 
@@ -149,6 +162,7 @@
     @Test
     public void testRegisterProximityUpdates_callOnSuccess() throws RemoteException {
         mSpyAttentionManager.mIsServiceEnabled = true;
+        mSpyAttentionManager.mIsProximityEnabled = true;
         doReturn(true).when(mSpyAttentionManager).isServiceAvailable();
         doReturn(true).when(mMockIPowerManager).isInteractive();
 
@@ -162,6 +176,7 @@
     @Test
     public void testRegisterProximityUpdates_callOnSuccessTwiceInARow() throws RemoteException {
         mSpyAttentionManager.mIsServiceEnabled = true;
+        mSpyAttentionManager.mIsProximityEnabled = true;
         doReturn(true).when(mSpyAttentionManager).isServiceAvailable();
         doReturn(true).when(mMockIPowerManager).isInteractive();
 
@@ -188,6 +203,7 @@
     public void testUnregisterProximityUpdates_noCrashWhenCallbackMismatched()
             throws RemoteException {
         mSpyAttentionManager.mIsServiceEnabled = true;
+        mSpyAttentionManager.mIsProximityEnabled = true;
         doReturn(true).when(mSpyAttentionManager).isServiceAvailable();
         doReturn(true).when(mMockIPowerManager).isInteractive();
         mSpyAttentionManager.onStartProximityUpdates(mMockProximityUpdateCallbackInternal);
@@ -209,6 +225,7 @@
     public void testUnregisterProximityUpdates_cancelRegistrationWhenMatched()
             throws RemoteException {
         mSpyAttentionManager.mIsServiceEnabled = true;
+        mSpyAttentionManager.mIsProximityEnabled = true;
         doReturn(true).when(mSpyAttentionManager).isServiceAvailable();
         doReturn(true).when(mMockIPowerManager).isInteractive();
         mSpyAttentionManager.onStartProximityUpdates(mMockProximityUpdateCallbackInternal);
@@ -221,6 +238,7 @@
     public void testUnregisterProximityUpdates_noCrashWhenTwiceInARow() throws RemoteException {
         // Attention Service registers proximity updates.
         mSpyAttentionManager.mIsServiceEnabled = true;
+        mSpyAttentionManager.mIsProximityEnabled = true;
         doReturn(true).when(mSpyAttentionManager).isServiceAvailable();
         doReturn(true).when(mMockIPowerManager).isInteractive();
         mSpyAttentionManager.onStartProximityUpdates(mMockProximityUpdateCallbackInternal);
@@ -248,6 +266,7 @@
     @Test
     public void testCheckAttention_returnFalseWhenPowerManagerNotInteract() throws RemoteException {
         mSpyAttentionManager.mIsServiceEnabled = true;
+        mSpyAttentionManager.mIsProximityEnabled = true;
         doReturn(false).when(mMockIPowerManager).isInteractive();
         AttentionCallbackInternal callback = Mockito.mock(AttentionCallbackInternal.class);
         assertThat(mSpyAttentionManager.checkAttention(mTimeout, callback)).isFalse();
@@ -256,6 +275,7 @@
     @Test
     public void testCheckAttention_callOnSuccess() throws RemoteException {
         mSpyAttentionManager.mIsServiceEnabled = true;
+        mSpyAttentionManager.mIsProximityEnabled = true;
         doReturn(true).when(mSpyAttentionManager).isServiceAvailable();
         doReturn(true).when(mMockIPowerManager).isInteractive();
         mSpyAttentionManager.mCurrentAttentionCheck = null;
diff --git a/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
index a0fb3de..f368a66 100644
--- a/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
@@ -78,6 +78,7 @@
 import android.service.dreams.DreamManagerInternal;
 import android.sysprop.PowerProperties;
 import android.test.mock.MockContentResolver;
+import android.util.IntArray;
 import android.view.Display;
 import android.view.DisplayInfo;
 
@@ -2322,6 +2323,31 @@
         verify(mLowPowerStandbyControllerMock).setActiveDuringMaintenance(false);
     }
 
+    @Test
+    public void testPowerGroupInitialization_multipleDisplayGroups() {
+        IntArray displayGroupIds = IntArray.wrap(new int[]{1, 2, 3});
+        when(mDisplayManagerInternalMock.getDisplayGroupIds()).thenReturn(displayGroupIds);
+
+        createService();
+        startSystem();
+
+        // Power group for DEFAULT_DISPLAY_GROUP is added by default.
+        assertThat(mService.getPowerGroupSize()).isEqualTo(4);
+    }
+
+    @Test
+    public void testPowerGroupInitialization_multipleDisplayGroupsWithDefaultGroup() {
+        IntArray displayGroupIds = IntArray.wrap(new int[]{Display.DEFAULT_DISPLAY_GROUP, 1, 2, 3});
+        when(mDisplayManagerInternalMock.getDisplayGroupIds()).thenReturn(displayGroupIds);
+
+        createService();
+        startSystem();
+
+        // Power group for DEFAULT_DISPLAY_GROUP is added once even if getDisplayGroupIds() return
+        // an array including DEFAULT_DESIPLAY_GROUP.
+        assertThat(mService.getPowerGroupSize()).isEqualTo(4);
+    }
+
     private WakeLock acquireWakeLock(String tag, int flags) {
         IBinder token = new Binder();
         String packageName = "pkg.name";
diff --git a/services/tests/servicestests/src/com/android/server/rollback/RollbackPackageHealthObserverTest.java b/services/tests/servicestests/src/com/android/server/rollback/RollbackPackageHealthObserverTest.java
deleted file mode 100644
index 0be678a..0000000
--- a/services/tests/servicestests/src/com/android/server/rollback/RollbackPackageHealthObserverTest.java
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.rollback;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.content.pm.VersionedPackage;
-import android.util.Log;
-import android.util.Xml;
-
-import androidx.test.runner.AndroidJUnit4;
-
-import com.android.server.SystemConfig;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.TemporaryFolder;
-import org.junit.runner.RunWith;
-import org.xmlpull.v1.XmlPullParser;
-
-import java.io.BufferedWriter;
-import java.io.File;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.util.Scanner;
-
-@RunWith(AndroidJUnit4.class)
-public class RollbackPackageHealthObserverTest {
-    private static final String LOG_TAG = "RollbackPackageHealthObserverTest";
-
-    private SystemConfig mSysConfig;
-
-    @Rule public TemporaryFolder mTemporaryFolder = new TemporaryFolder();
-
-    @Before
-    public void setup() {
-        mSysConfig = new SystemConfigTestClass();
-    }
-
-    /**
-    * Subclass of SystemConfig without running the constructor.
-    */
-    private class SystemConfigTestClass extends SystemConfig {
-        SystemConfigTestClass() {
-          super(false);
-        }
-    }
-
-    /**
-     * Test that isAutomaticRollbackDenied works correctly when packages that are not
-     * denied are sent.
-     */
-    @Test
-    public void isRollbackAllowedTest_false() throws IOException {
-        final String contents =
-                "<config>\n"
-                + "    <automatic-rollback-denylisted-app package=\"com.android.vending\" />\n"
-                + "</config>";
-        final File folder = createTempSubfolder("folder");
-        createTempFile(folder, "automatic-rollback-denylisted-app.xml", contents);
-
-        readPermissions(folder, /* Grant all permission flags */ ~0);
-
-        assertThat(RollbackPackageHealthObserver.isAutomaticRollbackDenied(mSysConfig,
-            new VersionedPackage("com.test.package", 1))).isEqualTo(false);
-    }
-
-    /**
-     * Test that isAutomaticRollbackDenied works correctly when packages that are
-     * denied are sent.
-     */
-    @Test
-    public void isRollbackAllowedTest_true() throws IOException {
-        final String contents =
-                "<config>\n"
-                + "    <automatic-rollback-denylisted-app package=\"com.android.vending\" />\n"
-                + "</config>";
-        final File folder = createTempSubfolder("folder");
-        createTempFile(folder, "automatic-rollback-denylisted-app.xml", contents);
-
-        readPermissions(folder, /* Grant all permission flags */ ~0);
-
-        assertThat(RollbackPackageHealthObserver.isAutomaticRollbackDenied(mSysConfig,
-            new VersionedPackage("com.android.vending", 1))).isEqualTo(true);
-    }
-
-    /**
-     * Test that isAutomaticRollbackDenied works correctly when no config is present
-     */
-    @Test
-    public void isRollbackAllowedTest_noConfig() throws IOException {
-        final File folder = createTempSubfolder("folder");
-
-        readPermissions(folder, /* Grant all permission flags */ ~0);
-
-        assertThat(RollbackPackageHealthObserver.isAutomaticRollbackDenied(mSysConfig,
-            new VersionedPackage("com.android.vending", 1))).isEqualTo(false);
-    }
-
-    /**
-     * Creates folderName/fileName in the mTemporaryFolder and fills it with the contents.
-     *
-     * @param folder   pre-existing subdirectory of mTemporaryFolder to put the file
-     * @param fileName name of the file (e.g. filename.xml) to create
-     * @param contents contents to write to the file
-     * @return the newly created file
-     */
-    private File createTempFile(File folder, String fileName, String contents)
-            throws IOException {
-        File file = new File(folder, fileName);
-        BufferedWriter bw = new BufferedWriter(new FileWriter(file));
-        bw.write(contents);
-        bw.close();
-
-        // Print to logcat for test debugging.
-        Log.d(LOG_TAG, "Contents of file " + file.getAbsolutePath());
-        Scanner input = new Scanner(file);
-        while (input.hasNextLine()) {
-            Log.d(LOG_TAG, input.nextLine());
-        }
-
-        return file;
-    }
-
-    private void readPermissions(File libraryDir, int permissionFlag) {
-        final XmlPullParser parser = Xml.newPullParser();
-        mSysConfig.readPermissions(parser, libraryDir, permissionFlag);
-    }
-
-    /**
-     * Creates folderName/fileName in the mTemporaryFolder and fills it with the contents.
-     *
-     * @param folderName subdirectory of mTemporaryFolder to put the file, creating if needed
-     * @return the folder
-     */
-    private File createTempSubfolder(String folderName)
-            throws IOException {
-        File folder = new File(mTemporaryFolder.getRoot(), folderName);
-        folder.mkdirs();
-        return folder;
-    }
-}
diff --git a/services/tests/servicestests/src/com/android/server/timezonedetector/location/LocationTimeZoneProviderControllerTest.java b/services/tests/servicestests/src/com/android/server/timezonedetector/location/LocationTimeZoneProviderControllerTest.java
index aeb8ec8..7ff015d 100644
--- a/services/tests/servicestests/src/com/android/server/timezonedetector/location/LocationTimeZoneProviderControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/timezonedetector/location/LocationTimeZoneProviderControllerTest.java
@@ -88,18 +88,21 @@
     private static final long ARBITRARY_TIME_MILLIS = 12345L;
 
     private static final TimeZoneProviderEvent USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1 =
-            createSuggestionEvent(asList("Europe/London"));
+            createSuggestionEvent(ARBITRARY_TIME_MILLIS, asList("Europe/London"));
     private static final TimeZoneProviderEvent USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2 =
-            createSuggestionEvent(asList("Europe/Paris"));
+            createSuggestionEvent(ARBITRARY_TIME_MILLIS + 1, asList("Europe/Paris"));
     private static final TimeZoneProviderStatus UNCERTAIN_PROVIDER_STATUS =
             new TimeZoneProviderStatus.Builder()
                     .setLocationDetectionDependencyStatus(DEPENDENCY_STATUS_TEMPORARILY_UNAVAILABLE)
                     .setConnectivityDependencyStatus(DEPENDENCY_STATUS_OK)
                     .setTimeZoneResolutionOperationStatus(OPERATION_STATUS_UNKNOWN)
                     .build();
-    private static final TimeZoneProviderEvent USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT =
+    private static final TimeZoneProviderEvent USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT1 =
             TimeZoneProviderEvent.createUncertainEvent(
                     ARBITRARY_TIME_MILLIS, UNCERTAIN_PROVIDER_STATUS);
+    private static final TimeZoneProviderEvent USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT2 =
+            TimeZoneProviderEvent.createUncertainEvent(
+                    ARBITRARY_TIME_MILLIS + 1, UNCERTAIN_PROVIDER_STATUS);
     private static final TimeZoneProviderEvent USER1_PERM_FAILURE_LOCATION_TIME_ZONE_EVENT =
             TimeZoneProviderEvent.createPermanentFailureEvent(ARBITRARY_TIME_MILLIS, "Test");
 
@@ -328,7 +331,7 @@
 
         // Finally, the uncertainty timeout should cause the controller to make an uncertain
         // suggestion.
-        mTestThreadingDomain.executeNext();
+        mTestThreadingDomain.executeAll();
 
         assertControllerState(controller, STATE_UNCERTAIN);
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
@@ -649,7 +652,7 @@
         // cause a suggestion to be made straight away, but the uncertainty timeout should be
         // started and the secondary should be started.
         mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
-                USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT);
+                USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT1);
 
         assertControllerState(controller, STATE_CERTAIN);
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
@@ -680,7 +683,7 @@
         // cause a suggestion to be made straight away, but the uncertainty timeout should be
         // started. Both providers are now started, with no initialization timeout set.
         mTestSecondaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
-                USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT);
+                USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT1);
 
         assertControllerState(controller, STATE_CERTAIN);
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
@@ -693,7 +696,7 @@
 
         // Simulate time passing. This means the uncertainty timeout should fire and the uncertain
         // suggestion should be made.
-        mTestThreadingDomain.executeNext();
+        mTestThreadingDomain.executeAll();
 
         assertControllerState(controller, STATE_UNCERTAIN);
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
@@ -702,7 +705,7 @@
                 PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestMetricsLogger.assertStateChangesAndCommit(STATE_UNCERTAIN);
         mTestCallback.assertEventWithUncertainSuggestionReportedAndCommit(
-                USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT);
+                USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT1);
         assertFalse(controller.isUncertaintyTimeoutSet());
     }
 
@@ -744,7 +747,7 @@
         // Uncertainty should not cause a suggestion to be made straight away, but the uncertainty
         // timeout should be started and the secondary should be started.
         mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
-                USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT);
+                USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT1);
 
         assertControllerState(controller, STATE_CERTAIN);
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
@@ -772,6 +775,147 @@
     }
 
     @Test
+    public void enabled_uncertaintyDuringUncertaintyTimeoutTriggersNoSuggestion() {
+        LocationTimeZoneProviderController controller = new LocationTimeZoneProviderController(
+                mTestThreadingDomain, mTestMetricsLogger, mTestPrimaryLocationTimeZoneProvider,
+                mTestSecondaryLocationTimeZoneProvider, false /* recordStateChanges */);
+        TestEnvironment testEnvironment = new TestEnvironment(
+                mTestThreadingDomain, controller, USER1_CONFIG_GEO_DETECTION_ENABLED);
+
+        // Initialize and check initial state.
+        controller.initialize(testEnvironment, mTestCallback);
+
+        assertControllerState(controller, STATE_INITIALIZING);
+        mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
+                PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+        mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
+        mTestMetricsLogger.assertStateChangesAndCommit(
+                STATE_PROVIDERS_INITIALIZING, STATE_STOPPED, STATE_INITIALIZING);
+        mTestCallback.assertEventWithNoSuggestionReportedAndCommit(
+                DETECTION_ALGORITHM_STATUS_RUNNING);
+        assertFalse(controller.isUncertaintyTimeoutSet());
+
+        // Simulate a location event being received from the primary provider. This should cause a
+        // suggestion to be made.
+        mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
+                USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1);
+
+        assertControllerState(controller, STATE_CERTAIN);
+        mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
+                PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+        mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
+        mTestMetricsLogger.assertStateChangesAndCommit(STATE_CERTAIN);
+        mTestCallback.assertEventWithCertainSuggestionReportedAndCommit(
+                USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1);
+        assertFalse(controller.isUncertaintyTimeoutSet());
+
+        // Uncertainty should not cause a suggestion to be made straight away, but the uncertainty
+        // timeout should be started and the secondary should be started.
+        mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
+                USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT1);
+
+        assertControllerState(controller, STATE_CERTAIN);
+        mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
+                PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+        mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
+                PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+        mTestMetricsLogger.assertStateChangesAndCommit();
+        mTestCallback.assertNoEventReported();
+        assertUncertaintyTimeoutSet(testEnvironment, controller);
+
+        // Another uncertain suggestion from the primary during the uncertainty timeout should have
+        // no effect.
+        mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
+                USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT1);
+        assertControllerState(controller, STATE_CERTAIN);
+        mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
+                PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+        mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
+                PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+        mTestMetricsLogger.assertStateChangesAndCommit();
+        mTestCallback.assertNoEventReported();
+        assertUncertaintyTimeoutSet(testEnvironment, controller);
+    }
+
+    @Test
+    public void enabled_uncertaintyAfterUncertaintyTimeoutTriggersImmediateSuggestion() {
+        LocationTimeZoneProviderController controller = new LocationTimeZoneProviderController(
+                mTestThreadingDomain, mTestMetricsLogger, mTestPrimaryLocationTimeZoneProvider,
+                mTestSecondaryLocationTimeZoneProvider, false /* recordStateChanges */);
+        TestEnvironment testEnvironment = new TestEnvironment(
+                mTestThreadingDomain, controller, USER1_CONFIG_GEO_DETECTION_ENABLED);
+
+        // Initialize and check initial state.
+        controller.initialize(testEnvironment, mTestCallback);
+
+        assertControllerState(controller, STATE_INITIALIZING);
+        mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
+                PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+        mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
+        mTestMetricsLogger.assertStateChangesAndCommit(
+                STATE_PROVIDERS_INITIALIZING, STATE_STOPPED, STATE_INITIALIZING);
+        mTestCallback.assertEventWithNoSuggestionReportedAndCommit(
+                DETECTION_ALGORITHM_STATUS_RUNNING);
+        assertFalse(controller.isUncertaintyTimeoutSet());
+
+        // Simulate a location event being received from the primary provider. This should cause a
+        // suggestion to be made.
+        mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
+                USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1);
+
+        assertControllerState(controller, STATE_CERTAIN);
+        mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
+                PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+        mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
+        mTestMetricsLogger.assertStateChangesAndCommit(STATE_CERTAIN);
+        mTestCallback.assertEventWithCertainSuggestionReportedAndCommit(
+                USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1);
+        assertFalse(controller.isUncertaintyTimeoutSet());
+
+        // Uncertainty should not cause a suggestion to be made straight away, but the uncertainty
+        // timeout should be started and the secondary should be started.
+        mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
+                USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT1);
+
+        assertControllerState(controller, STATE_CERTAIN);
+        mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
+                PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+        mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
+                PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+        mTestMetricsLogger.assertStateChangesAndCommit();
+        mTestCallback.assertNoEventReported();
+        assertUncertaintyTimeoutSet(testEnvironment, controller);
+
+        // Simulate time passing. This means the uncertainty timeout should fire and the uncertain
+        // suggestion should be made.
+        mTestThreadingDomain.executeAll();
+
+        assertControllerState(controller, STATE_UNCERTAIN);
+        mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
+                PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+        mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
+                PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+        mTestMetricsLogger.assertStateChangesAndCommit(STATE_UNCERTAIN);
+        mTestCallback.assertEventWithUncertainSuggestionReportedAndCommit(
+                USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT1);
+        assertFalse(controller.isUncertaintyTimeoutSet());
+
+        // Another uncertain suggestion from the primary should cause an immediate suggestion.
+        mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
+                USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT2);
+
+        assertControllerState(controller, STATE_UNCERTAIN);
+        mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
+                PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+        mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
+                PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+        mTestMetricsLogger.assertStateChangesAndCommit();
+        mTestCallback.assertEventWithUncertainSuggestionReportedAndCommit(
+                USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT2);
+        assertFalse(controller.isUncertaintyTimeoutSet());
+    }
+
+    @Test
     public void configChanges_enableAndDisableWithNoPreviousSuggestion() {
         LocationTimeZoneProviderController controller = new LocationTimeZoneProviderController(
                 mTestThreadingDomain, mTestMetricsLogger, mTestPrimaryLocationTimeZoneProvider,
@@ -965,7 +1109,7 @@
 
         // Simulate uncertainty from the secondary.
         mTestSecondaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
-                USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT);
+                USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT1);
 
         assertControllerState(controller, STATE_INITIALIZING);
         mTestPrimaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
@@ -991,7 +1135,7 @@
 
         // Simulate uncertainty from the secondary.
         mTestSecondaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
-                USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT);
+                USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT1);
 
         assertControllerState(controller, STATE_CERTAIN);
         mTestPrimaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
@@ -1085,7 +1229,7 @@
         // give this test the opportunity to simulate its failure. Then it will be possible to
         // demonstrate controller behavior with only the primary working.
         mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
-                USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT);
+                USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT1);
 
         assertControllerState(controller, STATE_INITIALIZING);
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
@@ -1124,7 +1268,7 @@
 
         // Simulate uncertainty from the primary. The secondary cannot be started.
         mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
-                USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT);
+                USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT1);
 
         assertControllerState(controller, STATE_CERTAIN);
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
@@ -1160,7 +1304,7 @@
         // give this test the opportunity to simulate its failure. Then it will be possible to
         // demonstrate controller behavior with only the primary working.
         mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
-                USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT);
+                USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT1);
 
         assertControllerState(controller, STATE_INITIALIZING);
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
@@ -1282,7 +1426,7 @@
 
         // Simulate an uncertain event from the primary. This will start the secondary.
         mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
-                USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT);
+                USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT1);
 
         {
             LocationTimeZoneManagerServiceState state = controller.getStateForTests();
@@ -1471,18 +1615,19 @@
                 controller.getUncertaintyTimeoutDelayMillis());
     }
 
-    private static TimeZoneProviderEvent createSuggestionEvent(@NonNull List<String> timeZoneIds) {
+    private static TimeZoneProviderEvent createSuggestionEvent(
+            long elapsedRealtimeMillis, @NonNull List<String> timeZoneIds) {
         TimeZoneProviderStatus providerStatus = new TimeZoneProviderStatus.Builder()
                 .setLocationDetectionDependencyStatus(DEPENDENCY_STATUS_NOT_APPLICABLE)
                 .setConnectivityDependencyStatus(DEPENDENCY_STATUS_NOT_APPLICABLE)
                 .setTimeZoneResolutionOperationStatus(OPERATION_STATUS_OK)
                 .build();
         TimeZoneProviderSuggestion suggestion = new TimeZoneProviderSuggestion.Builder()
-                .setElapsedRealtimeMillis(ARBITRARY_TIME_MILLIS)
+                .setElapsedRealtimeMillis(elapsedRealtimeMillis)
                 .setTimeZoneIds(timeZoneIds)
                 .build();
         return TimeZoneProviderEvent.createSuggestionEvent(
-                ARBITRARY_TIME_MILLIS, suggestion, providerStatus);
+                elapsedRealtimeMillis, suggestion, providerStatus);
     }
 
     private static void assertControllerState(LocationTimeZoneProviderController controller,
diff --git a/services/tests/servicestests/src/com/android/server/timezonedetector/location/TestThreadingDomain.java b/services/tests/servicestests/src/com/android/server/timezonedetector/location/TestThreadingDomain.java
index e08fea0..a3fb5e6 100644
--- a/services/tests/servicestests/src/com/android/server/timezonedetector/location/TestThreadingDomain.java
+++ b/services/tests/servicestests/src/com/android/server/timezonedetector/location/TestThreadingDomain.java
@@ -142,4 +142,10 @@
         mCurrentTimeMillis = queued.executionTimeMillis;
         queued.runnable.run();
     }
+
+    void executeAll() {
+        while (!mQueue.isEmpty()) {
+            executeNext();
+        }
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/vibrator/VibrationSettingsTest.java b/services/tests/servicestests/src/com/android/server/vibrator/VibrationSettingsTest.java
index d50aca9..843e2b4 100644
--- a/services/tests/servicestests/src/com/android/server/vibrator/VibrationSettingsTest.java
+++ b/services/tests/servicestests/src/com/android/server/vibrator/VibrationSettingsTest.java
@@ -49,6 +49,7 @@
 import android.app.ActivityManager;
 import android.content.ComponentName;
 import android.content.ContentResolver;
+import android.content.Context;
 import android.content.ContextWrapper;
 import android.content.Intent;
 import android.content.pm.PackageManagerInternal;
@@ -121,18 +122,14 @@
     @Rule public FakeSettingsProviderRule mSettingsProviderRule = FakeSettingsProvider.rule();
 
     @Mock private VibrationSettings.OnVibratorSettingsChanged mListenerMock;
-    @Mock
-    private PowerManagerInternal mPowerManagerInternalMock;
-    @Mock
-    private VirtualDeviceManagerInternal mVirtualDeviceManagerInternalMock;
-    @Mock
-    private PackageManagerInternal mPackageManagerInternalMock;
-    @Mock
-    private VibrationConfig mVibrationConfigMock;
+    @Mock private PowerManagerInternal mPowerManagerInternalMock;
+    @Mock private VirtualDeviceManagerInternal mVirtualDeviceManagerInternalMock;
+    @Mock private PackageManagerInternal mPackageManagerInternalMock;
+    @Mock private AudioManager mAudioManagerMock;
+    @Mock private VibrationConfig mVibrationConfigMock;
 
     private TestLooper mTestLooper;
     private ContextWrapper mContextSpy;
-    private AudioManager mAudioManager;
     private VibrationSettings mVibrationSettings;
     private PowerManagerInternal.LowPowerModeListener mRegisteredPowerModeListener;
     private VirtualDeviceManagerInternal.VirtualDisplayListener mRegisteredVirtualDisplayListener;
@@ -146,6 +143,7 @@
 
         ContentResolver contentResolver = mSettingsProviderRule.mockContentResolver(mContextSpy);
         when(mContextSpy.getContentResolver()).thenReturn(contentResolver);
+        when(mContextSpy.getSystemService(eq(Context.AUDIO_SERVICE))).thenReturn(mAudioManagerMock);
         doAnswer(invocation -> {
             mRegisteredPowerModeListener = invocation.getArgument(0);
             return null;
@@ -165,7 +163,6 @@
         addServicesForTest();
 
         setDefaultIntensity(VIBRATION_INTENSITY_MEDIUM);
-        mAudioManager = mContextSpy.getSystemService(AudioManager.class);
         mVibrationSettings = new VibrationSettings(mContextSpy,
                 new Handler(mTestLooper.getLooper()), mVibrationConfigMock);
 
@@ -211,9 +208,34 @@
     }
 
     @Test
+    public void addListener_switchUserTriggerListener() {
+        mVibrationSettings.addListener(mListenerMock);
+
+        // Testing the broadcast flow manually.
+        mVibrationSettings.mSettingChangeReceiver.onReceive(mContextSpy,
+                new Intent(Intent.ACTION_USER_SWITCHED));
+
+        verify(mListenerMock).onChange();
+    }
+
+    @Test
+    public void addListener_ringerModeChangeTriggerListener() {
+        mVibrationSettings.addListener(mListenerMock);
+
+        // Testing the broadcast flow manually.
+        mVibrationSettings.mSettingChangeReceiver.onReceive(mContextSpy,
+                new Intent(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION));
+        mVibrationSettings.mSettingChangeReceiver.onReceive(mContextSpy,
+                new Intent(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION));
+
+        verify(mListenerMock, times(2)).onChange();
+    }
+
+    @Test
     public void addListener_settingsChangeTriggerListener() {
         mVibrationSettings.addListener(mListenerMock);
 
+        // Testing the broadcast flow manually.
         mVibrationSettings.mSettingObserver.onChange(false);
         mVibrationSettings.mSettingObserver.onChange(false);
 
@@ -224,6 +246,7 @@
     public void addListener_lowPowerModeChangeTriggerListener() {
         mVibrationSettings.addListener(mListenerMock);
 
+        // Testing the broadcast flow manually.
         mRegisteredPowerModeListener.onLowPowerModeChanged(LOW_POWER_STATE);
         mRegisteredPowerModeListener.onLowPowerModeChanged(NORMAL_POWER_STATE);
         mRegisteredPowerModeListener.onLowPowerModeChanged(NORMAL_POWER_STATE); // No change.
@@ -235,13 +258,20 @@
     public void removeListener_noMoreCallbacksToListener() {
         mVibrationSettings.addListener(mListenerMock);
 
-        setUserSetting(Settings.System.RING_VIBRATION_INTENSITY, 0);
+        mVibrationSettings.mSettingObserver.onChange(false);
         verify(mListenerMock).onChange();
 
         mVibrationSettings.removeListener(mListenerMock);
 
+        // Trigger multiple observers manually.
+        mVibrationSettings.mSettingObserver.onChange(false);
+        mRegisteredPowerModeListener.onLowPowerModeChanged(LOW_POWER_STATE);
+        mVibrationSettings.mSettingChangeReceiver.onReceive(mContextSpy,
+                new Intent(Intent.ACTION_USER_SWITCHED));
+        mVibrationSettings.mSettingChangeReceiver.onReceive(mContextSpy,
+                new Intent(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION));
+
         verifyNoMoreInteractions(mListenerMock);
-        setUserSetting(Settings.System.VIBRATE_INPUT_DEVICES, 1);
     }
 
     @Test
@@ -482,7 +512,7 @@
         assertVibrationNotIgnoredForUsage(USAGE_RINGTONE);
 
         // Testing the broadcast flow manually.
-        mAudioManager.setRingerModeInternal(AudioManager.RINGER_MODE_SILENT);
+        when(mAudioManagerMock.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_SILENT);
         mVibrationSettings.mSettingChangeReceiver.onReceive(mContextSpy,
                 new Intent(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION));
 
@@ -785,7 +815,6 @@
                 mVibrationSettings.shouldIgnoreVibration(callerInfo));
     }
 
-
     private String errorMessageForUsage(int usage) {
         return "Error for usage " + VibrationAttributes.usageToString(usage);
     }
@@ -814,8 +843,8 @@
     }
 
     private void setRingerMode(int ringerMode) {
-        mAudioManager.setRingerModeInternal(ringerMode);
-        assertEquals(ringerMode, mAudioManager.getRingerModeInternal());
+        when(mAudioManagerMock.getRingerModeInternal()).thenReturn(ringerMode);
+        // Mock AudioManager broadcast of internal ringer mode change.
         mVibrationSettings.mSettingChangeReceiver.onReceive(mContextSpy,
                 new Intent(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION));
     }
diff --git a/services/tests/uiservicestests/Android.bp b/services/tests/uiservicestests/Android.bp
index 94f2d2e..4b65895 100644
--- a/services/tests/uiservicestests/Android.bp
+++ b/services/tests/uiservicestests/Android.bp
@@ -26,6 +26,7 @@
         "services.devicepolicy",
         "services.net",
         "services.usage",
+        "service-permission.stubs.system_server",
         "guava",
         "androidx.test.rules",
         "hamcrest-library",
diff --git a/services/tests/wmtests/Android.bp b/services/tests/wmtests/Android.bp
index e5371975..6509591 100644
--- a/services/tests/wmtests/Android.bp
+++ b/services/tests/wmtests/Android.bp
@@ -49,6 +49,7 @@
     static_libs: [
         "frameworks-base-testutils",
         "services.core",
+        "service-permission.stubs.system_server",
         "androidx.test.runner",
         "androidx.test.rules",
         "mockito-target-extended-minus-junit4",
@@ -57,7 +58,6 @@
         "testng",
         "truth-prebuilt",
         "testables",
-        "ub-uiautomator",
         "hamcrest-library",
         "platform-compat-test-rules",
         "CtsSurfaceValidatorLib",
diff --git a/services/texttospeech/java/com/android/server/texttospeech/TextToSpeechManagerService.java b/services/texttospeech/java/com/android/server/texttospeech/TextToSpeechManagerService.java
index 9015563..2411498 100644
--- a/services/texttospeech/java/com/android/server/texttospeech/TextToSpeechManagerService.java
+++ b/services/texttospeech/java/com/android/server/texttospeech/TextToSpeechManagerService.java
@@ -63,6 +63,12 @@
         public void createSession(String engine,
                 ITextToSpeechSessionCallback sessionCallback) {
             synchronized (mLock) {
+                if (engine == null) {
+                    runSessionCallbackMethod(
+                            () -> sessionCallback.onError("Engine cannot be null"));
+                    return;
+                }
+
                 TextToSpeechManagerPerUserService perUserService = getServiceForUserLocked(
                         UserHandle.getCallingUserId());
                 if (perUserService != null) {
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/DetectorSession.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/DetectorSession.java
index cd29dac..4cbebb3 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/DetectorSession.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/DetectorSession.java
@@ -233,7 +233,8 @@
 
         if (ENABLE_PROXIMITY_RESULT) {
             mAttentionManagerInternal = LocalServices.getService(AttentionManagerInternal.class);
-            if (mAttentionManagerInternal != null) {
+            if (mAttentionManagerInternal != null
+                    && mAttentionManagerInternal.isProximitySupported()) {
                 mAttentionManagerInternal.onStartProximityUpdates(mProximityCallbackInternal);
             }
         }
diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java
index c152a41..1da4ea9 100644
--- a/telecomm/java/android/telecom/Call.java
+++ b/telecomm/java/android/telecom/Call.java
@@ -24,6 +24,7 @@
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.pm.ServiceInfo;
 import android.net.Uri;
+import android.os.BadParcelableException;
 import android.os.Build;
 import android.os.Bundle;
 import android.os.Handler;
@@ -2951,21 +2952,27 @@
 
         for(String key : bundle.keySet()) {
             if (key != null) {
-                final Object value = bundle.get(key);
-                final Object newValue = newBundle.get(key);
                 if (!newBundle.containsKey(key)) {
                     return false;
                 }
-                if (value instanceof Bundle && newValue instanceof Bundle) {
-                    if (!areBundlesEqual((Bundle) value, (Bundle) newValue)) {
+                // In case new call extra contains non-framework class objects, return false to
+                // force update the call extra
+                try {
+                    final Object value = bundle.get(key);
+                    final Object newValue = newBundle.get(key);
+                    if (value instanceof Bundle && newValue instanceof Bundle) {
+                        if (!areBundlesEqual((Bundle) value, (Bundle) newValue)) {
+                            return false;
+                        }
+                    }
+                    if (value instanceof byte[] && newValue instanceof byte[]) {
+                        if (!Arrays.equals((byte[]) value, (byte[]) newValue)) {
+                            return false;
+                        }
+                    } else if (!Objects.equals(value, newValue)) {
                         return false;
                     }
-                }
-                if (value instanceof byte[] && newValue instanceof byte[]) {
-                    if (!Arrays.equals((byte[]) value, (byte[]) newValue)) {
-                        return false;
-                    }
-                } else if (!Objects.equals(value, newValue)) {
+                } catch (BadParcelableException e) {
                     return false;
                 }
             }
diff --git a/telecomm/java/android/telecom/CallAttributes.java b/telecomm/java/android/telecom/CallAttributes.java
index 1a0f192..f3ef834 100644
--- a/telecomm/java/android/telecom/CallAttributes.java
+++ b/telecomm/java/android/telecom/CallAttributes.java
@@ -58,6 +58,9 @@
     /** @hide **/
     public static final String CALL_CAPABILITIES_KEY = "TelecomCapabilities";
 
+    /** @hide **/
+    public static final String CALLER_PID = "CallerPid";
+
     private CallAttributes(@NonNull PhoneAccountHandle phoneAccountHandle,
             @NonNull CharSequence displayName,
             @NonNull Uri address,
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index c4a501d..d772bf8 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -10650,12 +10650,20 @@
      * no reason to power it off. When any of the voters want to power it off, it will be turned
      * off. In case of emergency, the radio will be turned on even if there are some reasons for
      * powering it off, and these radio off votes will be cleared.
-     * Multiple apps can vote for the same reason and the last vote will take effect. Each app is
-     * responsible for its vote. A powering-off vote of a reason will be maintained until it is
-     * cleared by calling {@link clearRadioPowerOffForReason} for that reason, or an emergency call
-     * is made, or the device is rebooted. When an app comes backup from a crash, it needs to make
-     * sure if its vote is as expected. An app can use the API {@link getRadioPowerOffReasons} to
-     * check its vote.
+     * <p>
+     * Each API call is for one reason. However, an app can call the API multiple times for multiple
+     * reasons. Multiple apps can vote for the same reason but the vote of one app does not affect
+     * the vote of another app.
+     * <p>
+     * Each app is responsible for its vote. A powering-off vote for a reason of an app will be
+     * maintained until it is cleared by calling {@link #clearRadioPowerOffForReason(int)} for that
+     * reason by the app, or an emergency call is made, or the device is rebooted. When an app
+     * comes backup from a crash, it needs to make sure if its vote is as expected. An app can use
+     * the API {@link #getRadioPowerOffReasons()} to check its votes. Votes won't be removed when
+     * an app crashes.
+     * <p>
+     * User setting for power state is persistent across device reboots. This applies to all users,
+     * callers must be careful to update the off reasons when the current user changes.
      *
      * @param reason The reason for powering off radio.
      * @throws SecurityException if the caller does not have MODIFY_PHONE_STATE permission.
@@ -10712,10 +10720,10 @@
     }
 
     /**
-     * Get reasons for powering off radio, as requested by {@link requestRadioPowerOffForReason}.
-     * If the reason set is empty, the radio is on in all cases.
+     * Get reasons for powering off radio of the calling app, as requested by
+     * {@link #requestRadioPowerOffForReason(int)}.
      *
-     * @return Set of reasons for powering off radio.
+     * @return Set of reasons for powering off radio of the calling app.
      * @throws SecurityException if the caller does not have READ_PRIVILEGED_PHONE_STATE permission.
      * @throws IllegalStateException if the Telephony service is not currently available.
      *
@@ -15140,6 +15148,14 @@
     @TestApi
     public static final int HAL_SERVICE_IMS = 7;
 
+    /**
+     * HAL service type that supports the HAL APIs implementation of IRadioSatellite
+     * {@link RadioSatelliteProxy}
+     * @hide
+     */
+    @TestApi
+    public static final int HAL_SERVICE_SATELLITE = 8;
+
     /** @hide */
     @Retention(RetentionPolicy.SOURCE)
     @IntDef(prefix = {"HAL_SERVICE_"},
@@ -15152,6 +15168,7 @@
                     HAL_SERVICE_SIM,
                     HAL_SERVICE_VOICE,
                     HAL_SERVICE_IMS,
+                    HAL_SERVICE_SATELLITE
             })
     public @interface HalService {}
 
diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java
index 8ed60c1..45daab3 100644
--- a/telephony/java/com/android/internal/telephony/RILConstants.java
+++ b/telephony/java/com/android/internal/telephony/RILConstants.java
@@ -571,6 +571,22 @@
     int RIL_REQUEST_UPDATE_IMS_CALL_STATUS = 240;
     int RIL_REQUEST_SET_N1_MODE_ENABLED = 241;
     int RIL_REQUEST_IS_N1_MODE_ENABLED = 242;
+    int RIL_REQUEST_SET_LOCATION_PRIVACY_SETTING = 243;
+    int RIL_REQUEST_GET_LOCATION_PRIVACY_SETTING = 244;
+    int RIL_REQUEST_GET_SATELLITE_CAPABILITIES = 245;
+    int RIL_REQUEST_SET_SATELLITE_POWER = 246;
+    int RIL_REQUEST_GET_SATELLITE_POWER = 247;
+    int RIL_REQUEST_PROVISION_SATELLITE_SERVICE = 248;
+    int RIL_REQUEST_ADD_ALLOWED_SATELLITE_CONTACTS = 249;
+    int RIL_REQUEST_REMOVE_ALLOWED_SATELLITE_CONTACTS = 250;
+    int RIL_REQUEST_SEND_SATELLITE_MESSAGES = 251;
+    int RIL_REQUEST_GET_PENDING_SATELLITE_MESSAGES = 252;
+    int RIL_REQUEST_GET_SATELLITE_MODE = 253;
+    int RIL_REQUEST_SET_SATELLITE_INDICATION_FILTER = 254;
+    int RIL_REQUEST_START_SENDING_SATELLITE_POINTING_INFO = 255;
+    int RIL_REQUEST_STOP_SENDING_SATELLITE_POINTING_INFO = 256;
+    int RIL_REQUEST_GET_MAX_CHARACTERS_PER_SATELLITE_TEXT_MESSAGE = 257;
+    int RIL_REQUEST_GET_TIME_FOR_NEXT_SATELLITE_VISIBILITY = 258;
 
     /* Responses begin */
     int RIL_RESPONSE_ACKNOWLEDGEMENT = 800;
@@ -632,6 +648,13 @@
     int RIL_UNSOL_RESPONSE_SIM_PHONEBOOK_CHANGED = 1053;
     int RIL_UNSOL_RESPONSE_SIM_PHONEBOOK_RECORDS_RECEIVED = 1054;
     int RIL_UNSOL_SLICING_CONFIG_CHANGED = 1055;
+    int RIL_UNSOL_PENDING_SATELLITE_MESSAGE_COUNT = 1056;
+    int RIL_UNSOL_NEW_SATELLITE_MESSAGES = 1057;
+    int RIL_UNSOL_SATELLITE_MESSAGES_TRANSFER_COMPLETE = 1058;
+    int RIL_UNSOL_SATELLITE_POINTING_INFO_CHANGED = 1059;
+    int RIL_UNSOL_SATELLITE_MODE_CHANGED = 1060;
+    int RIL_UNSOL_SATELLITE_RADIO_TECHNOLOGY_CHANGED = 1061;
+    int RIL_UNSOL_SATELLITE_PROVISION_STATE_CHANGED = 1062;
 
     /* The following unsols are not defined in RIL.h */
     int RIL_UNSOL_HAL_NON_RIL_BASE = 1100;
diff --git a/tests/EnforcePermission/aidl/android/tests/enforcepermission/IProtected.aidl b/tests/EnforcePermission/aidl/android/tests/enforcepermission/IProtected.aidl
index 18e3aec..87aad10 100644
--- a/tests/EnforcePermission/aidl/android/tests/enforcepermission/IProtected.aidl
+++ b/tests/EnforcePermission/aidl/android/tests/enforcepermission/IProtected.aidl
@@ -31,4 +31,25 @@
 
     @EnforcePermission("INTERNET")
     void ProtectedByInternetAndReadSyncSettingsImplicitly();
+
+    @EnforcePermission("TURN_SCREEN_ON")
+    void ProtectedByTurnScreenOn();
+
+    @EnforcePermission("READ_CONTACTS")
+    void ProtectedByReadContacts();
+
+    @EnforcePermission("READ_CALENDAR")
+    void ProtectedByReadCalendar();
+
+    @EnforcePermission(allOf={"INTERNET", "VIBRATE"})
+    void ProtectedByInternetAndVibrate();
+
+    @EnforcePermission(allOf={"INTERNET", "READ_SYNC_SETTINGS"})
+    void ProtectedByInternetAndReadSyncSettings();
+
+    @EnforcePermission(anyOf={"ACCESS_WIFI_STATE", "VIBRATE"})
+    void ProtectedByAccessWifiStateOrVibrate();
+
+    @EnforcePermission(anyOf={"INTERNET", "VIBRATE"})
+    void ProtectedByInternetOrVibrate();
 }
diff --git a/tests/EnforcePermission/service-app/AndroidManifest.xml b/tests/EnforcePermission/service-app/AndroidManifest.xml
index ddafe15..eba1230 100644
--- a/tests/EnforcePermission/service-app/AndroidManifest.xml
+++ b/tests/EnforcePermission/service-app/AndroidManifest.xml
@@ -15,6 +15,9 @@
 -->
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
   package="android.tests.enforcepermission.service">
+
+    <uses-permission android:name="android.permission.UPDATE_APP_OPS_STATS" />
+
     <application>
         <service
           android:name=".TestService"
diff --git a/tests/EnforcePermission/service-app/src/android/tests/enforcepermission/service/NestedTestService.java b/tests/EnforcePermission/service-app/src/android/tests/enforcepermission/service/NestedTestService.java
index 7879a12..0f083c9 100644
--- a/tests/EnforcePermission/service-app/src/android/tests/enforcepermission/service/NestedTestService.java
+++ b/tests/EnforcePermission/service-app/src/android/tests/enforcepermission/service/NestedTestService.java
@@ -18,13 +18,21 @@
 
 import android.annotation.EnforcePermission;
 import android.app.Service;
+import android.content.Context;
 import android.content.Intent;
 import android.os.IBinder;
+import android.os.PermissionEnforcer;
 import android.tests.enforcepermission.INested;
 import android.util.Log;
 
 public class NestedTestService extends Service {
     private static final String TAG = "EnforcePermission.NestedTestService";
+    private INested.Stub mBinder;
+
+    @Override
+    public void onCreate() {
+        mBinder = new Stub(this);
+    }
 
     @Override
     public IBinder onBind(Intent intent) {
@@ -32,7 +40,12 @@
         return mBinder;
     }
 
-    private final INested.Stub mBinder = new INested.Stub() {
+    private static class Stub extends INested.Stub {
+
+        Stub(Context context) {
+            super(PermissionEnforcer.fromContext(context));
+        }
+
         @Override
         @EnforcePermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
         public void ProtectedByAccessNetworkState() {
@@ -44,5 +57,5 @@
         public void ProtectedByReadSyncSettings() {
             ProtectedByReadSyncSettings_enforcePermission();
         }
-    };
+    }
 }
diff --git a/tests/EnforcePermission/service-app/src/android/tests/enforcepermission/service/TestService.java b/tests/EnforcePermission/service-app/src/android/tests/enforcepermission/service/TestService.java
index e9b897d..0a3af1a 100644
--- a/tests/EnforcePermission/service-app/src/android/tests/enforcepermission/service/TestService.java
+++ b/tests/EnforcePermission/service-app/src/android/tests/enforcepermission/service/TestService.java
@@ -22,6 +22,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.os.IBinder;
+import android.os.PermissionEnforcer;
 import android.os.RemoteException;
 import android.tests.enforcepermission.INested;
 import android.tests.enforcepermission.IProtected;
@@ -36,9 +37,11 @@
 
     private static final String TAG = "EnforcePermission.TestService";
     private volatile ServiceConnection mNestedServiceConnection;
+    private IProtected.Stub mBinder;
 
     @Override
     public void onCreate() {
+        mBinder = new Stub(this);
         mNestedServiceConnection = new ServiceConnection();
         Intent intent = new Intent(this, NestedTestService.class);
         boolean bound = bindService(intent, mNestedServiceConnection, Context.BIND_AUTO_CREATE);
@@ -78,7 +81,12 @@
         return mBinder;
     }
 
-    private final IProtected.Stub mBinder = new IProtected.Stub() {
+    private class Stub extends IProtected.Stub {
+
+        Stub(Context context) {
+            super(PermissionEnforcer.fromContext(context));
+        }
+
         @Override
         @EnforcePermission(android.Manifest.permission.INTERNET)
         public void ProtectedByInternet() {
@@ -105,7 +113,6 @@
             ProtectedByInternetAndAccessNetworkStateImplicitly_enforcePermission();
 
             mNestedServiceConnection.get().ProtectedByAccessNetworkState();
-
         }
 
         @Override
@@ -115,5 +122,55 @@
 
             mNestedServiceConnection.get().ProtectedByReadSyncSettings();
         }
-    };
+
+        @Override
+        @EnforcePermission(android.Manifest.permission.TURN_SCREEN_ON)
+        public void ProtectedByTurnScreenOn() {
+            ProtectedByTurnScreenOn_enforcePermission();
+        }
+
+        @Override
+        @EnforcePermission(android.Manifest.permission.READ_CONTACTS)
+        public void ProtectedByReadContacts() {
+            ProtectedByReadContacts_enforcePermission();
+        }
+
+        @Override
+        @EnforcePermission(android.Manifest.permission.READ_CALENDAR)
+        public void ProtectedByReadCalendar() {
+            ProtectedByReadCalendar_enforcePermission();
+        }
+
+        @Override
+        @EnforcePermission(allOf = {
+                android.Manifest.permission.INTERNET,
+                android.Manifest.permission.VIBRATE})
+        public void ProtectedByInternetAndVibrate() {
+            ProtectedByInternetAndVibrate_enforcePermission();
+        }
+
+        @Override
+        @EnforcePermission(allOf = {
+                android.Manifest.permission.INTERNET,
+                android.Manifest.permission.READ_SYNC_SETTINGS})
+        public void ProtectedByInternetAndReadSyncSettings() {
+            ProtectedByInternetAndReadSyncSettings_enforcePermission();
+        }
+
+        @Override
+        @EnforcePermission(anyOf = {
+                  android.Manifest.permission.ACCESS_WIFI_STATE,
+                  android.Manifest.permission.VIBRATE})
+        public void ProtectedByAccessWifiStateOrVibrate() {
+            ProtectedByAccessWifiStateOrVibrate_enforcePermission();
+        }
+
+        @Override
+        @EnforcePermission(anyOf = {
+                android.Manifest.permission.INTERNET,
+                android.Manifest.permission.VIBRATE})
+        public void ProtectedByInternetOrVibrate() {
+            ProtectedByInternetOrVibrate_enforcePermission();
+        }
+    }
 }
diff --git a/tests/EnforcePermission/test-app/AndroidManifest.xml b/tests/EnforcePermission/test-app/AndroidManifest.xml
index 4a0c6a8..8bd05d7 100644
--- a/tests/EnforcePermission/test-app/AndroidManifest.xml
+++ b/tests/EnforcePermission/test-app/AndroidManifest.xml
@@ -16,9 +16,20 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
   package="android.tests.enforcepermission.tests">
 
-    <!-- Expected for the tests (not actually used) -->
+    <!-- Expected permissions for the tests (not actually used). These
+         are granted automatically at runtime by Tradefed (see
+         GrantPermissionPreparer). -->
+    <!-- normal -->
     <uses-permission android:name="android.permission.INTERNET" />
     <uses-permission android:name="android.permission.READ_SYNC_SETTINGS" />
+    <!-- normal|appops -->
+    <uses-permission android:name="android.permission.TURN_SCREEN_ON" />
+    <!-- dangerous -->
+    <uses-permission android:name="android.permission.READ_CONTACTS" />
+
+    <!-- Used by the tests to activate/deactivate AppOps -->
+    <uses-permission android:name="android.permission.MANAGE_APP_OPS_MODES" />
+    <uses-permission android:name="android.permission.MANAGE_APPOPS" />
 
     <queries>
         <package android:name="android.tests.enforcepermission.service" />
diff --git a/tests/EnforcePermission/test-app/src/android/tests/enforcepermission/tests/ServiceTest.java b/tests/EnforcePermission/test-app/src/android/tests/enforcepermission/tests/ServiceTest.java
index d2a4a03..e09097c 100644
--- a/tests/EnforcePermission/test-app/src/android/tests/enforcepermission/tests/ServiceTest.java
+++ b/tests/EnforcePermission/test-app/src/android/tests/enforcepermission/tests/ServiceTest.java
@@ -21,11 +21,13 @@
 import static org.junit.Assert.assertThrows;
 import static org.junit.Assert.assertTrue;
 
+import android.app.AppOpsManager;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.ServiceConnection;
 import android.os.IBinder;
+import android.os.Process;
 import android.os.RemoteException;
 import android.tests.enforcepermission.IProtected;
 import android.util.Log;
@@ -126,4 +128,61 @@
             throws RemoteException {
         mServiceConnection.get().ProtectedByInternetAndReadSyncSettingsImplicitly();
     }
+
+    @Test
+    public void testAppOpPermissionGranted_succeeds() throws RemoteException {
+        AppOpsManager appOpsManager = mContext.getSystemService(AppOpsManager.class);
+        appOpsManager.setUidMode(AppOpsManager.OP_TURN_SCREEN_ON,
+                Process.myUid(), AppOpsManager.MODE_ALLOWED);
+
+        mServiceConnection.get().ProtectedByTurnScreenOn();
+    }
+
+    @Test
+    public void testAppOpPermissionDenied_fails() throws RemoteException {
+        AppOpsManager appOpsManager = mContext.getSystemService(AppOpsManager.class);
+        appOpsManager.setUidMode(AppOpsManager.OP_TURN_SCREEN_ON,
+                Process.myUid(), AppOpsManager.MODE_ERRORED);
+
+        final Exception ex = assertThrows(SecurityException.class,
+                () -> mServiceConnection.get().ProtectedByTurnScreenOn());
+        assertThat(ex.getMessage(), containsString("TURN_SCREEN_ON"));
+    }
+
+    @Test
+    public void testRuntimePermissionGranted_succeeds() throws RemoteException {
+        mServiceConnection.get().ProtectedByReadContacts();
+    }
+
+    @Test
+    public void testRuntimePermissionDenied_fails() throws RemoteException {
+        final Exception ex = assertThrows(SecurityException.class,
+                () -> mServiceConnection.get().ProtectedByReadCalendar());
+        assertThat(ex.getMessage(), containsString("READ_CALENDAR"));
+    }
+
+    @Test
+    public void testAllOfPermissionGranted_succeeds() throws RemoteException {
+        mServiceConnection.get().ProtectedByInternetAndReadSyncSettings();
+    }
+
+    @Test
+    public void testAllOfPermissionDenied_fails() throws RemoteException {
+        final Exception ex = assertThrows(SecurityException.class,
+                () -> mServiceConnection.get().ProtectedByInternetAndVibrate());
+        assertThat(ex.getMessage(), containsString("VIBRATE"));
+    }
+
+    @Test
+    public void testAnyOfPermissionGranted_succeeds() throws RemoteException {
+        mServiceConnection.get().ProtectedByInternetOrVibrate();
+    }
+
+    @Test
+    public void testAnyOfPermissionDenied_fails() throws RemoteException {
+        final Exception ex = assertThrows(SecurityException.class,
+                () -> mServiceConnection.get().ProtectedByAccessWifiStateOrVibrate());
+        assertThat(ex.getMessage(), containsString("VIBRATE"));
+        assertThat(ex.getMessage(), containsString("ACCESS_WIFI_STATE"));
+    }
 }
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/GestureHelper.java b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/GestureHelper.java
index a8f1b3d..6b24598 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/GestureHelper.java
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/GestureHelper.java
@@ -20,6 +20,7 @@
 import android.app.Instrumentation;
 import android.app.UiAutomation;
 import android.os.SystemClock;
+import android.util.Log;
 import android.view.InputDevice;
 import android.view.InputEvent;
 import android.view.MotionEvent;
@@ -32,6 +33,7 @@
  * Injects gestures given an {@link Instrumentation} object.
  */
 public class GestureHelper {
+    private static final String TAG = GestureHelper.class.getSimpleName();
     // Inserted after each motion event injection.
     private static final int MOTION_EVENT_INJECTION_DELAY_MILLIS = 5;
 
@@ -208,6 +210,9 @@
             for (int j = 0; j < coords.length; j++) {
                 coords[j].x += (endPoints[j].x - startPoints[j].x) / steps;
                 coords[j].y += (endPoints[j].y - startPoints[j].y) / steps;
+
+                // TODO: remove logging once b/269505548 is resolved
+                Log.d(TAG, "(" + coords[j].x + ", " + coords[j].y + ")");
             }
 
             eventTime = SystemClock.uptimeMillis();
diff --git a/tests/HandwritingIme/src/com/google/android/test/handwritingime/BoundsInfoDrawHelper.java b/tests/HandwritingIme/src/com/google/android/test/handwritingime/BoundsInfoDrawHelper.java
new file mode 100644
index 0000000..6b924f3
--- /dev/null
+++ b/tests/HandwritingIme/src/com/google/android/test/handwritingime/BoundsInfoDrawHelper.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.android.test.handwritingime;
+
+import static com.google.android.test.handwritingime.HandwritingIme.BOUNDS_INFO_EDITOR_BOUNDS;
+import static com.google.android.test.handwritingime.HandwritingIme.BOUNDS_INFO_NONE;
+import static com.google.android.test.handwritingime.HandwritingIme.BOUNDS_INFO_VISIBLE_LINE_BOUNDS;
+
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Matrix;
+import android.graphics.Paint;
+import android.graphics.RectF;
+import android.view.View;
+import android.view.inputmethod.CursorAnchorInfo;
+import android.view.inputmethod.EditorBoundsInfo;
+
+import androidx.annotation.Nullable;
+
+import com.android.internal.graphics.ColorUtils;
+
+import java.util.List;
+
+public class BoundsInfoDrawHelper {
+    private static final Paint sPaint = new Paint();
+    private static final int EDITOR_BOUNDS_COLOR =
+            ColorUtils.setAlphaComponent(Color.DKGRAY, 128);
+    private static final int HANDWRITING_BOUNDS_COLOR =
+            ColorUtils.setAlphaComponent(Color.BLUE, 128);
+    private static final int VISIBLE_LINE_BOUNDS_COLOR =
+            ColorUtils.setAlphaComponent(Color.MAGENTA, 128);
+
+    public static void draw(Canvas canvas, View inkView, int boundsInfoMode,
+            CursorAnchorInfo cursorAnchorInfo) {
+        if (boundsInfoMode == BOUNDS_INFO_NONE || cursorAnchorInfo == null) {
+            return;
+        }
+
+        // The matrix in CursorAnchorInfo transforms the editor coordinates to on-screen
+        // coordinates. We then transform the matrix from the on-screen coordinates to the
+        // inkView's coordinates. So the result matrix transforms the editor coordinates
+        // to the inkView coordinates.
+        final Matrix matrix = cursorAnchorInfo.getMatrix();
+        inkView.transformMatrixToLocal(matrix);
+
+        if ((boundsInfoMode & BOUNDS_INFO_EDITOR_BOUNDS) != 0) {
+            drawEditorBoundsInfo(canvas, matrix, cursorAnchorInfo.getEditorBoundsInfo());
+        }
+
+        if ((boundsInfoMode & BOUNDS_INFO_VISIBLE_LINE_BOUNDS) != 0) {
+            drawVisibleLineBounds(canvas, matrix, cursorAnchorInfo.getVisibleLineBounds());
+        }
+    }
+
+    private static void setPaintForEditorBoundsInfo() {
+        sPaint.reset();
+        sPaint.setStyle(Paint.Style.STROKE);
+        sPaint.setStrokeWidth(5f);
+    }
+
+    private static void drawEditorBoundsInfo(Canvas canvas, Matrix matrix,
+            @Nullable EditorBoundsInfo editorBoundsInfo) {
+        if (editorBoundsInfo == null) {
+            return;
+        }
+        final RectF editorBounds = editorBoundsInfo.getEditorBounds();
+        setPaintForEditorBoundsInfo();
+        if (editorBounds != null) {
+            final RectF localEditorBounds = new RectF(editorBounds);
+            matrix.mapRect(localEditorBounds);
+            sPaint.setColor(EDITOR_BOUNDS_COLOR);
+            canvas.drawRect(localEditorBounds, sPaint);
+        }
+
+        final RectF handwritingBounds = editorBoundsInfo.getHandwritingBounds();
+        if (handwritingBounds != null) {
+            final RectF localHandwritingBounds = new RectF(handwritingBounds);
+            matrix.mapRect(localHandwritingBounds);
+            sPaint.setColor(HANDWRITING_BOUNDS_COLOR);
+            canvas.drawRect(localHandwritingBounds, sPaint);
+        }
+    }
+
+    private static void setPaintForVisibleLineBounds() {
+        sPaint.reset();
+        sPaint.setStyle(Paint.Style.STROKE);
+        sPaint.setStrokeWidth(2f);
+        sPaint.setColor(VISIBLE_LINE_BOUNDS_COLOR);
+    }
+
+    private static void drawVisibleLineBounds(Canvas canvas, Matrix matrix,
+            List<RectF> visibleLineBounds) {
+        if (visibleLineBounds.isEmpty()) {
+            return;
+        }
+        setPaintForVisibleLineBounds();
+        for (RectF lineBound : visibleLineBounds) {
+            matrix.mapRect(lineBound);
+            canvas.drawRect(lineBound, sPaint);
+        }
+    }
+}
diff --git a/tests/HandwritingIme/src/com/google/android/test/handwritingime/HandwritingIme.java b/tests/HandwritingIme/src/com/google/android/test/handwritingime/HandwritingIme.java
index 2fd2368..8380dcf 100644
--- a/tests/HandwritingIme/src/com/google/android/test/handwritingime/HandwritingIme.java
+++ b/tests/HandwritingIme/src/com/google/android/test/handwritingime/HandwritingIme.java
@@ -25,7 +25,9 @@
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.Window;
+import android.view.inputmethod.CursorAnchorInfo;
 import android.view.inputmethod.DeleteGesture;
+import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.HandwritingGesture;
 import android.view.inputmethod.InputConnection;
 import android.view.inputmethod.InsertGesture;
@@ -34,6 +36,7 @@
 import android.view.inputmethod.SelectGesture;
 import android.widget.AdapterView;
 import android.widget.ArrayAdapter;
+import android.widget.CheckBox;
 import android.widget.FrameLayout;
 import android.widget.LinearLayout;
 import android.widget.Spinner;
@@ -43,9 +46,6 @@
 import java.util.function.IntConsumer;
 
 public class HandwritingIme extends InputMethodService {
-
-    public static final int HEIGHT_DP = 100;
-
     private static final int OP_NONE = 0;
     private static final int OP_SELECT = 1;
     private static final int OP_DELETE = 2;
@@ -62,6 +62,12 @@
     private Spinner mRichGestureGranularitySpinner;
     private PointF mRichGestureStartPoint;
 
+    static final int BOUNDS_INFO_NONE = 0;
+    static final int BOUNDS_INFO_VISIBLE_LINE_BOUNDS = 1;
+    static final int BOUNDS_INFO_EDITOR_BOUNDS = 2;
+    private int mBoundsInfoMode = BOUNDS_INFO_NONE;
+    private LinearLayout mBoundsInfoCheckBoxes;
+
     private final IntConsumer mResultConsumer = value -> Log.d(TAG, "Gesture result: " + value);
 
     interface HandwritingFinisher {
@@ -201,12 +207,7 @@
     public View onCreateInputView() {
         Log.d(TAG, "onCreateInputView");
         final ViewGroup view = new FrameLayout(this);
-        final View inner = new View(this);
-        final float density = getResources().getDisplayMetrics().density;
-        final int height = (int) (HEIGHT_DP * density);
         view.setPadding(0, 0, 0, 0);
-        view.addView(inner, new FrameLayout.LayoutParams(
-                FrameLayout.LayoutParams.MATCH_PARENT, height));
 
         LinearLayout layout = new LinearLayout(this);
         layout.setLayoutParams(new LinearLayout.LayoutParams(
@@ -214,9 +215,9 @@
         layout.setOrientation(LinearLayout.VERTICAL);
         layout.addView(getRichGestureActionsSpinner());
         layout.addView(getRichGestureGranularitySpinner());
-
+        layout.addView(getBoundsInfoCheckBoxes());
+        layout.setBackgroundColor(getColor(R.color.holo_green_light));
         view.addView(layout);
-        inner.setBackgroundColor(getColor(R.color.holo_green_light));
 
         return view;
     }
@@ -228,7 +229,7 @@
         mRichGestureModeSpinner = new Spinner(this);
         mRichGestureModeSpinner.setPadding(100, 0, 100, 0);
         mRichGestureModeSpinner.setTooltipText("Handwriting IME mode");
-        String[] items = new String[] {
+        String[] items = new String[]{
                 "Handwriting IME - Rich gesture disabled",
                 "Rich gesture SELECT",
                 "Rich gesture DELETE",
@@ -259,6 +260,69 @@
         return mRichGestureModeSpinner;
     }
 
+    private void updateCursorAnchorInfo(int boundsInfoMode) {
+        final InputConnection ic = getCurrentInputConnection();
+        if (ic == null) return;
+
+        if (boundsInfoMode == BOUNDS_INFO_NONE) {
+            ic.requestCursorUpdates(0);
+            return;
+        }
+
+        final int cursorUpdateMode = InputConnection.CURSOR_UPDATE_MONITOR;
+        int cursorUpdateFilter = 0;
+        if ((boundsInfoMode & BOUNDS_INFO_EDITOR_BOUNDS) != 0) {
+            cursorUpdateFilter |= InputConnection.CURSOR_UPDATE_FILTER_EDITOR_BOUNDS;
+        }
+
+        if ((boundsInfoMode & BOUNDS_INFO_VISIBLE_LINE_BOUNDS) != 0) {
+            cursorUpdateFilter |= InputConnection.CURSOR_UPDATE_FILTER_VISIBLE_LINE_BOUNDS;
+        }
+        ic.requestCursorUpdates(cursorUpdateMode | cursorUpdateFilter);
+    }
+
+    private void updateBoundsInfoMode() {
+        if (mInk != null) {
+            mInk.setBoundsInfoMode(mBoundsInfoMode);
+        }
+        updateCursorAnchorInfo(mBoundsInfoMode);
+    }
+
+    private View getBoundsInfoCheckBoxes() {
+        if (mBoundsInfoCheckBoxes != null) {
+            return mBoundsInfoCheckBoxes;
+        }
+        mBoundsInfoCheckBoxes = new LinearLayout(this);
+        mBoundsInfoCheckBoxes.setPadding(100, 0, 100, 0);
+        mBoundsInfoCheckBoxes.setOrientation(LinearLayout.HORIZONTAL);
+
+        final CheckBox editorBoundsInfoCheckBox = new CheckBox(this);
+        editorBoundsInfoCheckBox.setText("EditorBoundsInfo");
+        editorBoundsInfoCheckBox.setOnCheckedChangeListener((buttonView, isChecked) -> {
+            if (isChecked) {
+                mBoundsInfoMode |= BOUNDS_INFO_EDITOR_BOUNDS;
+            } else {
+                mBoundsInfoMode &= ~BOUNDS_INFO_EDITOR_BOUNDS;
+            }
+            updateBoundsInfoMode();
+        });
+
+        final CheckBox visibleLineBoundsInfoCheckBox = new CheckBox(this);
+        visibleLineBoundsInfoCheckBox.setText("VisibleLineBounds");
+        visibleLineBoundsInfoCheckBox.setOnCheckedChangeListener((buttonView, isChecked) -> {
+            if (isChecked) {
+                mBoundsInfoMode |= BOUNDS_INFO_VISIBLE_LINE_BOUNDS;
+            } else {
+                mBoundsInfoMode &= ~BOUNDS_INFO_VISIBLE_LINE_BOUNDS;
+            }
+            updateBoundsInfoMode();
+        });
+
+        mBoundsInfoCheckBoxes.addView(editorBoundsInfoCheckBox);
+        mBoundsInfoCheckBoxes.addView(visibleLineBoundsInfoCheckBox);
+        return mBoundsInfoCheckBoxes;
+    }
+
     private View getRichGestureGranularitySpinner() {
         if (mRichGestureGranularitySpinner != null) {
             return mRichGestureGranularitySpinner;
@@ -294,6 +358,7 @@
         Log.d(TAG, "onPrepareStylusHandwriting ");
         if (mInk == null) {
             mInk = new InkView(this, new HandwritingFinisherImpl(), new StylusConsumer());
+            mInk.setBoundsInfoMode(mBoundsInfoMode);
         }
     }
 
@@ -323,4 +388,16 @@
     private boolean areRichGesturesEnabled() {
         return mRichGestureMode != OP_NONE;
     }
+
+    @Override
+    public void onUpdateCursorAnchorInfo(CursorAnchorInfo cursorAnchorInfo) {
+        if (mInk != null) {
+            mInk.setCursorAnchorInfo(cursorAnchorInfo);
+        }
+    }
+
+    @Override
+    public void onStartInput(EditorInfo attribute, boolean restarting) {
+        updateCursorAnchorInfo(mBoundsInfoMode);
+    }
 }
diff --git a/tests/HandwritingIme/src/com/google/android/test/handwritingime/InkView.java b/tests/HandwritingIme/src/com/google/android/test/handwritingime/InkView.java
index e94c79e..86b324c 100644
--- a/tests/HandwritingIme/src/com/google/android/test/handwritingime/InkView.java
+++ b/tests/HandwritingIme/src/com/google/android/test/handwritingime/InkView.java
@@ -26,6 +26,7 @@
 import android.view.ViewGroup;
 import android.view.WindowManager;
 import android.view.WindowMetrics;
+import android.view.inputmethod.CursorAnchorInfo;
 
 class InkView extends View {
     private static final long FINISH_TIMEOUT = 1500;
@@ -37,6 +38,9 @@
     private static final float STYLUS_MOVE_TOLERANCE = 1;
     private Runnable mFinishRunnable;
 
+    private CursorAnchorInfo mCursorAnchorInfo;
+    private int mBoundsInfoMode;
+
     InkView(Context context, HandwritingIme.HandwritingFinisher hwController,
             HandwritingIme.StylusConsumer consumer) {
         super(context);
@@ -66,6 +70,7 @@
 
         canvas.drawPath(mPath, mPaint);
         canvas.drawARGB(20, 255, 50, 50);
+        BoundsInfoDrawHelper.draw(canvas, this, mBoundsInfoMode, mCursorAnchorInfo);
     }
 
     private void stylusStart(float x, float y) {
@@ -156,4 +161,15 @@
         return mFinishRunnable;
     }
 
+    void setCursorAnchorInfo(CursorAnchorInfo cursorAnchorInfo) {
+        mCursorAnchorInfo = cursorAnchorInfo;
+        invalidate();
+    }
+
+    void setBoundsInfoMode(int boundsInfoMode) {
+        if (boundsInfoMode != mBoundsInfoMode) {
+            invalidate();
+        }
+        mBoundsInfoMode = boundsInfoMode;
+    }
 }
diff --git a/tests/Input/src/com/android/test/input/AnrTest.kt b/tests/Input/src/com/android/test/input/AnrTest.kt
index 0246426..41f6680 100644
--- a/tests/Input/src/com/android/test/input/AnrTest.kt
+++ b/tests/Input/src/com/android/test/input/AnrTest.kt
@@ -151,8 +151,7 @@
     private fun triggerAnr() {
         startUnresponsiveActivity()
         val uiDevice: UiDevice = UiDevice.getInstance(instrumentation)
-        val obj: UiObject2? = uiDevice.wait(Until.findObject(
-                By.text("Unresponsive gesture monitor")), 10000)
+        val obj: UiObject2? = uiDevice.wait(Until.findObject(By.pkg(PACKAGE_NAME)), 10000)
 
         if (obj == null) {
             fail("Could not find unresponsive activity")
diff --git a/tests/InputMethodStressTest/Android.bp b/tests/InputMethodStressTest/Android.bp
index 0ad3876..27640a5 100644
--- a/tests/InputMethodStressTest/Android.bp
+++ b/tests/InputMethodStressTest/Android.bp
@@ -32,5 +32,8 @@
         "general-tests",
         "vts",
     ],
-    sdk_version: "31",
+    data: [
+        ":SimpleTestIme",
+    ],
+    sdk_version: "current",
 }
diff --git a/tests/InputMethodStressTest/AndroidManifest.xml b/tests/InputMethodStressTest/AndroidManifest.xml
index 2d183bc..62eee02 100644
--- a/tests/InputMethodStressTest/AndroidManifest.xml
+++ b/tests/InputMethodStressTest/AndroidManifest.xml
@@ -17,7 +17,7 @@
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
           package="com.android.inputmethod.stresstest">
-
+    <uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
     <application>
         <activity android:name=".ImeStressTestUtil$TestActivity"
                   android:configChanges="orientation|screenSize"/>
diff --git a/tests/InputMethodStressTest/AndroidTest.xml b/tests/InputMethodStressTest/AndroidTest.xml
index 9ac4135..bedf099 100644
--- a/tests/InputMethodStressTest/AndroidTest.xml
+++ b/tests/InputMethodStressTest/AndroidTest.xml
@@ -25,6 +25,7 @@
 
     <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
+        <option name="test-file-name" value="SimpleTestIme.apk" />
         <option name="test-file-name" value="InputMethodStressTest.apk" />
     </target_preparer>
 
diff --git a/tests/InputMethodStressTest/src/com/android/inputmethod/stresstest/AutoShowTest.java b/tests/InputMethodStressTest/src/com/android/inputmethod/stresstest/AutoShowTest.java
index 0c7e452..3d257b2 100644
--- a/tests/InputMethodStressTest/src/com/android/inputmethod/stresstest/AutoShowTest.java
+++ b/tests/InputMethodStressTest/src/com/android/inputmethod/stresstest/AutoShowTest.java
@@ -32,6 +32,7 @@
 
 import android.app.Instrumentation;
 import android.content.Intent;
+import android.content.res.Configuration;
 import android.os.SystemClock;
 import android.platform.test.annotations.RootPermissionTest;
 import android.platform.test.rule.UnlockScreenRule;
@@ -60,17 +61,11 @@
 @RunWith(Parameterized.class)
 public final class AutoShowTest {
 
-    @Rule(order = 0) public DisableLockScreenRule mDisableLockScreenRule =
-            new DisableLockScreenRule();
-    @Rule(order = 1) public UnlockScreenRule mUnlockScreenRule = new UnlockScreenRule();
-    @Rule(order = 2) public ScreenOrientationRule mScreenOrientationRule =
-            new ScreenOrientationRule(true /* isPortrait */);
-    @Rule(order = 3) public PressHomeBeforeTestRule mPressHomeBeforeTestRule =
-            new PressHomeBeforeTestRule();
-    @Rule(order = 4) public ScreenCaptureRule mScreenCaptureRule =
+    @Rule(order = 0) public UnlockScreenRule mUnlockScreenRule = new UnlockScreenRule();
+    @Rule(order = 1) public ImeStressTestRule mImeStressTestRule =
+        new ImeStressTestRule(true /* useSimpleTestIme */);
+    @Rule(order = 2) public ScreenCaptureRule mScreenCaptureRule =
             new ScreenCaptureRule("/sdcard/InputMethodStressTest");
-
-    // TODO(b/240359838): add test case {@code Configuration.SCREENLAYOUT_SIZE_LARGE}.
     @Parameterized.Parameters(
             name = "windowFocusFlags={0}, softInputVisibility={1}, softInputAdjustment={2}")
     public static List<Object[]> windowAndSoftInputFlagParameters() {
@@ -80,11 +75,14 @@
     private final int mSoftInputFlags;
     private final int mWindowFocusFlags;
     private final Instrumentation mInstrumentation;
+    private final boolean mIsLargeScreen;
 
     public AutoShowTest(int windowFocusFlags, int softInputVisibility, int softInputAdjustment) {
         mSoftInputFlags = softInputVisibility | softInputAdjustment;
         mWindowFocusFlags = windowFocusFlags;
         mInstrumentation = InstrumentationRegistry.getInstrumentation();
+        mIsLargeScreen = mInstrumentation.getContext().getResources()
+                .getConfiguration().isLayoutSizeAtLeast(Configuration.SCREENLAYOUT_SIZE_LARGE);
     }
 
     /**
@@ -322,8 +320,7 @@
         verifyClickBehavior(activity);
     }
 
-    public static void verifyAutoShowBehavior_forwardWithKeyboardOff(TestActivity activity) {
-        // public: also used by ImeOpenCloseStressTest
+    private void verifyAutoShowBehavior_forwardWithKeyboardOff(TestActivity activity) {
         if (hasUnfocusableWindowFlags(activity)) {
             verifyImeAlwaysHiddenWithWindowFlagSet(activity);
             return;
@@ -353,12 +350,12 @@
                 break;
             }
             case WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED: {
-                if (softInputAdjustment
-                        == WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE) {
+                if ((softInputAdjustment
+                        == WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE) || mIsLargeScreen) {
                     // The current system behavior will choose to show IME automatically when
                     // navigating forward to an app that has no visibility state specified
                     // (i.e. SOFT_INPUT_STATE_UNSPECIFIED) with set SOFT_INPUT_ADJUST_RESIZE
-                    // flag.
+                    // flag or running on a large screen device.
                     waitOnMainUntilImeIsShown(editText);
                 } else {
                     verifyImeIsAlwaysHidden(editText);
@@ -370,7 +367,7 @@
         }
     }
 
-    private static void verifyAutoShowBehavior_forwardWithKeyboardOn(TestActivity activity) {
+    private void verifyAutoShowBehavior_forwardWithKeyboardOn(TestActivity activity) {
         int windowFlags = activity.getWindow().getAttributes().flags;
         int softInputMode = activity.getWindow().getAttributes().softInputMode;
         int softInputVisibility = softInputMode & WindowManager.LayoutParams.SOFT_INPUT_MASK_STATE;
@@ -414,12 +411,12 @@
                 break;
             }
             case WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED: {
-                if (softInputAdjustment
-                        == WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE) {
+                if ((softInputAdjustment
+                        == WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE) || mIsLargeScreen) {
                     // The current system behavior will choose to show IME automatically when
-                    // navigating
-                    // forward to an app that has no visibility state specified  (i.e.
-                    // SOFT_INPUT_STATE_UNSPECIFIED) with set SOFT_INPUT_ADJUST_RESIZE flag.
+                    // navigating forward to an app that has no visibility state specified  (i.e.
+                    // SOFT_INPUT_STATE_UNSPECIFIED) with set SOFT_INPUT_ADJUST_RESIZE flag or
+                    // running on a large screen device.
                     waitOnMainUntilImeIsShown(editText);
                 } else {
                     verifyImeIsAlwaysHidden(editText);
diff --git a/tests/InputMethodStressTest/src/com/android/inputmethod/stresstest/DefaultImeVisibilityTest.java b/tests/InputMethodStressTest/src/com/android/inputmethod/stresstest/DefaultImeVisibilityTest.java
new file mode 100644
index 0000000..299cbf1
--- /dev/null
+++ b/tests/InputMethodStressTest/src/com/android/inputmethod/stresstest/DefaultImeVisibilityTest.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.inputmethod.stresstest;
+
+import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
+import static android.view.WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED;
+
+import static com.android.inputmethod.stresstest.ImeStressTestUtil.REQUEST_FOCUS_ON_CREATE;
+import static com.android.inputmethod.stresstest.ImeStressTestUtil.TestActivity.createIntent;
+import static com.android.inputmethod.stresstest.ImeStressTestUtil.callOnMainSync;
+import static com.android.inputmethod.stresstest.ImeStressTestUtil.verifyWindowAndViewFocus;
+import static com.android.inputmethod.stresstest.ImeStressTestUtil.waitOnMainUntilImeIsHidden;
+import static com.android.inputmethod.stresstest.ImeStressTestUtil.waitOnMainUntilImeIsShown;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Intent;
+import android.platform.test.annotations.RootPermissionTest;
+import android.platform.test.rule.UnlockScreenRule;
+import android.widget.EditText;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Test IME visibility by using system default IME to ensure the behavior is consistent
+ * across Android platform versions.
+ */
+@RootPermissionTest
+@RunWith(Parameterized.class)
+public final class DefaultImeVisibilityTest {
+
+    @Rule(order = 0)
+    public UnlockScreenRule mUnlockScreenRule = new UnlockScreenRule();
+    // Use system default IME for test.
+    @Rule(order = 1)
+    public ImeStressTestRule mImeStressTestRule =
+            new ImeStressTestRule(false /* useSimpleTestIme */);
+
+    @Rule(order = 2)
+    public ScreenCaptureRule mScreenCaptureRule =
+            new ScreenCaptureRule("/sdcard/InputMethodStressTest");
+
+    private static final int NUM_TEST_ITERATIONS = 10;
+
+    @Parameterized.Parameters(name = "isPortrait={0}")
+    public static List<Boolean> isPortraitCases() {
+        // Test in both portrait and landscape mode.
+        return Arrays.asList(true, false);
+    }
+
+    public DefaultImeVisibilityTest(boolean isPortrait) {
+        mImeStressTestRule.setIsPortrait(isPortrait);
+    }
+
+    @Test
+    public void showHideDefaultIme() {
+        Intent intent =
+                createIntent(
+                        0x0, /* No window focus flags */
+                        SOFT_INPUT_STATE_UNSPECIFIED | SOFT_INPUT_ADJUST_RESIZE,
+                        Collections.singletonList(REQUEST_FOCUS_ON_CREATE));
+        ImeStressTestUtil.TestActivity activity = ImeStressTestUtil.TestActivity.start(intent);
+        EditText editText = activity.getEditText();
+        for (int i = 0; i < NUM_TEST_ITERATIONS; i++) {
+
+            boolean showResult = callOnMainSync(activity::showImeWithInputMethodManager);
+            assertThat(showResult).isTrue();
+            verifyWindowAndViewFocus(editText, true, true);
+            waitOnMainUntilImeIsShown(editText);
+
+            boolean hideResult = callOnMainSync(activity::hideImeWithInputMethodManager);
+            assertThat(hideResult).isTrue();
+            waitOnMainUntilImeIsHidden(editText);
+        }
+    }
+}
diff --git a/tests/InputMethodStressTest/src/com/android/inputmethod/stresstest/DisableLockScreenRule.java b/tests/InputMethodStressTest/src/com/android/inputmethod/stresstest/DisableLockScreenRule.java
deleted file mode 100644
index d95decf..0000000
--- a/tests/InputMethodStressTest/src/com/android/inputmethod/stresstest/DisableLockScreenRule.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.inputmethod.stresstest;
-
-import android.support.test.uiautomator.UiDevice;
-
-import androidx.test.platform.app.InstrumentationRegistry;
-
-import org.junit.rules.TestWatcher;
-import org.junit.runner.Description;
-
-import java.io.IOException;
-
-/** Disable lock screen during the test. */
-public class DisableLockScreenRule extends TestWatcher {
-    private static final String LOCK_SCREEN_OFF_COMMAND = "locksettings set-disabled true";
-    private static final String LOCK_SCREEN_ON_COMMAND = "locksettings set-disabled false";
-
-    private final UiDevice mUiDevice =
-            UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
-
-    @Override
-    protected void starting(Description description) {
-        try {
-            mUiDevice.executeShellCommand(LOCK_SCREEN_OFF_COMMAND);
-        } catch (IOException e) {
-            throw new RuntimeException("Could not disable lock screen.", e);
-        }
-    }
-
-    @Override
-    protected void finished(Description description) {
-        try {
-            mUiDevice.executeShellCommand(LOCK_SCREEN_ON_COMMAND);
-        } catch (IOException e) {
-            throw new RuntimeException("Could not enable lock screen.", e);
-        }
-    }
-}
diff --git a/tests/InputMethodStressTest/src/com/android/inputmethod/stresstest/ImeOpenCloseStressTest.java b/tests/InputMethodStressTest/src/com/android/inputmethod/stresstest/ImeOpenCloseStressTest.java
index 9d4aefb..7632ab0 100644
--- a/tests/InputMethodStressTest/src/com/android/inputmethod/stresstest/ImeOpenCloseStressTest.java
+++ b/tests/InputMethodStressTest/src/com/android/inputmethod/stresstest/ImeOpenCloseStressTest.java
@@ -68,14 +68,10 @@
     private static final String TAG = "ImeOpenCloseStressTest";
     private static final int NUM_TEST_ITERATIONS = 10;
 
-    @Rule(order = 0) public DisableLockScreenRule mDisableLockScreenRule =
-            new DisableLockScreenRule();
-    @Rule(order = 1) public UnlockScreenRule mUnlockScreenRule = new UnlockScreenRule();
-    @Rule(order = 2) public ScreenOrientationRule mScreenOrientationRule =
-            new ScreenOrientationRule(true /* isPortrait */);
-    @Rule(order = 3) public PressHomeBeforeTestRule mPressHomeBeforeTestRule =
-            new PressHomeBeforeTestRule();
-    @Rule(order = 4) public ScreenCaptureRule mScreenCaptureRule =
+    @Rule(order = 0) public UnlockScreenRule mUnlockScreenRule = new UnlockScreenRule();
+    @Rule(order = 1) public ImeStressTestRule mImeStressTestRule =
+            new ImeStressTestRule(true /* useSimpleTestIme */);
+    @Rule(order = 2) public ScreenCaptureRule mScreenCaptureRule =
             new ScreenCaptureRule("/sdcard/InputMethodStressTest");
 
     private final Instrumentation mInstrumentation;
@@ -499,8 +495,6 @@
 
     @Test
     public void testRotateScreenWithKeyboardOn() throws Exception {
-        // TODO(b/256739702): Keyboard disappears after rotating screen to landscape mode if
-        // android:configChanges="orientation|screenSize" is not set
         Intent intent =
                 createIntent(
                         mWindowFocusFlags,
diff --git a/tests/InputMethodStressTest/src/com/android/inputmethod/stresstest/ImeStressTestRule.java b/tests/InputMethodStressTest/src/com/android/inputmethod/stresstest/ImeStressTestRule.java
new file mode 100644
index 0000000..12104b2
--- /dev/null
+++ b/tests/InputMethodStressTest/src/com/android/inputmethod/stresstest/ImeStressTestRule.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.inputmethod.stresstest;
+
+import android.app.Instrumentation;
+import android.os.RemoteException;
+import android.support.test.uiautomator.UiDevice;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import org.checkerframework.checker.nullness.qual.NonNull;
+import org.junit.rules.TestWatcher;
+import org.junit.runner.Description;
+
+import java.io.IOException;
+
+/**
+ * Do setup and cleanup for Ime stress tests, including disabling lock and auto-rotate screen,
+ * pressing home and enabling a simple test Ime during the tests.
+ */
+public class ImeStressTestRule extends TestWatcher {
+    private static final String LOCK_SCREEN_OFF_COMMAND = "locksettings set-disabled true";
+    private static final String LOCK_SCREEN_ON_COMMAND = "locksettings set-disabled false";
+    private static final String SET_PORTRAIT_MODE_COMMAND = "settings put system user_rotation 0";
+    private static final String SET_LANDSCAPE_MODE_COMMAND = "settings put system user_rotation 1";
+    private static final String SIMPLE_IME_ID =
+            "com.android.apps.inputmethod.simpleime/.SimpleInputMethodService";
+    private static final String ENABLE_IME_COMMAND = "ime enable " + SIMPLE_IME_ID;
+    private static final String SET_IME_COMMAND = "ime set " + SIMPLE_IME_ID;
+    private static final String DISABLE_IME_COMMAND = "ime disable " + SIMPLE_IME_ID;
+    private static final String RESET_IME_COMMAND = "ime reset";
+
+    @NonNull private final Instrumentation mInstrumentation;
+    @NonNull private final UiDevice mUiDevice;
+    // Whether the screen orientation is set to portrait.
+    private boolean mIsPortrait;
+    // Whether to use a simple test Ime or system default Ime for test.
+    private final boolean mUseSimpleTestIme;
+
+    public ImeStressTestRule(boolean useSimpleTestIme) {
+        mInstrumentation = InstrumentationRegistry.getInstrumentation();
+        mUiDevice = UiDevice.getInstance(mInstrumentation);
+        // Default is portrait mode
+        mIsPortrait = true;
+        mUseSimpleTestIme = useSimpleTestIme;
+    }
+
+    public void setIsPortrait(boolean isPortrait) {
+        mIsPortrait = isPortrait;
+    }
+
+    @Override
+    protected void starting(Description description) {
+        disableLockScreen();
+        setOrientation();
+        mUiDevice.pressHome();
+        if (mUseSimpleTestIme) {
+            enableSimpleIme();
+        } else {
+            resetImeToDefault();
+        }
+
+        mInstrumentation.waitForIdleSync();
+    }
+
+    @Override
+    protected void finished(Description description) {
+        if (mUseSimpleTestIme) {
+            disableSimpleIme();
+        }
+        unfreezeRotation();
+        restoreLockScreen();
+    }
+
+    private void disableLockScreen() {
+        try {
+            executeShellCommand(LOCK_SCREEN_OFF_COMMAND);
+        } catch (IOException e) {
+            throw new RuntimeException("Could not disable lock screen.", e);
+        }
+    }
+
+    private void restoreLockScreen() {
+        try {
+            executeShellCommand(LOCK_SCREEN_ON_COMMAND);
+        } catch (IOException e) {
+            throw new RuntimeException("Could not enable lock screen.", e);
+        }
+    }
+
+    private void setOrientation() {
+        try {
+            mUiDevice.freezeRotation();
+            executeShellCommand(
+                    mIsPortrait ? SET_PORTRAIT_MODE_COMMAND : SET_LANDSCAPE_MODE_COMMAND);
+        } catch (IOException e) {
+            throw new RuntimeException("Could not set screen orientation.", e);
+        } catch (RemoteException e) {
+            throw new RuntimeException("Could not freeze rotation.", e);
+        }
+    }
+
+    private void unfreezeRotation() {
+        try {
+            mUiDevice.unfreezeRotation();
+        } catch (RemoteException e) {
+            throw new RuntimeException("Could not unfreeze screen rotation.", e);
+        }
+    }
+
+    private void enableSimpleIme() {
+        try {
+            executeShellCommand(ENABLE_IME_COMMAND);
+            executeShellCommand(SET_IME_COMMAND);
+        } catch (IOException e) {
+            throw new RuntimeException("Could not enable SimpleTestIme.", e);
+        }
+    }
+
+    private void disableSimpleIme() {
+        try {
+            executeShellCommand(DISABLE_IME_COMMAND);
+        } catch (IOException e) {
+            throw new RuntimeException("Could not disable SimpleTestIme.", e);
+        }
+    }
+
+    private void resetImeToDefault() {
+        try {
+            executeShellCommand(RESET_IME_COMMAND);
+        } catch (IOException e) {
+            throw new RuntimeException("Could not reset Ime to default.", e);
+        }
+    }
+
+    private @NonNull String executeShellCommand(@NonNull String cmd) throws IOException {
+        return mUiDevice.executeShellCommand(cmd);
+    }
+}
diff --git a/tests/InputMethodStressTest/src/com/android/inputmethod/stresstest/NotificationTest.java b/tests/InputMethodStressTest/src/com/android/inputmethod/stresstest/NotificationTest.java
index d2708ad..f4a04a1 100644
--- a/tests/InputMethodStressTest/src/com/android/inputmethod/stresstest/NotificationTest.java
+++ b/tests/InputMethodStressTest/src/com/android/inputmethod/stresstest/NotificationTest.java
@@ -77,11 +77,10 @@
     private static final BySelector REPLY_SEND_BUTTON_SELECTOR =
             By.res("com.android.systemui", "remote_input_send").enabled(true);
 
-    @Rule
-    public UnlockScreenRule mUnlockScreenRule = new UnlockScreenRule();
-
-    @Rule
-    public ScreenCaptureRule mScreenCaptureRule =
+    @Rule(order = 0) public UnlockScreenRule mUnlockScreenRule = new UnlockScreenRule();
+    @Rule(order = 1) public ImeStressTestRule mImeStressTestRule =
+            new ImeStressTestRule(true /* useSimpleTestIme */);
+    @Rule(order = 2) public ScreenCaptureRule mScreenCaptureRule =
             new ScreenCaptureRule("/sdcard/InputMethodStressTest");
 
     private Context mContext;
@@ -141,7 +140,8 @@
 
         // Post inline reply notification.
         PendingIntent pendingIntent = PendingIntent.getBroadcast(
-                mContext, REPLY_REQUEST_CODE, new Intent().setAction(ACTION_REPLY),
+                mContext, REPLY_REQUEST_CODE,
+                new Intent().setAction(ACTION_REPLY).setClass(mContext, NotificationTest.class),
                 PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE);
         RemoteInput remoteInput = new RemoteInput.Builder(REPLY_INPUT_KEY)
                 .setLabel(REPLY_INPUT_LABEL)
diff --git a/tests/InputMethodStressTest/src/com/android/inputmethod/stresstest/PressHomeBeforeTestRule.java b/tests/InputMethodStressTest/src/com/android/inputmethod/stresstest/PressHomeBeforeTestRule.java
deleted file mode 100644
index 6586f63..0000000
--- a/tests/InputMethodStressTest/src/com/android/inputmethod/stresstest/PressHomeBeforeTestRule.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.inputmethod.stresstest;
-
-import android.support.test.uiautomator.UiDevice;
-
-import androidx.test.platform.app.InstrumentationRegistry;
-
-import org.junit.rules.TestWatcher;
-import org.junit.runner.Description;
-
-/** This rule will press home before a test case. */
-public class PressHomeBeforeTestRule extends TestWatcher {
-    private final UiDevice mUiDevice =
-            UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
-
-    @Override
-    protected void starting(Description description) {
-        mUiDevice.pressHome();
-    }
-}
diff --git a/tests/InputMethodStressTest/src/com/android/inputmethod/stresstest/ScreenOrientationRule.java b/tests/InputMethodStressTest/src/com/android/inputmethod/stresstest/ScreenOrientationRule.java
deleted file mode 100644
index bc3b1ef..0000000
--- a/tests/InputMethodStressTest/src/com/android/inputmethod/stresstest/ScreenOrientationRule.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.inputmethod.stresstest;
-
-import android.os.RemoteException;
-import android.support.test.uiautomator.UiDevice;
-
-import androidx.test.platform.app.InstrumentationRegistry;
-
-import org.junit.rules.TestWatcher;
-import org.junit.runner.Description;
-
-import java.io.IOException;
-
-/**
- * Disable auto-rotate during the test and set the screen orientation to portrait or landscape
- * before the test starts.
- */
-public class ScreenOrientationRule extends TestWatcher {
-    private static final String SET_PORTRAIT_MODE_CMD = "settings put system user_rotation 0";
-    private static final String SET_LANDSCAPE_MODE_CMD = "settings put system user_rotation 1";
-
-    private final boolean mIsPortrait;
-    private final UiDevice mUiDevice =
-            UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
-
-    ScreenOrientationRule(boolean isPortrait) {
-        mIsPortrait = isPortrait;
-    }
-
-    @Override
-    protected void starting(Description description) {
-        try {
-            mUiDevice.freezeRotation();
-            mUiDevice.executeShellCommand(mIsPortrait ? SET_PORTRAIT_MODE_CMD :
-                    SET_LANDSCAPE_MODE_CMD);
-        } catch (IOException e) {
-            throw new RuntimeException("Could not set screen orientation.", e);
-        } catch (RemoteException e) {
-            throw new RuntimeException("Could not freeze rotation.", e);
-        }
-    }
-
-    @Override
-    protected void finished(Description description) {
-        try {
-            mUiDevice.unfreezeRotation();
-        } catch (RemoteException e) {
-            throw new RuntimeException("Could not unfreeze screen rotation.", e);
-        }
-    }
-}
diff --git a/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java b/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java
index f8d885a..d7fa124 100644
--- a/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java
+++ b/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java
@@ -417,9 +417,9 @@
                         int failureReason, int mitigationCount) {
                     if (versionedPackage.getVersionCode() == VERSION_CODE) {
                         // Only rollback for specific versionCode
-                        return PackageHealthObserverImpact.USER_IMPACT_MEDIUM;
+                        return PackageHealthObserverImpact.USER_IMPACT_LEVEL_30;
                     }
-                    return PackageHealthObserverImpact.USER_IMPACT_NONE;
+                    return PackageHealthObserverImpact.USER_IMPACT_LEVEL_0;
                 }
             };
 
@@ -442,13 +442,13 @@
     public void testPackageFailureNotifyAllDifferentImpacts() throws Exception {
         PackageWatchdog watchdog = createWatchdog();
         TestObserver observerNone = new TestObserver(OBSERVER_NAME_1,
-                PackageHealthObserverImpact.USER_IMPACT_NONE);
+                PackageHealthObserverImpact.USER_IMPACT_LEVEL_0);
         TestObserver observerHigh = new TestObserver(OBSERVER_NAME_2,
-                PackageHealthObserverImpact.USER_IMPACT_HIGH);
+                PackageHealthObserverImpact.USER_IMPACT_LEVEL_100);
         TestObserver observerMid = new TestObserver(OBSERVER_NAME_3,
-                PackageHealthObserverImpact.USER_IMPACT_MEDIUM);
+                PackageHealthObserverImpact.USER_IMPACT_LEVEL_30);
         TestObserver observerLow = new TestObserver(OBSERVER_NAME_4,
-                PackageHealthObserverImpact.USER_IMPACT_LOW);
+                PackageHealthObserverImpact.USER_IMPACT_LEVEL_10);
 
         // Start observing for all impact observers
         watchdog.startObservingHealth(observerNone, Arrays.asList(APP_A, APP_B, APP_C, APP_D),
@@ -499,9 +499,9 @@
     public void testPackageFailureNotifyLeastImpactSuccessively() throws Exception {
         PackageWatchdog watchdog = createWatchdog();
         TestObserver observerFirst = new TestObserver(OBSERVER_NAME_1,
-                PackageHealthObserverImpact.USER_IMPACT_LOW);
+                PackageHealthObserverImpact.USER_IMPACT_LEVEL_10);
         TestObserver observerSecond = new TestObserver(OBSERVER_NAME_2,
-                PackageHealthObserverImpact.USER_IMPACT_MEDIUM);
+                PackageHealthObserverImpact.USER_IMPACT_LEVEL_30);
 
         // Start observing for observerFirst and observerSecond with failure handling
         watchdog.startObservingHealth(observerFirst, Arrays.asList(APP_A), LONG_DURATION);
@@ -517,7 +517,7 @@
         assertThat(observerSecond.mMitigatedPackages).isEmpty();
 
         // After observerFirst handles failure, next action it has is high impact
-        observerFirst.mImpact = PackageHealthObserverImpact.USER_IMPACT_HIGH;
+        observerFirst.mImpact = PackageHealthObserverImpact.USER_IMPACT_LEVEL_100;
         observerFirst.mMitigatedPackages.clear();
         observerSecond.mMitigatedPackages.clear();
 
@@ -531,7 +531,7 @@
         assertThat(observerFirst.mMitigatedPackages).isEmpty();
 
         // After observerSecond handles failure, it has no further actions
-        observerSecond.mImpact = PackageHealthObserverImpact.USER_IMPACT_NONE;
+        observerSecond.mImpact = PackageHealthObserverImpact.USER_IMPACT_LEVEL_0;
         observerFirst.mMitigatedPackages.clear();
         observerSecond.mMitigatedPackages.clear();
 
@@ -545,7 +545,7 @@
         assertThat(observerSecond.mMitigatedPackages).isEmpty();
 
         // After observerFirst handles failure, it too has no further actions
-        observerFirst.mImpact = PackageHealthObserverImpact.USER_IMPACT_NONE;
+        observerFirst.mImpact = PackageHealthObserverImpact.USER_IMPACT_LEVEL_0;
         observerFirst.mMitigatedPackages.clear();
         observerSecond.mMitigatedPackages.clear();
 
@@ -566,9 +566,9 @@
     public void testPackageFailureNotifyOneSameImpact() throws Exception {
         PackageWatchdog watchdog = createWatchdog();
         TestObserver observer1 = new TestObserver(OBSERVER_NAME_1,
-                PackageHealthObserverImpact.USER_IMPACT_HIGH);
+                PackageHealthObserverImpact.USER_IMPACT_LEVEL_100);
         TestObserver observer2 = new TestObserver(OBSERVER_NAME_2,
-                PackageHealthObserverImpact.USER_IMPACT_HIGH);
+                PackageHealthObserverImpact.USER_IMPACT_LEVEL_100);
 
         // Start observing for observer1 and observer2 with failure handling
         watchdog.startObservingHealth(observer2, Arrays.asList(APP_A), SHORT_DURATION);
@@ -592,11 +592,11 @@
         TestController controller = new TestController();
         PackageWatchdog watchdog = createWatchdog(controller, true /* withPackagesReady */);
         TestObserver observer1 = new TestObserver(OBSERVER_NAME_1,
-                PackageHealthObserverImpact.USER_IMPACT_HIGH);
+                PackageHealthObserverImpact.USER_IMPACT_LEVEL_100);
         TestObserver observer2 = new TestObserver(OBSERVER_NAME_2,
-                PackageHealthObserverImpact.USER_IMPACT_HIGH);
+                PackageHealthObserverImpact.USER_IMPACT_LEVEL_100);
         TestObserver observer3 = new TestObserver(OBSERVER_NAME_3,
-                PackageHealthObserverImpact.USER_IMPACT_HIGH);
+                PackageHealthObserverImpact.USER_IMPACT_LEVEL_100);
 
 
         // Start observing with explicit health checks for APP_A and APP_B respectively
@@ -645,7 +645,7 @@
         TestController controller = new TestController();
         PackageWatchdog watchdog = createWatchdog(controller, true /* withPackagesReady */);
         TestObserver observer = new TestObserver(OBSERVER_NAME_1,
-                PackageHealthObserverImpact.USER_IMPACT_MEDIUM);
+                PackageHealthObserverImpact.USER_IMPACT_LEVEL_30);
 
         // Start observing with explicit health checks for APP_A and APP_B
         controller.setSupportedPackages(Arrays.asList(APP_A, APP_B, APP_C));
@@ -711,7 +711,7 @@
         TestController controller = new TestController();
         PackageWatchdog watchdog = createWatchdog(controller, true /* withPackagesReady */);
         TestObserver observer = new TestObserver(OBSERVER_NAME_1,
-                PackageHealthObserverImpact.USER_IMPACT_MEDIUM);
+                PackageHealthObserverImpact.USER_IMPACT_LEVEL_30);
 
         // Start observing with explicit health checks for APP_A and
         // package observation duration == LONG_DURATION
@@ -742,7 +742,7 @@
         TestController controller = new TestController();
         PackageWatchdog watchdog = createWatchdog(controller, true /* withPackagesReady */);
         TestObserver observer = new TestObserver(OBSERVER_NAME_1,
-                PackageHealthObserverImpact.USER_IMPACT_MEDIUM);
+                PackageHealthObserverImpact.USER_IMPACT_LEVEL_30);
 
         // Start observing with explicit health checks for APP_A and
         // package observation duration == SHORT_DURATION / 2
@@ -818,7 +818,7 @@
 
         // Start observing with failure handling
         TestObserver observer = new TestObserver(OBSERVER_NAME_1,
-                PackageHealthObserverImpact.USER_IMPACT_HIGH);
+                PackageHealthObserverImpact.USER_IMPACT_LEVEL_100);
         wd.startObservingHealth(observer, Collections.singletonList(APP_A), SHORT_DURATION);
 
         // Notify of NetworkStack failure
@@ -1073,9 +1073,9 @@
     public void testBootLoopMitigationDoneForLowestUserImpact() {
         PackageWatchdog watchdog = createWatchdog();
         TestObserver bootObserver1 = new TestObserver(OBSERVER_NAME_1);
-        bootObserver1.setImpact(PackageHealthObserverImpact.USER_IMPACT_LOW);
+        bootObserver1.setImpact(PackageHealthObserverImpact.USER_IMPACT_LEVEL_10);
         TestObserver bootObserver2 = new TestObserver(OBSERVER_NAME_2);
-        bootObserver2.setImpact(PackageHealthObserverImpact.USER_IMPACT_MEDIUM);
+        bootObserver2.setImpact(PackageHealthObserverImpact.USER_IMPACT_LEVEL_30);
         watchdog.registerHealthObserver(bootObserver1);
         watchdog.registerHealthObserver(bootObserver2);
         for (int i = 0; i < PackageWatchdog.DEFAULT_BOOT_LOOP_TRIGGER_COUNT; i++) {
@@ -1446,7 +1446,7 @@
 
         TestObserver(String name) {
             mName = name;
-            mImpact = PackageHealthObserverImpact.USER_IMPACT_MEDIUM;
+            mImpact = PackageHealthObserverImpact.USER_IMPACT_LEVEL_30;
         }
 
         TestObserver(String name, int impact) {
diff --git a/tests/SurfaceViewBufferTests/src/com/android/test/InverseDisplayTransformTests.kt b/tests/SurfaceViewBufferTests/src/com/android/test/InverseDisplayTransformTests.kt
index e722ba5..1de965e 100644
--- a/tests/SurfaceViewBufferTests/src/com/android/test/InverseDisplayTransformTests.kt
+++ b/tests/SurfaceViewBufferTests/src/com/android/test/InverseDisplayTransformTests.kt
@@ -76,4 +76,4 @@
         }
         LayersTraceSubject(trace).layer("SurfaceView", 3).hasBufferSize(rotatedBufferSize)
     }
-}
+}
\ No newline at end of file
diff --git a/tests/SurfaceViewBufferTests/src/com/android/test/SharedBufferModeTests.kt b/tests/SurfaceViewBufferTests/src/com/android/test/SharedBufferModeTests.kt
index be3ed71..4c5224a 100644
--- a/tests/SurfaceViewBufferTests/src/com/android/test/SharedBufferModeTests.kt
+++ b/tests/SurfaceViewBufferTests/src/com/android/test/SharedBufferModeTests.kt
@@ -87,4 +87,4 @@
             checkPixels(svBounds, Color.BLUE)
         }
     }
-}
+}
\ No newline at end of file
diff --git a/tests/SurfaceViewBufferTests/src/com/android/test/SurfaceTracingTestBase.kt b/tests/SurfaceViewBufferTests/src/com/android/test/SurfaceTracingTestBase.kt
index cf4cb8c..a38019d 100644
--- a/tests/SurfaceViewBufferTests/src/com/android/test/SurfaceTracingTestBase.kt
+++ b/tests/SurfaceViewBufferTests/src/com/android/test/SurfaceTracingTestBase.kt
@@ -116,4 +116,4 @@
         private const val TRACE_FLAGS =
                 (1 shl 0) or (1 shl 5) or (1 shl 6) // TRACE_CRITICAL | TRACE_BUFFERS | TRACE_SYNC
     }
-}
+}
\ No newline at end of file
diff --git a/tests/SurfaceViewBufferTests/src/com/android/test/SurfaceViewBufferTestBase.kt b/tests/SurfaceViewBufferTests/src/com/android/test/SurfaceViewBufferTestBase.kt
index bba9678..1770e32 100644
--- a/tests/SurfaceViewBufferTests/src/com/android/test/SurfaceViewBufferTestBase.kt
+++ b/tests/SurfaceViewBufferTests/src/com/android/test/SurfaceViewBufferTestBase.kt
@@ -100,4 +100,4 @@
             INVERSE_DISPLAY(0x08)
         }
     }
-}
+}
\ No newline at end of file
diff --git a/tests/componentalias/Android.bp b/tests/componentalias/Android.bp
index 7af76e1..01d34e4 100644
--- a/tests/componentalias/Android.bp
+++ b/tests/componentalias/Android.bp
@@ -26,7 +26,6 @@
         "compatibility-device-util-axt",
         "mockito-target-extended-minus-junit4",
         "truth-prebuilt",
-        "ub-uiautomator",
     ],
     libs: ["android.test.base"],
     srcs: [
diff --git a/tools/aapt2/SdkConstants.cpp b/tools/aapt2/SdkConstants.cpp
index a7c5479..a766bd4 100644
--- a/tools/aapt2/SdkConstants.cpp
+++ b/tools/aapt2/SdkConstants.cpp
@@ -26,8 +26,8 @@
 namespace aapt {
 
 static ApiVersion sDevelopmentSdkLevel = 10000;
-static const auto sDevelopmentSdkCodeNames =
-    std::unordered_set<StringPiece>({"Q", "R", "S", "Sv2", "Tiramisu", "UpsideDownCake"});
+static const auto sDevelopmentSdkCodeNames = std::unordered_set<StringPiece>(
+    {"Q", "R", "S", "Sv2", "Tiramisu", "UpsideDownCake", "VanillaIceCream"});
 
 static const std::vector<std::pair<uint16_t, ApiVersion>> sAttrIdMap = {
     {0x021c, 1},
diff --git a/tools/aapt2/cmd/Link_test.cpp b/tools/aapt2/cmd/Link_test.cpp
index 28fcc1a..e629baf 100644
--- a/tools/aapt2/cmd/Link_test.cpp
+++ b/tools/aapt2/cmd/Link_test.cpp
@@ -441,8 +441,8 @@
       R"(<resources>
           <public type="attr" name="finalized_res" id="0x01010001"/>
 
-          <!-- S staged attributes (support staged resources in the same type id) -->
-          <staging-public-group type="attr" first-id="0x01010050">
+          <!-- S staged attributes (Not support staged resources in the same type id) -->
+          <staging-public-group type="attr" first-id="0x01fc0050">
             <public name="staged_s_res" />
           </staging-public-group>
 
@@ -480,8 +480,8 @@
           <public type="attr" name="staged_s2_res" id="0x01010003"/>
           <public type="string" name="staged_s_string" id="0x01020000"/>
 
-          <!-- S staged attributes (support staged resources in the same type id) -->
-          <staging-public-group-final type="attr" first-id="0x01010050">
+          <!-- S staged attributes (Not support staged resources in the same type id) -->
+          <staging-public-group-final type="attr" first-id="0x01fc0050">
             <public name="staged_s_res" />
           </staging-public-group-final>
 
@@ -551,7 +551,7 @@
   EXPECT_THAT(android_r_contents, HasSubstr("public static final int finalized_res=0x01010001;"));
   EXPECT_THAT(
       android_r_contents,
-      HasSubstr("public static final int staged_s_res; static { staged_s_res=0x01010050; }"));
+      HasSubstr("public static final int staged_s_res; static { staged_s_res=0x01fc0050; }"));
   EXPECT_THAT(
       android_r_contents,
       HasSubstr("public static final int staged_s_string; static { staged_s_string=0x01fd0080; }"));
@@ -583,7 +583,7 @@
 
   result = am.GetResourceId("android:attr/staged_s_res");
   ASSERT_TRUE(result.has_value());
-  EXPECT_THAT(*result, Eq(0x01010050));
+  EXPECT_THAT(*result, Eq(0x01fc0050));
 
   result = am.GetResourceId("android:string/staged_s_string");
   ASSERT_TRUE(result.has_value());
diff --git a/tools/aapt2/compile/IdAssigner.cpp b/tools/aapt2/compile/IdAssigner.cpp
index b3f98a9..5421abd 100644
--- a/tools/aapt2/compile/IdAssigner.cpp
+++ b/tools/aapt2/compile/IdAssigner.cpp
@@ -37,6 +37,7 @@
 
 template <typename Id, typename Key>
 struct NextIdFinder {
+  std::map<Id, Key> pre_assigned_ids_;
   explicit NextIdFinder(Id start_id = 0u) : next_id_(start_id){};
 
   // Attempts to reserve an identifier for the specified key.
@@ -55,7 +56,6 @@
   Id next_id_;
   bool next_id_called_ = false;
   bool exhausted_ = false;
-  std::map<Id, Key> pre_assigned_ids_;
   typename std::map<Id, Key>::iterator next_preassigned_id_;
 };
 
@@ -158,7 +158,7 @@
   }
 
   if (assigned_id_map_) {
-    // Reserve all the IDs mentioned in the stable ID map. That way we won't assig IDs that were
+    // Reserve all the IDs mentioned in the stable ID map. That way we won't assign IDs that were
     // listed in the map if they don't exist in the table.
     for (const auto& stable_id_entry : *assigned_id_map_) {
       const ResourceName& pre_assigned_name = stable_id_entry.first;
@@ -191,6 +191,11 @@
 }
 
 namespace {
+static const std::string_view staged_type_overlap_error =
+    "Staged public resource type IDs have conflict with non staged public resources type "
+    "IDs, please restart staged resource type ID assignment at 0xff in public-staging.xml "
+    "and also delete all the overlapping groups in public-final.xml";
+
 template <typename Id, typename Key>
 Result<Id> NextIdFinder<Id, Key>::ReserveId(Key key, Id id) {
   CHECK(!next_id_called_) << "ReserveId cannot be called after NextId";
@@ -282,8 +287,20 @@
     // another type.
     auto assign_result = type_id_finder_.ReserveId(key, id.type_id());
     if (!assign_result.has_value()) {
-      diag->Error(android::DiagMessage() << "can't assign ID " << id << " to resource " << name
-                                         << " because type " << assign_result.error());
+      auto pre_assigned_type = type_id_finder_.pre_assigned_ids_[id.type_id()].type;
+      bool pre_assigned_type_staged =
+          non_staged_type_ids_.find(pre_assigned_type) == non_staged_type_ids_.end();
+      auto hex_type_id = fmt::format("{:#04x}", (int)id.type_id());
+      bool current_type_staged = visibility.staged_api;
+      diag->Error(android::DiagMessage()
+                  << "can't assign type ID " << hex_type_id << " to "
+                  << (current_type_staged ? "staged type " : "non staged type ") << name.type.type
+                  << " because this type ID have been assigned to "
+                  << (pre_assigned_type_staged ? "staged type " : "non staged type ")
+                  << pre_assigned_type);
+      if (pre_assigned_type_staged || current_type_staged) {
+        diag->Error(android::DiagMessage() << staged_type_overlap_error);
+      }
       return false;
     }
     type = types_.emplace(key, TypeGroup(package_id_, id.type_id())).first;
@@ -298,6 +315,20 @@
                   << " because type already has ID " << std::hex << (int)id.type_id());
       return false;
     }
+  } else {
+    // Ensure that staged public resources cannot have the same type name and type id with
+    // non staged public resources.
+    auto non_staged_type = non_staged_type_ids_.find(name.type.type);
+    if (non_staged_type != non_staged_type_ids_.end() && non_staged_type->second == id.type_id()) {
+      diag->Error(
+          android::DiagMessage()
+          << "can`t assign type ID " << fmt::format("{:#04x}", (int)id.type_id())
+          << " to staged type " << name.type.type << " because type ID "
+          << fmt::format("{:#04x}", (int)id.type_id())
+          << " already has been assigned to a non staged resource type with the same type name");
+      diag->Error(android::DiagMessage() << staged_type_overlap_error);
+      return false;
+    }
   }
 
   auto assign_result = type->second.ReserveId(name, id);
diff --git a/tools/aapt2/compile/IdAssigner_test.cpp b/tools/aapt2/compile/IdAssigner_test.cpp
index 8911dad..ce45b7c 100644
--- a/tools/aapt2/compile/IdAssigner_test.cpp
+++ b/tools/aapt2/compile/IdAssigner_test.cpp
@@ -117,14 +117,28 @@
 }
 
 TEST_F(IdAssignerTests, FailWhenTypeHasTwoNonStagedIdsRegardlessOfStagedId) {
-  auto table = test::ResourceTableBuilder()
-                   .AddSimple("android:attr/foo", ResourceId(0x01050000))
-                   .AddSimple("android:attr/bar", ResourceId(0x01ff0006))
-                   .Add(NewResourceBuilder("android:attr/staged_baz")
-                            .SetId(0x01ff0000)
-                            .SetVisibility({.staged_api = true})
-                            .Build())
-                   .Build();
+  auto table =
+      test::ResourceTableBuilder()
+          .AddSimple("android:attr/foo", ResourceId(0x01050000))
+          .AddSimple("android:attr/bar", ResourceId(0x01ff0006))
+          .Add(NewResourceBuilder("android:attr/staged_baz")
+                   .SetId(0x01ff0000)
+                   .SetVisibility({.staged_api = true, .level = Visibility::Level::kPublic})
+                   .Build())
+          .Build();
+  IdAssigner assigner;
+  ASSERT_FALSE(assigner.Consume(context.get(), table.get()));
+}
+
+TEST_F(IdAssignerTests, FailWhenTypeHaveBothStagedAndNonStagedIds) {
+  auto table =
+      test::ResourceTableBuilder()
+          .AddSimple("android:attr/foo", ResourceId(0x01010000))
+          .Add(NewResourceBuilder("android:bool/staged_baz")
+                   .SetId(0x01010001)
+                   .SetVisibility({.staged_api = true, .level = Visibility::Level::kPublic})
+                   .Build())
+          .Build();
   IdAssigner assigner;
   ASSERT_FALSE(assigner.Consume(context.get(), table.get()));
 }