Merge "Support Gba Api"
diff --git a/OWNERS b/OWNERS
new file mode 100644
index 0000000..4f89f7d
--- /dev/null
+++ b/OWNERS
@@ -0,0 +1,24 @@
+# This top-level list should remain narrowly defined as team leads; individual
+# teams are strongly encouraged to define narrower OWNERS files at deeper
+# levels within the source tree; see OWNERS.md for more details
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
+
+# Support bulk translation updates
+per-file */res*/values*/*.xml = [email protected]
+
+per-file Android.bp = file:platform/build/soong:/OWNERS
+per-file Android.mk = file:platform/build/soong:/OWNERS
+per-file ApiDocs.bp = file:platform/build/soong:/OWNERS
+per-file StubLibraries.bp = file:platform/build/soong:/OWNERS
diff --git a/OWNERS.md b/OWNERS.md
new file mode 100644
index 0000000..6428c59
--- /dev/null
+++ b/OWNERS.md
@@ -0,0 +1,34 @@
+As general background, `OWNERS` files expedite code reviews by helping code
+authors quickly find relevant reviewers, and they also ensure that stakeholders
+are involved in code changes in their areas.
+
+The structure of `frameworks/base/` is unique among Android repositories, and
+it's evolved into a complex interleaved structure over the years.  Because of
+this structure, the best place to authoritatively define `OWNERS` can vary
+wildly, but here are some common patterns:
+
+* `core/java/` contains source that is included in the base classpath, and as
+such it's where most APIs are defined:
+  * `core/java/android/app/`
+  * `core/java/android/content/`
+* `services/core/` contains most system services, and these directories
+typically have more granularity than `core/java/`, since they can be refactored
+without API changes:
+  * `services/core/java/com/android/server/net/`
+  * `services/core/java/com/android/server/wm/`
+* `services/` contains several system services that have been isolated from the
+main `services/core/` project:
+  * `services/appwidget/`
+  * `services/midi/`
+* `apex/` contains Mainline modules:
+  * `apex/jobscheduler/`
+  * `apex/permission/`
+* Finally, some teams may have dedicated top-level directories:
+  * `media/`
+  * `wifi/`
+
+Area maintainers are strongly encouraged to list people in a single
+authoritative `OWNERS` file in **exactly one** location.  Then, other paths
+should reference that single authoritative `OWNERS` file using an include
+directive.  This approach ensures that updates are applied consistently across
+the tree, reducing maintenance burden.
diff --git a/ZYGOTE_OWNERS b/ZYGOTE_OWNERS
new file mode 100644
index 0000000..90a185b
--- /dev/null
+++ b/ZYGOTE_OWNERS
@@ -0,0 +1,5 @@
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
diff --git a/apct-tests/perftests/OWNERS b/apct-tests/perftests/OWNERS
new file mode 100644
index 0000000..a060ad9
--- /dev/null
+++ b/apct-tests/perftests/OWNERS
@@ -0,0 +1,2 @@
[email protected]
[email protected]
diff --git a/apct-tests/perftests/autofill/OWNERS b/apct-tests/perftests/autofill/OWNERS
new file mode 100644
index 0000000..c52751d
--- /dev/null
+++ b/apct-tests/perftests/autofill/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/service/autofill/OWNERS
diff --git a/apct-tests/perftests/blobstore/OWNERS b/apct-tests/perftests/blobstore/OWNERS
new file mode 100644
index 0000000..65bb6b8
--- /dev/null
+++ b/apct-tests/perftests/blobstore/OWNERS
@@ -0,0 +1 @@
+include /apex/blobstore/OWNERS
diff --git a/apct-tests/perftests/contentcapture/OWNERS b/apct-tests/perftests/contentcapture/OWNERS
new file mode 100644
index 0000000..a28e00a
--- /dev/null
+++ b/apct-tests/perftests/contentcapture/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/service/contentcapture/OWNERS
diff --git a/apct-tests/perftests/core/apps/overlay/OWNERS b/apct-tests/perftests/core/apps/overlay/OWNERS
new file mode 100644
index 0000000..afb98d4
--- /dev/null
+++ b/apct-tests/perftests/core/apps/overlay/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/content/om/OWNERS
diff --git a/apct-tests/perftests/core/src/android/accounts/OWNERS b/apct-tests/perftests/core/src/android/accounts/OWNERS
new file mode 100644
index 0000000..df1b4f4
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/accounts/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/accounts/OWNERS
diff --git a/apct-tests/perftests/core/src/android/database/OWNERS b/apct-tests/perftests/core/src/android/database/OWNERS
new file mode 100644
index 0000000..bb9a2ca
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/database/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/database/OWNERS
diff --git a/apct-tests/perftests/inputmethod/OWNERS b/apct-tests/perftests/inputmethod/OWNERS
new file mode 100644
index 0000000..5deb2ce
--- /dev/null
+++ b/apct-tests/perftests/inputmethod/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/view/inputmethod/OWNERS
diff --git a/apct-tests/perftests/inputmethod/src/android/inputmethod/ImePerfRunPrecondition.java b/apct-tests/perftests/inputmethod/src/android/inputmethod/ImePerfRunPrecondition.java
index fc48fd5..4bfcade 100644
--- a/apct-tests/perftests/inputmethod/src/android/inputmethod/ImePerfRunPrecondition.java
+++ b/apct-tests/perftests/inputmethod/src/android/inputmethod/ImePerfRunPrecondition.java
@@ -16,134 +16,8 @@
 
 package android.inputmethod;
 
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
-import static android.inputmethod.ImePerfTestBase.executeShellCommand;
-import static android.inputmethod.ImePerfTestBase.runWithShellPermissionIdentity;
-
-import android.app.ActivityManager;
-import android.app.ActivityManager.RunningAppProcessInfo;
-import android.app.ActivityTaskManager;
-import android.content.Context;
-import android.inputmethod.ImePerfTestBase.SettingsSession;
-import android.os.BatteryManager;
-import android.os.Bundle;
-import android.os.SystemClock;
-import android.provider.Settings;
-import android.util.Log;
-import android.view.WindowManagerPolicyConstants;
-
-import androidx.test.platform.app.InstrumentationRegistry;
-
-import com.android.internal.policy.PhoneWindow;
-
-import org.junit.runner.Description;
-import org.junit.runner.Result;
-import org.junit.runner.notification.RunListener;
-
-import java.util.List;
+import android.perftests.utils.WindowPerfRunPreconditionBase;
 
 /** Prepare the preconditions before running performance test. */
-public class ImePerfRunPrecondition extends RunListener {
-    private static final String TAG = ImePerfRunPrecondition.class.getSimpleName();
-
-    private static final String ARGUMENT_LOG_ONLY = "log";
-    private static final String ARGUMENT_KILL_BACKGROUND = "kill-bg";
-    private static final String ARGUMENT_PROFILING_ITERATIONS = "profiling-iterations";
-    private static final String ARGUMENT_PROFILING_SAMPLING = "profiling-sampling";
-    private static final String DEFAULT_PROFILING_ITERATIONS = "10";
-    private static final String DEFAULT_PROFILING_SAMPLING_US = "10";
-    private static final long KILL_BACKGROUND_WAIT_MS = 3000;
-
-    /** The requested iterations to run with method profiling. */
-    static int sProfilingIterations;
-
-    /** The interval of sample profiling in microseconds. */
-    static int sSamplingIntervalUs;
-
-    private final Context mContext = InstrumentationRegistry.getInstrumentation().getContext();
-    private long mWaitPreconditionDoneMs = 500;
-
-    private final SettingsSession<Integer> mStayOnWhilePluggedInSetting = new SettingsSession<>(
-            Settings.Global.getInt(mContext.getContentResolver(),
-                    Settings.Global.STAY_ON_WHILE_PLUGGED_IN, 0),
-            value -> executeShellCommand(String.format("settings put global %s %d",
-                    Settings.Global.STAY_ON_WHILE_PLUGGED_IN, value)));
-
-    private final SettingsSession<Integer> mNavigationModeSetting = new SettingsSession<>(
-            mContext.getResources().getInteger(
-                    com.android.internal.R.integer.config_navBarInteractionMode),
-            value -> {
-                final String navOverlay;
-                switch (value) {
-                    case WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL:
-                    default:
-                        navOverlay = WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL_OVERLAY;
-                        break;
-                }
-                executeShellCommand("cmd overlay enable-exclusive " + navOverlay);
-            });
-
-    /** It only executes once before all tests. */
-    @Override
-    public void testRunStarted(Description description) {
-        final Bundle arguments = InstrumentationRegistry.getArguments();
-        // If true, it only logs the method names without running.
-        final boolean skip = Boolean.parseBoolean(arguments.getString(ARGUMENT_LOG_ONLY, "false"));
-        Log.i(TAG, "arguments=" + arguments);
-        if (skip) {
-            return;
-        }
-        sProfilingIterations = Integer.parseInt(
-                arguments.getString(ARGUMENT_PROFILING_ITERATIONS, DEFAULT_PROFILING_ITERATIONS));
-        sSamplingIntervalUs = Integer.parseInt(
-                arguments.getString(ARGUMENT_PROFILING_SAMPLING, DEFAULT_PROFILING_SAMPLING_US));
-
-        // Use same navigation mode (gesture navigation) across all devices and tests
-        // for consistency.
-        mNavigationModeSetting.set(WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL);
-        // Keep the device awake during testing.
-        mStayOnWhilePluggedInSetting.set(BatteryManager.BATTERY_PLUGGED_ANY);
-
-        runWithShellPermissionIdentity(() -> {
-            final ActivityTaskManager atm = mContext.getSystemService(ActivityTaskManager.class);
-            atm.removeAllVisibleRecentTasks();
-            atm.removeRootTasksWithActivityTypes(new int[] { ACTIVITY_TYPE_STANDARD,
-                    ACTIVITY_TYPE_ASSISTANT, ACTIVITY_TYPE_RECENTS, ACTIVITY_TYPE_UNDEFINED });
-        });
-        PhoneWindow.sendCloseSystemWindows(mContext, "ImePerfTests");
-
-        if (Boolean.parseBoolean(arguments.getString(ARGUMENT_KILL_BACKGROUND))) {
-            runWithShellPermissionIdentity(this::killBackgroundProcesses);
-            mWaitPreconditionDoneMs = KILL_BACKGROUND_WAIT_MS;
-        }
-        // Wait a while for the precondition setup to complete.
-        SystemClock.sleep(mWaitPreconditionDoneMs);
-    }
-
-    private void killBackgroundProcesses() {
-        Log.i(TAG, "Killing background processes...");
-        final ActivityManager am = mContext.getSystemService(ActivityManager.class);
-        final List<RunningAppProcessInfo> processes = am.getRunningAppProcesses();
-        if (processes == null) {
-            return;
-        }
-        for (RunningAppProcessInfo processInfo : processes) {
-            if (processInfo.importanceReasonCode == RunningAppProcessInfo.REASON_UNKNOWN
-                    && processInfo.importance > RunningAppProcessInfo.IMPORTANCE_SERVICE) {
-                for (String pkg : processInfo.pkgList) {
-                    am.forceStopPackage(pkg);
-                }
-            }
-        }
-    }
-
-    /** It only executes once after all tests. */
-    @Override
-    public void testRunFinished(Result result) {
-        mNavigationModeSetting.close();
-        mStayOnWhilePluggedInSetting.close();
-    }
+public class ImePerfRunPrecondition extends WindowPerfRunPreconditionBase {
 }
diff --git a/apct-tests/perftests/inputmethod/src/android/inputmethod/ImePerfTest.java b/apct-tests/perftests/inputmethod/src/android/inputmethod/ImePerfTest.java
index 2b7af2f..689fb36 100644
--- a/apct-tests/perftests/inputmethod/src/android/inputmethod/ImePerfTest.java
+++ b/apct-tests/perftests/inputmethod/src/android/inputmethod/ImePerfTest.java
@@ -29,7 +29,6 @@
 import android.content.ComponentName;
 import android.content.Context;
 import android.inputmethodservice.InputMethodService;
-import android.os.ParcelFileDescriptor;
 import android.os.Process;
 import android.os.SystemClock;
 import android.perftests.utils.ManualBenchmarkState;
@@ -420,23 +419,20 @@
                 });
     }
 
-    private void startAsyncAtrace() throws IOException {
+    private void startAsyncAtrace() {
         mIsTraceStarted = true;
         // IMF uses 'wm' component for trace in InputMethodService, InputMethodManagerService,
         // WindowManagerService and 'view' for client window (InsetsController).
         // TODO(b/167947940): Consider a separate input_method atrace
-        UI_AUTOMATION.executeShellCommand("atrace -b 32768 --async_start wm view");
-        // Avoid atrace isn't ready immediately.
-        SystemClock.sleep(TimeUnit.NANOSECONDS.toMillis(TIME_1_S_IN_NS));
+        startAsyncAtrace("wm view");
     }
 
     private void stopAsyncAtrace() {
         if (!mIsTraceStarted) {
             return;
         }
-        final ParcelFileDescriptor pfd = UI_AUTOMATION.executeShellCommand("atrace --async_stop");
         mIsTraceStarted = false;
-        final InputStream inputStream = new ParcelFileDescriptor.AutoCloseInputStream(pfd);
+        final InputStream inputStream = stopAsyncAtraceWithStream();
         try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) {
             String line;
             while ((line = reader.readLine()) != null) {
diff --git a/apct-tests/perftests/inputmethod/src/android/inputmethod/ImePerfTestBase.java b/apct-tests/perftests/inputmethod/src/android/inputmethod/ImePerfTestBase.java
index 1a861d7..f70d79c 100644
--- a/apct-tests/perftests/inputmethod/src/android/inputmethod/ImePerfTestBase.java
+++ b/apct-tests/perftests/inputmethod/src/android/inputmethod/ImePerfTestBase.java
@@ -18,135 +18,21 @@
 
 import static android.perftests.utils.PerfTestActivity.INTENT_EXTRA_ADD_EDIT_TEXT;
 
-import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
-
-import android.app.KeyguardManager;
-import android.app.UiAutomation;
-import android.content.Context;
 import android.content.Intent;
-import android.os.ParcelFileDescriptor;
-import android.os.PowerManager;
 import android.perftests.utils.PerfTestActivity;
+import android.perftests.utils.WindowPerfTestBase;
 
-
-import androidx.test.rule.ActivityTestRule;
-
-import org.junit.BeforeClass;
-
-import java.io.ByteArrayOutputStream;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.util.Objects;
-import java.util.function.Consumer;
-
-public class ImePerfTestBase {
-    static final UiAutomation UI_AUTOMATION = getInstrumentation().getUiAutomation();
-    static final long NANOS_PER_S = 1000L * 1000 * 1000;
-    static final long TIME_1_S_IN_NS = 1 * NANOS_PER_S;
+public class ImePerfTestBase extends WindowPerfTestBase {
     static final long TIMEOUT_1_S_IN_MS = 1 * 1000L;
 
-    @BeforeClass
-    public static void setUpOnce() {
-        final Context context = getInstrumentation().getContext();
-
-        if (!context.getSystemService(PowerManager.class).isInteractive()
-                || context.getSystemService(KeyguardManager.class).isKeyguardLocked()) {
-            executeShellCommand("input keyevent KEYCODE_WAKEUP");
-            executeShellCommand("wm dismiss-keyguard");
-        }
-        context.startActivity(new Intent(Intent.ACTION_MAIN)
-                .addCategory(Intent.CATEGORY_HOME).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
-    }
-
-    /**
-     * Executes shell command with reading the output. It may also used to block until the current
-     * command is completed.
-     */
-    static ByteArrayOutputStream executeShellCommand(String command) {
-        final ParcelFileDescriptor pfd = UI_AUTOMATION.executeShellCommand(command);
-        final byte[] buf = new byte[512];
-        final ByteArrayOutputStream bytes = new ByteArrayOutputStream();
-        int bytesRead;
-        try (FileInputStream fis = new ParcelFileDescriptor.AutoCloseInputStream(pfd)) {
-            while ((bytesRead = fis.read(buf)) != -1) {
-                bytes.write(buf, 0, bytesRead);
-            }
-        } catch (IOException e) {
-            throw new RuntimeException(e);
-        }
-        return bytes;
-    }
-
-    /** Returns how many iterations should run with method tracing. */
-    static int getProfilingIterations() {
-        return ImePerfRunPrecondition.sProfilingIterations;
-    }
-
-    static void runWithShellPermissionIdentity(Runnable runnable) {
-        UI_AUTOMATION.adoptShellPermissionIdentity();
-        try {
-            runnable.run();
-        } finally {
-            UI_AUTOMATION.dropShellPermissionIdentity();
-        }
-    }
-
-    static class SettingsSession<T> implements AutoCloseable {
-        private final Consumer<T> mSetter;
-        private final T mOriginalValue;
-        private boolean mChanged;
-
-        SettingsSession(T originalValue, Consumer<T> setter) {
-            mOriginalValue = originalValue;
-            mSetter = setter;
-        }
-
-        void set(T value) {
-            if (Objects.equals(value, mOriginalValue)) {
-                mChanged = false;
-                return;
-            }
-            mSetter.accept(value);
-            mChanged = true;
-        }
-
-        @Override
-        public void close() {
-            if (mChanged) {
-                mSetter.accept(mOriginalValue);
-            }
-        }
-    }
-
-    /**
-     * Provides an activity that keeps screen on and is able to wait for a stable lifecycle stage.
-     */
-    static class PerfTestActivityRule extends ActivityTestRule<PerfTestActivity> {
-        private final Intent mStartIntent =
-                new Intent(getInstrumentation().getTargetContext(), PerfTestActivity.class);
-
-        PerfTestActivityRule() {
-            this(false /* launchActivity */);
-        }
-
-        PerfTestActivityRule(boolean launchActivity) {
-            super(PerfTestActivity.class, false /* initialTouchMode */, launchActivity);
-        }
-
-        @Override
-        protected Intent getActivityIntent() {
-            return mStartIntent;
-        }
+    /** Provides an activity that contains an edit text view.*/
+    static class PerfTestActivityRule extends PerfTestActivityRuleBase {
 
         @Override
         public PerfTestActivity launchActivity(Intent intent) {
             intent.putExtra(INTENT_EXTRA_ADD_EDIT_TEXT, true);
             return super.launchActivity(intent);
         }
-
-        PerfTestActivity launchActivity() {
-            return launchActivity(mStartIntent);
-        }
     }
 
     static String[] buildArray(String[]... arrays) {
diff --git a/apct-tests/perftests/packagemanager/OWNERS b/apct-tests/perftests/packagemanager/OWNERS
new file mode 100644
index 0000000..d825dfd
--- /dev/null
+++ b/apct-tests/perftests/packagemanager/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/pm/OWNERS
diff --git a/apct-tests/perftests/textclassifier/OWNERS b/apct-tests/perftests/textclassifier/OWNERS
new file mode 100644
index 0000000..46b3cb8
--- /dev/null
+++ b/apct-tests/perftests/textclassifier/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/service/textclassifier/OWNERS
diff --git a/apct-tests/perftests/utils/src/android/perftests/utils/WindowPerfRunPreconditionBase.java b/apct-tests/perftests/utils/src/android/perftests/utils/WindowPerfRunPreconditionBase.java
new file mode 100644
index 0000000..8d2ac02
--- /dev/null
+++ b/apct-tests/perftests/utils/src/android/perftests/utils/WindowPerfRunPreconditionBase.java
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.perftests.utils;
+
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
+import static android.perftests.utils.WindowPerfTestBase.executeShellCommand;
+import static android.perftests.utils.WindowPerfTestBase.runWithShellPermissionIdentity;
+
+import android.app.ActivityManager;
+import android.app.ActivityManager.RunningAppProcessInfo;
+import android.app.ActivityTaskManager;
+import android.content.Context;
+import android.os.BatteryManager;
+import android.os.Bundle;
+import android.os.SystemClock;
+import android.perftests.utils.WindowPerfTestBase.SettingsSession;
+import android.provider.Settings;
+import android.util.Log;
+import android.view.WindowManagerPolicyConstants;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.internal.policy.PhoneWindow;
+
+import org.junit.runner.Description;
+import org.junit.runner.Result;
+import org.junit.runner.notification.RunListener;
+
+import java.util.List;
+
+/** Prepare the preconditions before running performance test. */
+public class WindowPerfRunPreconditionBase extends RunListener {
+    protected final String mTag = getClass().getSimpleName();
+
+    private static final String ARGUMENT_LOG_ONLY = "log";
+    private static final String ARGUMENT_KILL_BACKGROUND = "kill-bg";
+    private static final String ARGUMENT_PROFILING_ITERATIONS = "profiling-iterations";
+    private static final String ARGUMENT_PROFILING_SAMPLING = "profiling-sampling";
+    private static final String DEFAULT_PROFILING_ITERATIONS = "0";
+    private static final String DEFAULT_PROFILING_SAMPLING_US = "10";
+    private static final long KILL_BACKGROUND_WAIT_MS = 3000;
+
+    /** The requested iterations to run with method profiling. */
+    static int sProfilingIterations;
+
+    /** The interval of sample profiling in microseconds. */
+    static int sSamplingIntervalUs;
+
+    private final Context mContext = InstrumentationRegistry.getInstrumentation().getContext();
+    private long mWaitPreconditionDoneMs = 500;
+
+    private final SettingsSession<Integer> mStayOnWhilePluggedInSetting = new SettingsSession<>(
+            Settings.Global.getInt(mContext.getContentResolver(),
+                    Settings.Global.STAY_ON_WHILE_PLUGGED_IN, 0),
+            value -> executeShellCommand(String.format("settings put global %s %d",
+                    Settings.Global.STAY_ON_WHILE_PLUGGED_IN, value)));
+
+    private final SettingsSession<Integer> mNavigationModeSetting = new SettingsSession<>(
+            mContext.getResources().getInteger(
+                    com.android.internal.R.integer.config_navBarInteractionMode),
+            value -> {
+                final String navOverlay;
+                switch (value) {
+                    case WindowManagerPolicyConstants.NAV_BAR_MODE_2BUTTON:
+                        navOverlay = WindowManagerPolicyConstants.NAV_BAR_MODE_2BUTTON_OVERLAY;
+                        break;
+                    case WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON:
+                        navOverlay = WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON_OVERLAY;
+                        break;
+                    case WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL:
+                    default:
+                        navOverlay = WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL_OVERLAY;
+                        break;
+                }
+                executeShellCommand("cmd overlay enable-exclusive " + navOverlay);
+            });
+
+    /** It only executes once before all tests. */
+    @Override
+    public void testRunStarted(Description description) {
+        final Bundle arguments = InstrumentationRegistry.getArguments();
+        // If true, it only logs the method names without running.
+        final boolean skip = Boolean.parseBoolean(arguments.getString(ARGUMENT_LOG_ONLY, "false"));
+        Log.i(mTag, "arguments=" + arguments);
+        if (skip) {
+            return;
+        }
+        sProfilingIterations = Integer.parseInt(
+                arguments.getString(ARGUMENT_PROFILING_ITERATIONS, DEFAULT_PROFILING_ITERATIONS));
+        sSamplingIntervalUs = Integer.parseInt(
+                arguments.getString(ARGUMENT_PROFILING_SAMPLING, DEFAULT_PROFILING_SAMPLING_US));
+
+        // Use same navigation mode (gesture navigation) across all devices and tests
+        // for consistency.
+        mNavigationModeSetting.set(WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL);
+        // Keep the device awake during testing.
+        mStayOnWhilePluggedInSetting.set(BatteryManager.BATTERY_PLUGGED_ANY);
+
+        runWithShellPermissionIdentity(() -> {
+            final ActivityTaskManager atm = mContext.getSystemService(ActivityTaskManager.class);
+            atm.removeAllVisibleRecentTasks();
+            atm.removeRootTasksWithActivityTypes(new int[] { ACTIVITY_TYPE_STANDARD,
+                    ACTIVITY_TYPE_ASSISTANT, ACTIVITY_TYPE_RECENTS, ACTIVITY_TYPE_UNDEFINED });
+        });
+        PhoneWindow.sendCloseSystemWindows(mContext, mTag);
+
+        if (Boolean.parseBoolean(arguments.getString(ARGUMENT_KILL_BACKGROUND))) {
+            runWithShellPermissionIdentity(this::killBackgroundProcesses);
+            mWaitPreconditionDoneMs = KILL_BACKGROUND_WAIT_MS;
+        }
+        // Wait a while for the precondition setup to complete.
+        SystemClock.sleep(mWaitPreconditionDoneMs);
+    }
+
+    private void killBackgroundProcesses() {
+        Log.i(mTag, "Killing background processes...");
+        final ActivityManager am = mContext.getSystemService(ActivityManager.class);
+        final List<RunningAppProcessInfo> processes = am.getRunningAppProcesses();
+        if (processes == null) {
+            return;
+        }
+        for (RunningAppProcessInfo processInfo : processes) {
+            if (processInfo.importanceReasonCode == RunningAppProcessInfo.REASON_UNKNOWN
+                    && processInfo.importance > RunningAppProcessInfo.IMPORTANCE_SERVICE) {
+                for (String pkg : processInfo.pkgList) {
+                    am.forceStopPackage(pkg);
+                }
+            }
+        }
+    }
+
+    /** It only executes once after all tests. */
+    @Override
+    public void testRunFinished(Result result) {
+        mNavigationModeSetting.close();
+        mStayOnWhilePluggedInSetting.close();
+    }
+}
diff --git a/apct-tests/perftests/utils/src/android/perftests/utils/WindowPerfTestBase.java b/apct-tests/perftests/utils/src/android/perftests/utils/WindowPerfTestBase.java
new file mode 100644
index 0000000..ca59137
--- /dev/null
+++ b/apct-tests/perftests/utils/src/android/perftests/utils/WindowPerfTestBase.java
@@ -0,0 +1,193 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.perftests.utils;
+
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+
+import android.app.KeyguardManager;
+import android.app.UiAutomation;
+import android.content.Context;
+import android.content.Intent;
+import android.os.ParcelFileDescriptor;
+import android.os.PowerManager;
+import android.os.SystemClock;
+
+import androidx.test.rule.ActivityTestRule;
+
+import org.junit.After;
+import org.junit.BeforeClass;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Objects;
+import java.util.concurrent.TimeUnit;
+import java.util.function.Consumer;
+
+/** The base class for window related performance tests. */
+public class WindowPerfTestBase {
+    public static final long NANOS_PER_S = 1000L * 1000 * 1000;
+    public static final long TIME_1_S_IN_NS = 1 * NANOS_PER_S;
+
+    static boolean sIsProfilingMethod;
+
+    @BeforeClass
+    public static void setUpOnce() {
+        final Context context = getInstrumentation().getContext();
+
+        if (!context.getSystemService(PowerManager.class).isInteractive()
+                || context.getSystemService(KeyguardManager.class).isKeyguardLocked()) {
+            executeShellCommand("input keyevent KEYCODE_WAKEUP");
+            executeShellCommand("wm dismiss-keyguard");
+        }
+        context.startActivity(new Intent(Intent.ACTION_MAIN)
+                .addCategory(Intent.CATEGORY_HOME).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
+    }
+
+    @After
+    public void tearDown() {
+        // Make sure that profiling is stopped if test fails.
+        if (sIsProfilingMethod) {
+            stopProfiling();
+        }
+    }
+
+    public static UiAutomation getUiAutomation() {
+        return getInstrumentation().getUiAutomation();
+    }
+
+    public static void startAsyncAtrace(String tags) {
+        getUiAutomation().executeShellCommand("atrace -b 32768 --async_start " + tags);
+        // Avoid atrace isn't ready immediately.
+        SystemClock.sleep(TimeUnit.NANOSECONDS.toMillis(TIME_1_S_IN_NS));
+    }
+
+    public static InputStream stopAsyncAtraceWithStream() {
+        return new ParcelFileDescriptor.AutoCloseInputStream(
+                getUiAutomation().executeShellCommand("atrace --async_stop"));
+    }
+
+    /** Starts method tracing on system server. */
+    public static void startProfiling(File basePath, String outFileName) {
+        if (!basePath.exists()) {
+            executeShellCommand("mkdir -p " + basePath);
+        }
+        final String samplingArg = WindowPerfRunPreconditionBase.sSamplingIntervalUs > 0
+                ? ("--sampling " + WindowPerfRunPreconditionBase.sSamplingIntervalUs)
+                : "";
+        executeShellCommand("am profile start " + samplingArg + " system "
+                + new File(basePath, outFileName));
+        sIsProfilingMethod = true;
+    }
+
+    /** Stops method tracing of system server. */
+    public static void stopProfiling() {
+        executeShellCommand("am profile stop system");
+        sIsProfilingMethod = false;
+    }
+
+    public static boolean sIsProfilingMethod() {
+        return sIsProfilingMethod;
+    }
+
+    /** Returns how many iterations should run with method tracing. */
+    public static int getProfilingIterations() {
+        return WindowPerfRunPreconditionBase.sProfilingIterations;
+    }
+
+    /**
+     * Executes shell command with reading the output. It may also used to block until the current
+     * command is completed.
+     */
+    public static ByteArrayOutputStream executeShellCommand(String command) {
+        final ParcelFileDescriptor pfd = getUiAutomation().executeShellCommand(command);
+        final byte[] buf = new byte[512];
+        final ByteArrayOutputStream bytes = new ByteArrayOutputStream();
+        int bytesRead;
+        try (FileInputStream fis = new ParcelFileDescriptor.AutoCloseInputStream(pfd)) {
+            while ((bytesRead = fis.read(buf)) != -1) {
+                bytes.write(buf, 0, bytesRead);
+            }
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+        return bytes;
+    }
+
+    public static void runWithShellPermissionIdentity(Runnable runnable) {
+        getUiAutomation().adoptShellPermissionIdentity();
+        try {
+            runnable.run();
+        } finally {
+            getUiAutomation().dropShellPermissionIdentity();
+        }
+    }
+
+    public static class SettingsSession<T> implements AutoCloseable {
+        private final Consumer<T> mSetter;
+        private final T mOriginalValue;
+        private boolean mChanged;
+
+        public SettingsSession(T originalValue, Consumer<T> setter) {
+            mOriginalValue = originalValue;
+            mSetter = setter;
+        }
+
+        public void set(T value) {
+            if (Objects.equals(value, mOriginalValue)) {
+                mChanged = false;
+                return;
+            }
+            mSetter.accept(value);
+            mChanged = true;
+        }
+
+        @Override
+        public void close() {
+            if (mChanged) {
+                mSetter.accept(mOriginalValue);
+            }
+        }
+    }
+
+    /**
+     * Provides the {@link PerfTestActivity} with an associated customizable intent.
+     */
+    public static class PerfTestActivityRuleBase extends ActivityTestRule<PerfTestActivity> {
+        protected final Intent mStartIntent =
+                new Intent(getInstrumentation().getTargetContext(), PerfTestActivity.class);
+
+        public PerfTestActivityRuleBase() {
+            this(false /* launchActivity */);
+        }
+
+        public PerfTestActivityRuleBase(boolean launchActivity) {
+            super(PerfTestActivity.class, false /* initialTouchMode */, launchActivity);
+        }
+
+        @Override
+        public Intent getActivityIntent() {
+            return mStartIntent;
+        }
+
+        public PerfTestActivity launchActivity() {
+            return launchActivity(mStartIntent);
+        }
+    }
+}
diff --git a/apct-tests/perftests/windowmanager/OWNERS b/apct-tests/perftests/windowmanager/OWNERS
new file mode 100644
index 0000000..0862c05
--- /dev/null
+++ b/apct-tests/perftests/windowmanager/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/wm/OWNERS
diff --git a/apct-tests/perftests/windowmanager/src/android/wm/InternalWindowOperationPerfTest.java b/apct-tests/perftests/windowmanager/src/android/wm/InternalWindowOperationPerfTest.java
index 5c09ec2..bccef53 100644
--- a/apct-tests/perftests/windowmanager/src/android/wm/InternalWindowOperationPerfTest.java
+++ b/apct-tests/perftests/windowmanager/src/android/wm/InternalWindowOperationPerfTest.java
@@ -18,7 +18,6 @@
 
 import static android.perftests.utils.ManualBenchmarkState.StatsReport;
 
-import android.os.ParcelFileDescriptor;
 import android.os.SystemClock;
 import android.perftests.utils.ManualBenchmarkState;
 import android.perftests.utils.ManualBenchmarkState.ManualBenchmarkTest;
@@ -37,7 +36,6 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
-import java.util.concurrent.TimeUnit;
 
 /** Measure the performance of internal methods in window manager service by trace tag. */
 @LargeTest
@@ -85,7 +83,7 @@
 
         while (state.keepRunning(measuredTimeNs)) {
             if (!mIsTraceStarted && !mIsProfiling && !state.isWarmingUp()) {
-                startAsyncAtrace();
+                startAsyncAtrace("wm");
                 mIsTraceStarted = true;
             }
             final long startTime = SystemClock.elapsedRealtimeNanos();
@@ -108,15 +106,8 @@
         Log.i(TAG, String.valueOf(mTraceMarkParser));
     }
 
-    private void startAsyncAtrace() throws IOException {
-        sUiAutomation.executeShellCommand("atrace -b 32768 --async_start wm");
-        // Avoid atrace isn't ready immediately.
-        SystemClock.sleep(TimeUnit.NANOSECONDS.toMillis(TIME_1_S_IN_NS));
-    }
-
     private void stopAsyncAtrace() {
-        final ParcelFileDescriptor pfd = sUiAutomation.executeShellCommand("atrace --async_stop");
-        final InputStream inputStream = new ParcelFileDescriptor.AutoCloseInputStream(pfd);
+        final InputStream inputStream = stopAsyncAtraceWithStream();
         try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) {
             String line;
             while ((line = reader.readLine()) != null) {
diff --git a/apct-tests/perftests/windowmanager/src/android/wm/RecentsAnimationPerfTest.java b/apct-tests/perftests/windowmanager/src/android/wm/RecentsAnimationPerfTest.java
index 833cc0f..2aea61f 100644
--- a/apct-tests/perftests/windowmanager/src/android/wm/RecentsAnimationPerfTest.java
+++ b/apct-tests/perftests/windowmanager/src/android/wm/RecentsAnimationPerfTest.java
@@ -96,7 +96,7 @@
     @BeforeClass
     public static void setUpClass() {
         // Get the permission to invoke startRecentsActivity.
-        sUiAutomation.adoptShellPermissionIdentity();
+        getUiAutomation().adoptShellPermissionIdentity();
 
         final Context context = getInstrumentation().getContext();
         final PackageManager pm = context.getPackageManager();
@@ -129,7 +129,7 @@
             ActivityManager.resumeAppSwitches();
         } catch (RemoteException ignored) {
         }
-        sUiAutomation.dropShellPermissionIdentity();
+        getUiAutomation().dropShellPermissionIdentity();
     }
 
     @Before
@@ -233,7 +233,7 @@
 
             // Ensure the animation callback is done.
             Assume.assumeTrue(recentsSemaphore.tryAcquire(
-                    sIsProfilingMethod ? 10 * TIME_5_S_IN_NS : TIME_5_S_IN_NS,
+                    sIsProfilingMethod() ? 10 * TIME_5_S_IN_NS : TIME_5_S_IN_NS,
                     TimeUnit.NANOSECONDS));
         }
     }
diff --git a/apct-tests/perftests/windowmanager/src/android/wm/WindowAddRemovePerfTest.java b/apct-tests/perftests/windowmanager/src/android/wm/WindowAddRemovePerfTest.java
index 2960603..9403e8b 100644
--- a/apct-tests/perftests/windowmanager/src/android/wm/WindowAddRemovePerfTest.java
+++ b/apct-tests/perftests/windowmanager/src/android/wm/WindowAddRemovePerfTest.java
@@ -54,12 +54,12 @@
     @BeforeClass
     public static void setUpClass() {
         // Get the permission to use most window types.
-        sUiAutomation.adoptShellPermissionIdentity();
+        getUiAutomation().adoptShellPermissionIdentity();
     }
 
     @AfterClass
     public static void tearDownClass() {
-        sUiAutomation.dropShellPermissionIdentity();
+        getUiAutomation().dropShellPermissionIdentity();
     }
 
     /** The last customized iterations will provide the information of method profiling. */
diff --git a/apct-tests/perftests/windowmanager/src/android/wm/WindowManagerPerfTestBase.java b/apct-tests/perftests/windowmanager/src/android/wm/WindowManagerPerfTestBase.java
index b51a9a8..4b1982f 100644
--- a/apct-tests/perftests/windowmanager/src/android/wm/WindowManagerPerfTestBase.java
+++ b/apct-tests/perftests/windowmanager/src/android/wm/WindowManagerPerfTestBase.java
@@ -19,36 +19,21 @@
 import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
 
 import android.app.Activity;
-import android.app.KeyguardManager;
-import android.app.UiAutomation;
-import android.content.Context;
 import android.content.Intent;
-import android.os.ParcelFileDescriptor;
-import android.os.PowerManager;
 import android.perftests.utils.PerfTestActivity;
+import android.perftests.utils.WindowPerfTestBase;
 
-import androidx.test.rule.ActivityTestRule;
 import androidx.test.runner.lifecycle.ActivityLifecycleCallback;
 import androidx.test.runner.lifecycle.ActivityLifecycleMonitorRegistry;
 import androidx.test.runner.lifecycle.Stage;
 
-import org.junit.After;
-import org.junit.BeforeClass;
 import org.junit.runner.Description;
 import org.junit.runners.model.Statement;
 
-import java.io.ByteArrayOutputStream;
 import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.util.Objects;
 import java.util.concurrent.TimeUnit;
-import java.util.function.Consumer;
 
-public class WindowManagerPerfTestBase {
-    static final UiAutomation sUiAutomation = getInstrumentation().getUiAutomation();
-    static final long NANOS_PER_S = 1000L * 1000 * 1000;
-    static final long TIME_1_S_IN_NS = 1 * NANOS_PER_S;
+public class WindowManagerPerfTestBase extends WindowPerfTestBase {
     static final long TIME_5_S_IN_NS = 5 * NANOS_PER_S;
 
     /**
@@ -58,121 +43,21 @@
      */
     static final File BASE_OUT_PATH = new File("/data/local/tmp/WmPerfTests");
 
-    static boolean sIsProfilingMethod;
-
-    @BeforeClass
-    public static void setUpOnce() {
-        final Context context = getInstrumentation().getContext();
-
-        if (!context.getSystemService(PowerManager.class).isInteractive()
-                || context.getSystemService(KeyguardManager.class).isKeyguardLocked()) {
-            executeShellCommand("input keyevent KEYCODE_WAKEUP");
-            executeShellCommand("wm dismiss-keyguard");
-        }
-        context.startActivity(new Intent(Intent.ACTION_MAIN)
-                .addCategory(Intent.CATEGORY_HOME).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
-    }
-
-    @After
-    public void tearDown() {
-        // Make sure that profiling is stopped if test fails.
-        if (sIsProfilingMethod) {
-            stopProfiling();
-        }
+    static void startProfiling(String outFileName) {
+        startProfiling(BASE_OUT_PATH, outFileName);
     }
 
     /**
-     * Executes shell command with reading the output. It may also used to block until the current
-     * command is completed.
+     * Provides an activity that is able to wait for a stable lifecycle stage.
      */
-    static ByteArrayOutputStream executeShellCommand(String command) {
-        final ParcelFileDescriptor pfd = sUiAutomation.executeShellCommand(command);
-        final byte[] buf = new byte[512];
-        final ByteArrayOutputStream bytes = new ByteArrayOutputStream();
-        int bytesRead;
-        try (FileInputStream fis = new ParcelFileDescriptor.AutoCloseInputStream(pfd)) {
-            while ((bytesRead = fis.read(buf)) != -1) {
-                bytes.write(buf, 0, bytesRead);
-            }
-        } catch (IOException e) {
-            throw new RuntimeException(e);
-        }
-        return bytes;
-    }
-
-    /** Starts method tracing on system server. */
-    static void startProfiling(String subPath) {
-        if (!BASE_OUT_PATH.exists()) {
-            executeShellCommand("mkdir -p " + BASE_OUT_PATH);
-        }
-        final String samplingArg = WmPerfRunListener.sSamplingIntervalUs > 0
-                ? ("--sampling " + WmPerfRunListener.sSamplingIntervalUs)
-                : "";
-        executeShellCommand("am profile start " + samplingArg + " system "
-                + new File(BASE_OUT_PATH, subPath));
-        sIsProfilingMethod = true;
-    }
-
-    static void stopProfiling() {
-        executeShellCommand("am profile stop system");
-        sIsProfilingMethod = false;
-    }
-
-    /** Returns how many iterations should run with method tracing. */
-    static int getProfilingIterations() {
-        return WmPerfRunListener.sProfilingIterations;
-    }
-
-    static void runWithShellPermissionIdentity(Runnable runnable) {
-        sUiAutomation.adoptShellPermissionIdentity();
-        try {
-            runnable.run();
-        } finally {
-            sUiAutomation.dropShellPermissionIdentity();
-        }
-    }
-
-    static class SettingsSession<T> implements AutoCloseable {
-        private final Consumer<T> mSetter;
-        private final T mOriginalValue;
-        private boolean mChanged;
-
-        SettingsSession(T originalValue, Consumer<T> setter) {
-            mOriginalValue = originalValue;
-            mSetter = setter;
-        }
-
-        void set(T value) {
-            if (Objects.equals(value, mOriginalValue)) {
-                mChanged = false;
-                return;
-            }
-            mSetter.accept(value);
-            mChanged = true;
-        }
-
-        @Override
-        public void close() {
-            if (mChanged) {
-                mSetter.accept(mOriginalValue);
-            }
-        }
-    }
-
-    /**
-     * Provides an activity that keeps screen on and is able to wait for a stable lifecycle stage.
-     */
-    static class PerfTestActivityRule extends ActivityTestRule<PerfTestActivity> {
-        private final Intent mStartIntent =
-                new Intent(getInstrumentation().getTargetContext(), PerfTestActivity.class);
+    static class PerfTestActivityRule extends PerfTestActivityRuleBase {
         private final LifecycleListener mLifecycleListener = new LifecycleListener();
 
         PerfTestActivityRule() {
-            this(false /* launchActivity */);
         }
 
         PerfTestActivityRule(boolean launchActivity) {
-            super(PerfTestActivity.class, false /* initialTouchMode */, launchActivity);
+            super(launchActivity);
         }
 
         @Override
@@ -191,21 +76,12 @@
         }
 
         @Override
-        protected Intent getActivityIntent() {
-            return mStartIntent;
-        }
-
-        @Override
         public PerfTestActivity launchActivity(Intent intent) {
             final PerfTestActivity activity = super.launchActivity(intent);
             mLifecycleListener.setTargetActivity(activity);
             return activity;
         }
 
-        PerfTestActivity launchActivity() {
-            return launchActivity(mStartIntent);
-        }
-
         void waitForIdleSync(Stage state) {
             mLifecycleListener.waitForIdleSync(state);
         }
diff --git a/apct-tests/perftests/windowmanager/src/android/wm/WmPerfRunListener.java b/apct-tests/perftests/windowmanager/src/android/wm/WmPerfRunListener.java
index a9d5716..2b0801a 100644
--- a/apct-tests/perftests/windowmanager/src/android/wm/WmPerfRunListener.java
+++ b/apct-tests/perftests/windowmanager/src/android/wm/WmPerfRunListener.java
@@ -16,138 +16,8 @@
 
 package android.wm;
 
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
-import static android.wm.WindowManagerPerfTestBase.executeShellCommand;
-import static android.wm.WindowManagerPerfTestBase.runWithShellPermissionIdentity;
-
-import android.app.ActivityManager;
-import android.app.ActivityManager.RunningAppProcessInfo;
-import android.app.ActivityTaskManager;
-import android.content.Context;
-import android.os.BatteryManager;
-import android.os.Bundle;
-import android.os.SystemClock;
-import android.provider.Settings;
-import android.util.Log;
-import android.view.WindowManagerPolicyConstants;
-import android.wm.WindowManagerPerfTestBase.SettingsSession;
-
-import androidx.test.platform.app.InstrumentationRegistry;
-
-import com.android.internal.policy.PhoneWindow;
-
-import org.junit.runner.Description;
-import org.junit.runner.Result;
-import org.junit.runner.notification.RunListener;
-
-import java.util.List;
+import android.perftests.utils.WindowPerfRunPreconditionBase;
 
 /** Prepare the preconditions before running performance test. */
-public class WmPerfRunListener extends RunListener {
-    private static final String TAG = WmPerfRunListener.class.getSimpleName();
-
-    private static final String ARGUMENT_LOG_ONLY = "log";
-    private static final String ARGUMENT_KILL_BACKGROUND = "kill-bg";
-    private static final String ARGUMENT_PROFILING_ITERATIONS = "profiling-iterations";
-    private static final String ARGUMENT_PROFILING_SAMPLING = "profiling-sampling";
-    private static final String DEFAULT_PROFILING_ITERATIONS = "0";
-    private static final String DEFAULT_PROFILING_SAMPLING_US = "10";
-    private static final long KILL_BACKGROUND_WAIT_MS = 3000;
-
-    /** The requested iterations to run with method profiling. */
-    static int sProfilingIterations;
-
-    /** The interval of sample profiling in microseconds. */
-    static int sSamplingIntervalUs;
-
-    private final Context mContext = InstrumentationRegistry.getInstrumentation().getContext();
-    private long mWaitPreconditionDoneMs = 500;
-
-    private final SettingsSession<Integer> mStayOnWhilePluggedInSetting = new SettingsSession<>(
-            Settings.Global.getInt(mContext.getContentResolver(),
-                    Settings.Global.STAY_ON_WHILE_PLUGGED_IN, 0),
-            value -> executeShellCommand(String.format("settings put global %s %d",
-                    Settings.Global.STAY_ON_WHILE_PLUGGED_IN, value)));
-
-    private final SettingsSession<Integer> mNavigationModeSetting = new SettingsSession<>(
-            mContext.getResources().getInteger(
-                    com.android.internal.R.integer.config_navBarInteractionMode),
-            value -> {
-                final String navOverlay;
-                switch (value) {
-                    case WindowManagerPolicyConstants.NAV_BAR_MODE_2BUTTON:
-                        navOverlay = WindowManagerPolicyConstants.NAV_BAR_MODE_2BUTTON_OVERLAY;
-                        break;
-                    case WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON:
-                        navOverlay = WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON_OVERLAY;
-                        break;
-                    case WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL:
-                    default:
-                        navOverlay = WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL_OVERLAY;
-                        break;
-                }
-                executeShellCommand("cmd overlay enable-exclusive " + navOverlay);
-            });
-
-    /** It only executes once before all tests. */
-    @Override
-    public void testRunStarted(Description description) {
-        final Bundle arguments = InstrumentationRegistry.getArguments();
-        // If true, it only logs the method names without running.
-        final boolean skip = Boolean.parseBoolean(arguments.getString(ARGUMENT_LOG_ONLY, "false"));
-        Log.i(TAG, "arguments=" + arguments);
-        if (skip) {
-            return;
-        }
-        sProfilingIterations = Integer.parseInt(
-                arguments.getString(ARGUMENT_PROFILING_ITERATIONS, DEFAULT_PROFILING_ITERATIONS));
-        sSamplingIntervalUs = Integer.parseInt(
-                arguments.getString(ARGUMENT_PROFILING_SAMPLING, DEFAULT_PROFILING_SAMPLING_US));
-
-        // Use gesture navigation for consistency.
-        mNavigationModeSetting.set(WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL);
-        // Keep the device awake during testing.
-        mStayOnWhilePluggedInSetting.set(BatteryManager.BATTERY_PLUGGED_ANY);
-
-        runWithShellPermissionIdentity(() -> {
-            final ActivityTaskManager atm = mContext.getSystemService(ActivityTaskManager.class);
-            atm.removeAllVisibleRecentTasks();
-            atm.removeRootTasksWithActivityTypes(new int[] { ACTIVITY_TYPE_STANDARD,
-                    ACTIVITY_TYPE_ASSISTANT, ACTIVITY_TYPE_RECENTS, ACTIVITY_TYPE_UNDEFINED });
-        });
-        PhoneWindow.sendCloseSystemWindows(mContext, "WmPerfTests");
-
-        if (Boolean.parseBoolean(arguments.getString(ARGUMENT_KILL_BACKGROUND))) {
-            runWithShellPermissionIdentity(this::killBackgroundProcesses);
-            mWaitPreconditionDoneMs = KILL_BACKGROUND_WAIT_MS;
-        }
-        // Wait a while for the precondition setup to complete.
-        SystemClock.sleep(mWaitPreconditionDoneMs);
-    }
-
-    private void killBackgroundProcesses() {
-        final ActivityManager am = mContext.getSystemService(ActivityManager.class);
-        final List<RunningAppProcessInfo> processes = am.getRunningAppProcesses();
-        if (processes == null) {
-            return;
-        }
-        for (RunningAppProcessInfo processInfo : processes) {
-            if (processInfo.importanceReasonCode == RunningAppProcessInfo.REASON_UNKNOWN
-                    && processInfo.importance > RunningAppProcessInfo.IMPORTANCE_SERVICE) {
-                for (String pkg : processInfo.pkgList) {
-                    am.forceStopPackage(pkg);
-                }
-            }
-        }
-    }
-
-    /** It only executes once after all tests. */
-    @Override
-    public void testRunFinished(Result result) {
-        mNavigationModeSetting.close();
-        mStayOnWhilePluggedInSetting.close();
-    }
+public class WmPerfRunListener extends WindowPerfRunPreconditionBase {
 }
diff --git a/apex/appsearch/OWNERS b/apex/appsearch/OWNERS
new file mode 100644
index 0000000..ce0c212
--- /dev/null
+++ b/apex/appsearch/OWNERS
@@ -0,0 +1 @@
[email protected]
diff --git a/apex/appsearch/framework/java/android/app/TEST_MAPPING b/apex/appsearch/framework/java/TEST_MAPPING
similarity index 100%
rename from apex/appsearch/framework/java/android/app/TEST_MAPPING
rename to apex/appsearch/framework/java/TEST_MAPPING
diff --git a/apex/appsearch/framework/java/android/app/appsearch/AppSearchManager.java b/apex/appsearch/framework/java/android/app/appsearch/AppSearchManager.java
index 5fd45ea..442ca7b 100644
--- a/apex/appsearch/framework/java/android/app/appsearch/AppSearchManager.java
+++ b/apex/appsearch/framework/java/android/app/appsearch/AppSearchManager.java
@@ -224,7 +224,11 @@
         }
         AndroidFuture<AppSearchResult> future = new AndroidFuture<>();
         try {
-            mService.setSchema(DEFAULT_DATABASE_NAME, schemaBundles, request.isForceOverride(),
+            mService.setSchema(
+                    DEFAULT_DATABASE_NAME,
+                    schemaBundles,
+                    new ArrayList<>(request.getSchemasNotPlatformSurfaceable()),
+                    request.isForceOverride(),
                     new IAppSearchResultCallback.Stub() {
                         public void onResult(AppSearchResult result) {
                             future.complete(result);
diff --git a/apex/appsearch/framework/java/android/app/appsearch/AppSearchSchema.java b/apex/appsearch/framework/java/android/app/appsearch/AppSearchSchema.java
deleted file mode 100644
index 2db74a8..0000000
--- a/apex/appsearch/framework/java/android/app/appsearch/AppSearchSchema.java
+++ /dev/null
@@ -1,447 +0,0 @@
-/*
- * 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.
- */
-
-package android.app.appsearch;
-
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.SuppressLint;
-import android.app.appsearch.exceptions.IllegalSchemaException;
-import android.os.Bundle;
-import android.util.ArraySet;
-
-import com.android.internal.util.Preconditions;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Set;
-
-/**
- * The AppSearch Schema for a particular type of document.
- *
- * <p>For example, an e-mail message or a music recording could be a schema type.
- *
- * <p>The schema consists of type information, properties, and config (like tokenization type).
- *
- * @see AppSearchManager#setSchema
- */
-public final class AppSearchSchema {
-    private static final String SCHEMA_TYPE_FIELD = "schemaType";
-    private static final String PROPERTIES_FIELD = "properties";
-
-    private final Bundle mBundle;
-
-    /** @hide */
-    public AppSearchSchema(@NonNull Bundle bundle) {
-        Preconditions.checkNotNull(bundle);
-        mBundle = bundle;
-    }
-
-    /**
-     * Returns the {@link Bundle} populated by this builder.
-     *
-     * @hide
-     */
-    @NonNull
-    public Bundle getBundle() {
-        return mBundle;
-    }
-
-    @Override
-    public String toString() {
-        return mBundle.toString();
-    }
-
-    /** Returns the name of this schema type, e.g. Email. */
-    @NonNull
-    public String getSchemaType() {
-        return mBundle.getString(SCHEMA_TYPE_FIELD, "");
-    }
-
-    /**
-     * Returns the list of {@link PropertyConfig}s that are part of this schema.
-     *
-     * <p>This method creates a new list when called.
-     */
-    @NonNull
-    public List<PropertyConfig> getProperties() {
-        ArrayList<Bundle> propertyBundles =
-                mBundle.getParcelableArrayList(AppSearchSchema.PROPERTIES_FIELD);
-        if (propertyBundles.isEmpty()) {
-            return Collections.emptyList();
-        }
-        List<PropertyConfig> ret = new ArrayList<>(propertyBundles.size());
-        for (int i = 0; i < propertyBundles.size(); i++) {
-            ret.add(new PropertyConfig(propertyBundles.get(i)));
-        }
-        return ret;
-    }
-
-    /** Builder for {@link AppSearchSchema objects}. */
-    public static final class Builder {
-        private final String mTypeName;
-        private final ArrayList<Bundle> mPropertyBundles = new ArrayList<>();
-        private final Set<String> mPropertyNames = new ArraySet<>();
-        private boolean mBuilt = false;
-
-        /** Creates a new {@link AppSearchSchema.Builder}. */
-        public Builder(@NonNull String typeName) {
-            Preconditions.checkNotNull(typeName);
-            mTypeName = typeName;
-        }
-
-        /** Adds a property to the given type. */
-        // TODO(b/171360120): MissingGetterMatchingBuilder expects a method called getPropertys, but
-        //  we provide the (correct) method getProperties. Once the bug referenced in this TODO is
-        //  fixed, remove this SuppressLint.
-        @SuppressLint("MissingGetterMatchingBuilder")
-        @NonNull
-        public AppSearchSchema.Builder addProperty(@NonNull PropertyConfig propertyConfig) {
-            Preconditions.checkState(!mBuilt, "Builder has already been used");
-            Preconditions.checkNotNull(propertyConfig);
-            String name = propertyConfig.getName();
-            if (!mPropertyNames.add(name)) {
-                throw new IllegalSchemaException("Property defined more than once: " + name);
-            }
-            mPropertyBundles.add(propertyConfig.mBundle);
-            return this;
-        }
-
-        /**
-         * Constructs a new {@link AppSearchSchema} from the contents of this builder.
-         *
-         * <p>After calling this method, the builder must no longer be used.
-         */
-        @NonNull
-        public AppSearchSchema build() {
-            Preconditions.checkState(!mBuilt, "Builder has already been used");
-            Bundle bundle = new Bundle();
-            bundle.putString(AppSearchSchema.SCHEMA_TYPE_FIELD, mTypeName);
-            bundle.putParcelableArrayList(AppSearchSchema.PROPERTIES_FIELD, mPropertyBundles);
-            mBuilt = true;
-            return new AppSearchSchema(bundle);
-        }
-    }
-
-    /**
-     * Configuration for a single property (field) of a document type.
-     *
-     * <p>For example, an {@code EmailMessage} would be a type and the {@code subject} would be a
-     * property.
-     */
-    public static final class PropertyConfig {
-        private static final String NAME_FIELD = "name";
-        private static final String DATA_TYPE_FIELD = "dataType";
-        private static final String SCHEMA_TYPE_FIELD = "schemaType";
-        private static final String CARDINALITY_FIELD = "cardinality";
-        private static final String INDEXING_TYPE_FIELD = "indexingType";
-        private static final String TOKENIZER_TYPE_FIELD = "tokenizerType";
-
-        /**
-         * Physical data-types of the contents of the property.
-         *
-         * @hide
-         */
-        // NOTE: The integer values of these constants must match the proto enum constants in
-        // com.google.android.icing.proto.PropertyConfigProto.DataType.Code.
-        @IntDef(
-                value = {
-                    DATA_TYPE_STRING,
-                    DATA_TYPE_INT64,
-                    DATA_TYPE_DOUBLE,
-                    DATA_TYPE_BOOLEAN,
-                    DATA_TYPE_BYTES,
-                    DATA_TYPE_DOCUMENT,
-                })
-        @Retention(RetentionPolicy.SOURCE)
-        public @interface DataType {}
-
-        public static final int DATA_TYPE_STRING = 1;
-        public static final int DATA_TYPE_INT64 = 2;
-        public static final int DATA_TYPE_DOUBLE = 3;
-        public static final int DATA_TYPE_BOOLEAN = 4;
-
-        /** Unstructured BLOB. */
-        public static final int DATA_TYPE_BYTES = 5;
-
-        /**
-         * Indicates that the property is itself a {@link GenericDocument}, making it part of a
-         * hierarchical schema. Any property using this DataType MUST have a valid {@link
-         * PropertyConfig#getSchemaType}.
-         */
-        public static final int DATA_TYPE_DOCUMENT = 6;
-
-        /**
-         * The cardinality of the property (whether it is required, optional or repeated).
-         *
-         * @hide
-         */
-        // NOTE: The integer values of these constants must match the proto enum constants in
-        // com.google.android.icing.proto.PropertyConfigProto.Cardinality.Code.
-        @IntDef(
-                value = {
-                    CARDINALITY_REPEATED,
-                    CARDINALITY_OPTIONAL,
-                    CARDINALITY_REQUIRED,
-                })
-        @Retention(RetentionPolicy.SOURCE)
-        public @interface Cardinality {}
-
-        /** Any number of items (including zero) [0...*]. */
-        public static final int CARDINALITY_REPEATED = 1;
-
-        /** Zero or one value [0,1]. */
-        public static final int CARDINALITY_OPTIONAL = 2;
-
-        /** Exactly one value [1]. */
-        public static final int CARDINALITY_REQUIRED = 3;
-
-        /**
-         * Encapsulates the configurations on how AppSearch should query/index these terms.
-         *
-         * @hide
-         */
-        @IntDef(
-                value = {
-                    INDEXING_TYPE_NONE,
-                    INDEXING_TYPE_EXACT_TERMS,
-                    INDEXING_TYPE_PREFIXES,
-                })
-        @Retention(RetentionPolicy.SOURCE)
-        public @interface IndexingType {}
-
-        /**
-         * Content in this property will not be tokenized or indexed.
-         *
-         * <p>Useful if the data type is not made up of terms (e.g. {@link
-         * PropertyConfig#DATA_TYPE_DOCUMENT} or {@link PropertyConfig#DATA_TYPE_BYTES} type). None
-         * of the properties inside the nested property will be indexed regardless of the value of
-         * {@code indexingType} for the nested properties.
-         */
-        public static final int INDEXING_TYPE_NONE = 0;
-
-        /**
-         * Content in this property should only be returned for queries matching the exact tokens
-         * appearing in this property.
-         *
-         * <p>Ex. A property with "fool" should NOT match a query for "foo".
-         */
-        public static final int INDEXING_TYPE_EXACT_TERMS = 1;
-
-        /**
-         * Content in this property should be returned for queries that are either exact matches or
-         * query matches of the tokens appearing in this property.
-         *
-         * <p>Ex. A property with "fool" <b>should</b> match a query for "foo".
-         */
-        public static final int INDEXING_TYPE_PREFIXES = 2;
-
-        /**
-         * Configures how tokens should be extracted from this property.
-         *
-         * @hide
-         */
-        // NOTE: The integer values of these constants must match the proto enum constants in
-        // com.google.android.icing.proto.IndexingConfig.TokenizerType.Code.
-        @IntDef(
-                value = {
-                    TOKENIZER_TYPE_NONE,
-                    TOKENIZER_TYPE_PLAIN,
-                })
-        @Retention(RetentionPolicy.SOURCE)
-        public @interface TokenizerType {}
-
-        /**
-         * It is only valid for tokenizer_type to be 'NONE' if the data type is {@link
-         * PropertyConfig#DATA_TYPE_DOCUMENT}.
-         */
-        public static final int TOKENIZER_TYPE_NONE = 0;
-
-        /** Tokenization for plain text. */
-        public static final int TOKENIZER_TYPE_PLAIN = 1;
-
-        final Bundle mBundle;
-
-        PropertyConfig(@NonNull Bundle bundle) {
-            mBundle = Preconditions.checkNotNull(bundle);
-        }
-
-        @Override
-        public String toString() {
-            return mBundle.toString();
-        }
-
-        /** Returns the name of this property. */
-        @NonNull
-        public String getName() {
-            return mBundle.getString(NAME_FIELD, "");
-        }
-
-        /** Returns the type of data the property contains (e.g. string, int, bytes, etc). */
-        public @DataType int getDataType() {
-            return mBundle.getInt(DATA_TYPE_FIELD, -1);
-        }
-
-        /**
-         * Returns the logical schema-type of the contents of this property.
-         *
-         * <p>Only set when {@link #getDataType} is set to {@link #DATA_TYPE_DOCUMENT}. Otherwise,
-         * it is {@code null}.
-         */
-        @Nullable
-        public String getSchemaType() {
-            return mBundle.getString(SCHEMA_TYPE_FIELD);
-        }
-
-        /**
-         * Returns the cardinality of the property (whether it is optional, required or repeated).
-         */
-        public @Cardinality int getCardinality() {
-            return mBundle.getInt(CARDINALITY_FIELD, -1);
-        }
-
-        /** Returns how the property is indexed. */
-        public @IndexingType int getIndexingType() {
-            return mBundle.getInt(INDEXING_TYPE_FIELD);
-        }
-
-        /** Returns how this property is tokenized (split into words). */
-        public @TokenizerType int getTokenizerType() {
-            return mBundle.getInt(TOKENIZER_TYPE_FIELD);
-        }
-
-        /**
-         * Builder for {@link PropertyConfig}.
-         *
-         * <p>The following properties must be set, or {@link PropertyConfig} construction will
-         * fail:
-         *
-         * <ul>
-         *   <li>dataType
-         *   <li>cardinality
-         * </ul>
-         *
-         * <p>In addition, if {@code schemaType} is {@link #DATA_TYPE_DOCUMENT}, {@code schemaType}
-         * is also required.
-         */
-        public static final class Builder {
-            private final Bundle mBundle = new Bundle();
-            private boolean mBuilt = false;
-
-            /** Creates a new {@link PropertyConfig.Builder}. */
-            public Builder(@NonNull String propertyName) {
-                mBundle.putString(NAME_FIELD, propertyName);
-            }
-
-            /**
-             * Type of data the property contains (e.g. string, int, bytes, etc).
-             *
-             * <p>This property must be set.
-             */
-            @NonNull
-            public PropertyConfig.Builder setDataType(@DataType int dataType) {
-                Preconditions.checkState(!mBuilt, "Builder has already been used");
-                Preconditions.checkArgumentInRange(
-                        dataType, DATA_TYPE_STRING, DATA_TYPE_DOCUMENT, "dataType");
-                mBundle.putInt(DATA_TYPE_FIELD, dataType);
-                return this;
-            }
-
-            /**
-             * The logical schema-type of the contents of this property.
-             *
-             * <p>Only required when {@link #setDataType} is set to {@link #DATA_TYPE_DOCUMENT}.
-             * Otherwise, it is ignored.
-             */
-            @NonNull
-            public PropertyConfig.Builder setSchemaType(@NonNull String schemaType) {
-                Preconditions.checkState(!mBuilt, "Builder has already been used");
-                Preconditions.checkNotNull(schemaType);
-                mBundle.putString(SCHEMA_TYPE_FIELD, schemaType);
-                return this;
-            }
-
-            /**
-             * The cardinality of the property (whether it is optional, required or repeated).
-             *
-             * <p>This property must be set.
-             */
-            @NonNull
-            public PropertyConfig.Builder setCardinality(@Cardinality int cardinality) {
-                Preconditions.checkState(!mBuilt, "Builder has already been used");
-                Preconditions.checkArgumentInRange(
-                        cardinality, CARDINALITY_REPEATED, CARDINALITY_REQUIRED, "cardinality");
-                mBundle.putInt(CARDINALITY_FIELD, cardinality);
-                return this;
-            }
-
-            /**
-             * Configures how a property should be indexed so that it can be retrieved by queries.
-             */
-            @NonNull
-            public PropertyConfig.Builder setIndexingType(@IndexingType int indexingType) {
-                Preconditions.checkState(!mBuilt, "Builder has already been used");
-                Preconditions.checkArgumentInRange(
-                        indexingType, INDEXING_TYPE_NONE, INDEXING_TYPE_PREFIXES, "indexingType");
-                mBundle.putInt(INDEXING_TYPE_FIELD, indexingType);
-                return this;
-            }
-
-            /** Configures how this property should be tokenized (split into words). */
-            @NonNull
-            public PropertyConfig.Builder setTokenizerType(@TokenizerType int tokenizerType) {
-                Preconditions.checkState(!mBuilt, "Builder has already been used");
-                Preconditions.checkArgumentInRange(
-                        tokenizerType, TOKENIZER_TYPE_NONE, TOKENIZER_TYPE_PLAIN, "tokenizerType");
-                mBundle.putInt(TOKENIZER_TYPE_FIELD, tokenizerType);
-                return this;
-            }
-
-            /**
-             * Constructs a new {@link PropertyConfig} from the contents of this builder.
-             *
-             * <p>After calling this method, the builder must no longer be used.
-             *
-             * @throws IllegalSchemaException If the property is not correctly populated (e.g.
-             *     missing {@code dataType}).
-             */
-            @NonNull
-            public PropertyConfig build() {
-                Preconditions.checkState(!mBuilt, "Builder has already been used");
-                // TODO(b/147692920): Send the schema to Icing Lib for official validation, instead
-                //     of partially reimplementing some of the validation Icing does here.
-                if (!mBundle.containsKey(DATA_TYPE_FIELD)) {
-                    throw new IllegalSchemaException("Missing field: dataType");
-                }
-                if (mBundle.getString(SCHEMA_TYPE_FIELD, "").isEmpty()
-                        && mBundle.getInt(DATA_TYPE_FIELD) == DATA_TYPE_DOCUMENT) {
-                    throw new IllegalSchemaException(
-                            "Missing field: schemaType (required for configs with "
-                                    + "dataType = DOCUMENT)");
-                }
-                if (!mBundle.containsKey(CARDINALITY_FIELD)) {
-                    throw new IllegalSchemaException("Missing field: cardinality");
-                }
-                mBuilt = true;
-                return new PropertyConfig(mBundle);
-            }
-        }
-    }
-}
diff --git a/apex/appsearch/framework/java/android/app/appsearch/AppSearchSession.java b/apex/appsearch/framework/java/android/app/appsearch/AppSearchSession.java
index 9c7ccea..b7cd4f5 100644
--- a/apex/appsearch/framework/java/android/app/appsearch/AppSearchSession.java
+++ b/apex/appsearch/framework/java/android/app/appsearch/AppSearchSession.java
@@ -140,7 +140,11 @@
             schemaBundles.add(schema.getBundle());
         }
         try {
-            mService.setSchema(mDatabaseName, schemaBundles, request.isForceOverride(),
+            mService.setSchema(
+                    mDatabaseName,
+                    schemaBundles,
+                    new ArrayList<>(request.getSchemasNotPlatformSurfaceable()),
+                    request.isForceOverride(),
                     new IAppSearchResultCallback.Stub() {
                         public void onResult(AppSearchResult result) {
                             executor.execute(() -> callback.accept(result));
diff --git a/apex/appsearch/framework/java/android/app/appsearch/GenericDocument.java b/apex/appsearch/framework/java/android/app/appsearch/GenericDocument.java
deleted file mode 100644
index 0056377..0000000
--- a/apex/appsearch/framework/java/android/app/appsearch/GenericDocument.java
+++ /dev/null
@@ -1,963 +0,0 @@
-/*
- * 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.
- */
-
-package android.app.appsearch;
-
-import android.annotation.IntRange;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.SuppressLint;
-import android.app.appsearch.exceptions.AppSearchException;
-import android.os.Bundle;
-import android.util.Log;
-
-import com.android.internal.util.Preconditions;
-
-import java.lang.reflect.Array;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Set;
-
-/**
- * Represents a document unit.
- *
- * <p>Documents are constructed via {@link GenericDocument.Builder}.
- *
- * @see AppSearchManager#putDocuments
- * @see AppSearchManager#getByUri
- * @see AppSearchManager#query
- */
-public class GenericDocument {
-    private static final String TAG = "GenericDocument";
-
-    /** The default empty namespace. */
-    public static final String DEFAULT_NAMESPACE = "";
-
-    /**
-     * The maximum number of elements in a repeatable field. Will reject the request if exceed this
-     * limit.
-     */
-    private static final int MAX_REPEATED_PROPERTY_LENGTH = 100;
-
-    /**
-     * The maximum {@link String#length} of a {@link String} field. Will reject the request if
-     * {@link String}s longer than this.
-     */
-    private static final int MAX_STRING_LENGTH = 20_000;
-
-    /** The maximum number of indexed properties a document can have. */
-    private static final int MAX_INDEXED_PROPERTIES = 16;
-
-    /** The default score of document. */
-    private static final int DEFAULT_SCORE = 0;
-
-    /** The default time-to-live in millisecond of a document, which is infinity. */
-    private static final long DEFAULT_TTL_MILLIS = 0L;
-
-    private static final String PROPERTIES_FIELD = "properties";
-    private static final String BYTE_ARRAY_FIELD = "byteArray";
-    private static final String SCHEMA_TYPE_FIELD = "schemaType";
-    private static final String URI_FIELD = "uri";
-    private static final String SCORE_FIELD = "score";
-    private static final String TTL_MILLIS_FIELD = "ttlMillis";
-    private static final String CREATION_TIMESTAMP_MILLIS_FIELD = "creationTimestampMillis";
-    private static final String NAMESPACE_FIELD = "namespace";
-
-    /**
-     * The maximum number of indexed properties a document can have.
-     *
-     * <p>Indexed properties are properties where the {@link
-     * AppSearchSchema.PropertyConfig#getIndexingType()} constant is anything other than {@link
-     * AppSearchSchema.PropertyConfig.IndexingType#INDEXING_TYPE_NONE}.
-     */
-    public static int getMaxIndexedProperties() {
-        return MAX_INDEXED_PROPERTIES;
-    }
-
-    /** Contains {@link GenericDocument} basic information (uri, schemaType etc). */
-    @NonNull final Bundle mBundle;
-
-    /**
-     * Contains all properties in {@link GenericDocument} to support getting properties via keys.
-     */
-    @NonNull private final Bundle mProperties;
-
-    @NonNull private final String mUri;
-    @NonNull private final String mSchemaType;
-    private final long mCreationTimestampMillis;
-    @Nullable private Integer mHashCode;
-
-    /**
-     * Rebuilds a {@link GenericDocument} by the a bundle.
-     *
-     * @param bundle Contains {@link GenericDocument} basic information (uri, schemaType etc) and a
-     *     properties bundle contains all properties in {@link GenericDocument} to support getting
-     *     properties via keys.
-     * @hide
-     */
-    public GenericDocument(@NonNull Bundle bundle) {
-        Preconditions.checkNotNull(bundle);
-        mBundle = bundle;
-        mProperties = Preconditions.checkNotNull(bundle.getParcelable(PROPERTIES_FIELD));
-        mUri = Preconditions.checkNotNull(mBundle.getString(URI_FIELD));
-        mSchemaType = Preconditions.checkNotNull(mBundle.getString(SCHEMA_TYPE_FIELD));
-        mCreationTimestampMillis =
-                mBundle.getLong(CREATION_TIMESTAMP_MILLIS_FIELD, System.currentTimeMillis());
-    }
-
-    /**
-     * Creates a new {@link GenericDocument} from an existing instance.
-     *
-     * <p>This method should be only used by constructor of a subclass.
-     */
-    protected GenericDocument(@NonNull GenericDocument document) {
-        this(document.mBundle);
-    }
-
-    /**
-     * Returns the {@link Bundle} populated by this builder.
-     *
-     * @hide
-     */
-    @NonNull
-    public Bundle getBundle() {
-        return mBundle;
-    }
-
-    /** Returns the URI of the {@link GenericDocument}. */
-    @NonNull
-    public String getUri() {
-        return mUri;
-    }
-
-    /** Returns the namespace of the {@link GenericDocument}. */
-    @NonNull
-    public String getNamespace() {
-        return mBundle.getString(NAMESPACE_FIELD, DEFAULT_NAMESPACE);
-    }
-
-    /** Returns the schema type of the {@link GenericDocument}. */
-    @NonNull
-    public String getSchemaType() {
-        return mSchemaType;
-    }
-
-    /**
-     * Returns the creation timestamp of the {@link GenericDocument}, in milliseconds.
-     *
-     * <p>The value is in the {@link System#currentTimeMillis} time base.
-     */
-    public long getCreationTimestampMillis() {
-        return mCreationTimestampMillis;
-    }
-
-    /**
-     * Returns the TTL (Time To Live) of the {@link GenericDocument}, in milliseconds.
-     *
-     * <p>The TTL is measured against {@link #getCreationTimestampMillis}. At the timestamp of
-     * {@code creationTimestampMillis + ttlMillis}, measured in the {@link System#currentTimeMillis}
-     * time base, the document will be auto-deleted.
-     *
-     * <p>The default value is 0, which means the document is permanent and won't be auto-deleted
-     * until the app is uninstalled.
-     */
-    public long getTtlMillis() {
-        return mBundle.getLong(TTL_MILLIS_FIELD, DEFAULT_TTL_MILLIS);
-    }
-
-    /**
-     * Returns the score of the {@link GenericDocument}.
-     *
-     * <p>The score is a query-independent measure of the document's quality, relative to other
-     * {@link GenericDocument}s of the same type.
-     *
-     * <p>Results may be sorted by score using {@link SearchSpec.Builder#setRankingStrategy}.
-     * Documents with higher scores are considered better than documents with lower scores.
-     *
-     * <p>Any nonnegative integer can be used a score.
-     */
-    public int getScore() {
-        return mBundle.getInt(SCORE_FIELD, DEFAULT_SCORE);
-    }
-
-    /** Returns the names of all properties defined in this document. */
-    @NonNull
-    public Set<String> getPropertyNames() {
-        return Collections.unmodifiableSet(mProperties.keySet());
-    }
-
-    /**
-     * Retrieves a {@link String} value by key.
-     *
-     * @param key The key to look for.
-     * @return The first {@link String} associated with the given key or {@code null} if there is no
-     *     such key or the value is of a different type.
-     */
-    @Nullable
-    public String getPropertyString(@NonNull String key) {
-        Preconditions.checkNotNull(key);
-        String[] propertyArray = getPropertyStringArray(key);
-        if (propertyArray == null || propertyArray.length == 0) {
-            return null;
-        }
-        warnIfSinglePropertyTooLong("String", key, propertyArray.length);
-        return propertyArray[0];
-    }
-
-    /**
-     * Retrieves a {@code long} value by key.
-     *
-     * @param key The key to look for.
-     * @return The first {@code long} associated with the given key or default value {@code 0} if
-     *     there is no such key or the value is of a different type.
-     */
-    public long getPropertyLong(@NonNull String key) {
-        Preconditions.checkNotNull(key);
-        long[] propertyArray = getPropertyLongArray(key);
-        if (propertyArray == null || propertyArray.length == 0) {
-            return 0;
-        }
-        warnIfSinglePropertyTooLong("Long", key, propertyArray.length);
-        return propertyArray[0];
-    }
-
-    /**
-     * Retrieves a {@code double} value by key.
-     *
-     * @param key The key to look for.
-     * @return The first {@code double} associated with the given key or default value {@code 0.0}
-     *     if there is no such key or the value is of a different type.
-     */
-    public double getPropertyDouble(@NonNull String key) {
-        Preconditions.checkNotNull(key);
-        double[] propertyArray = getPropertyDoubleArray(key);
-        if (propertyArray == null || propertyArray.length == 0) {
-            return 0.0;
-        }
-        warnIfSinglePropertyTooLong("Double", key, propertyArray.length);
-        return propertyArray[0];
-    }
-
-    /**
-     * Retrieves a {@code boolean} value by key.
-     *
-     * @param key The key to look for.
-     * @return The first {@code boolean} associated with the given key or default value {@code
-     *     false} if there is no such key or the value is of a different type.
-     */
-    public boolean getPropertyBoolean(@NonNull String key) {
-        Preconditions.checkNotNull(key);
-        boolean[] propertyArray = getPropertyBooleanArray(key);
-        if (propertyArray == null || propertyArray.length == 0) {
-            return false;
-        }
-        warnIfSinglePropertyTooLong("Boolean", key, propertyArray.length);
-        return propertyArray[0];
-    }
-
-    /**
-     * Retrieves a {@code byte[]} value by key.
-     *
-     * @param key The key to look for.
-     * @return The first {@code byte[]} associated with the given key or {@code null} if there is no
-     *     such key or the value is of a different type.
-     */
-    @Nullable
-    public byte[] getPropertyBytes(@NonNull String key) {
-        Preconditions.checkNotNull(key);
-        byte[][] propertyArray = getPropertyBytesArray(key);
-        if (propertyArray == null || propertyArray.length == 0) {
-            return null;
-        }
-        warnIfSinglePropertyTooLong("ByteArray", key, propertyArray.length);
-        return propertyArray[0];
-    }
-
-    /**
-     * Retrieves a {@link GenericDocument} value by key.
-     *
-     * @param key The key to look for.
-     * @return The first {@link GenericDocument} associated with the given key or {@code null} if
-     *     there is no such key or the value is of a different type.
-     */
-    @Nullable
-    public GenericDocument getPropertyDocument(@NonNull String key) {
-        Preconditions.checkNotNull(key);
-        GenericDocument[] propertyArray = getPropertyDocumentArray(key);
-        if (propertyArray == null || propertyArray.length == 0) {
-            return null;
-        }
-        warnIfSinglePropertyTooLong("Document", key, propertyArray.length);
-        return propertyArray[0];
-    }
-
-    /** Prints a warning to logcat if the given propertyLength is greater than 1. */
-    private static void warnIfSinglePropertyTooLong(
-            @NonNull String propertyType, @NonNull String key, int propertyLength) {
-        if (propertyLength > 1) {
-            Log.w(
-                    TAG,
-                    "The value for \""
-                            + key
-                            + "\" contains "
-                            + propertyLength
-                            + " elements. Only the first one will be returned from "
-                            + "getProperty"
-                            + propertyType
-                            + "(). Try getProperty"
-                            + propertyType
-                            + "Array().");
-        }
-    }
-
-    /**
-     * Retrieves a repeated {@code String} property by key.
-     *
-     * @param key The key to look for.
-     * @return The {@code String[]} associated with the given key, or {@code null} if no value is
-     *     set or the value is of a different type.
-     */
-    @Nullable
-    public String[] getPropertyStringArray(@NonNull String key) {
-        Preconditions.checkNotNull(key);
-        return getAndCastPropertyArray(key, String[].class);
-    }
-
-    /**
-     * Retrieves a repeated {@link String} property by key.
-     *
-     * @param key The key to look for.
-     * @return The {@code long[]} associated with the given key, or {@code null} if no value is set
-     *     or the value is of a different type.
-     */
-    @Nullable
-    public long[] getPropertyLongArray(@NonNull String key) {
-        Preconditions.checkNotNull(key);
-        return getAndCastPropertyArray(key, long[].class);
-    }
-
-    /**
-     * Retrieves a repeated {@code double} property by key.
-     *
-     * @param key The key to look for.
-     * @return The {@code double[]} associated with the given key, or {@code null} if no value is
-     *     set or the value is of a different type.
-     */
-    @Nullable
-    public double[] getPropertyDoubleArray(@NonNull String key) {
-        Preconditions.checkNotNull(key);
-        return getAndCastPropertyArray(key, double[].class);
-    }
-
-    /**
-     * Retrieves a repeated {@code boolean} property by key.
-     *
-     * @param key The key to look for.
-     * @return The {@code boolean[]} associated with the given key, or {@code null} if no value is
-     *     set or the value is of a different type.
-     */
-    @Nullable
-    public boolean[] getPropertyBooleanArray(@NonNull String key) {
-        Preconditions.checkNotNull(key);
-        return getAndCastPropertyArray(key, boolean[].class);
-    }
-
-    /**
-     * Retrieves a {@code byte[][]} property by key.
-     *
-     * @param key The key to look for.
-     * @return The {@code byte[][]} associated with the given key, or {@code null} if no value is
-     *     set or the value is of a different type.
-     */
-    @SuppressLint("ArrayReturn")
-    @Nullable
-    @SuppressWarnings("unchecked")
-    public byte[][] getPropertyBytesArray(@NonNull String key) {
-        Preconditions.checkNotNull(key);
-        ArrayList<Bundle> bundles = getAndCastPropertyArray(key, ArrayList.class);
-        if (bundles == null || bundles.size() == 0) {
-            return null;
-        }
-        byte[][] bytes = new byte[bundles.size()][];
-        for (int i = 0; i < bundles.size(); i++) {
-            Bundle bundle = bundles.get(i);
-            if (bundle == null) {
-                Log.e(TAG, "The inner bundle is null at " + i + ", for key: " + key);
-                continue;
-            }
-            byte[] innerBytes = bundle.getByteArray(BYTE_ARRAY_FIELD);
-            if (innerBytes == null) {
-                Log.e(TAG, "The bundle at " + i + " contains a null byte[].");
-                continue;
-            }
-            bytes[i] = innerBytes;
-        }
-        return bytes;
-    }
-
-    /**
-     * Retrieves a repeated {@link GenericDocument} property by key.
-     *
-     * @param key The key to look for.
-     * @return The {@link GenericDocument}[] associated with the given key, or {@code null} if no
-     *     value is set or the value is of a different type.
-     */
-    @SuppressLint("ArrayReturn")
-    @Nullable
-    public GenericDocument[] getPropertyDocumentArray(@NonNull String key) {
-        Preconditions.checkNotNull(key);
-        Bundle[] bundles = getAndCastPropertyArray(key, Bundle[].class);
-        if (bundles == null || bundles.length == 0) {
-            return null;
-        }
-        GenericDocument[] documents = new GenericDocument[bundles.length];
-        for (int i = 0; i < bundles.length; i++) {
-            if (bundles[i] == null) {
-                Log.e(TAG, "The inner bundle is null at " + i + ", for key: " + key);
-                continue;
-            }
-            documents[i] = new GenericDocument(bundles[i]);
-        }
-        return documents;
-    }
-
-    /**
-     * Gets a repeated property of the given key, and casts it to the given class type, which must
-     * be an array class type.
-     */
-    @Nullable
-    private <T> T getAndCastPropertyArray(@NonNull String key, @NonNull Class<T> tClass) {
-        Object value = mProperties.get(key);
-        if (value == null) {
-            return null;
-        }
-        try {
-            return tClass.cast(value);
-        } catch (ClassCastException e) {
-            Log.w(TAG, "Error casting to requested type for key \"" + key + "\"", e);
-            return null;
-        }
-    }
-
-    @Override
-    public boolean equals(@Nullable Object other) {
-        if (this == other) {
-            return true;
-        }
-        if (!(other instanceof GenericDocument)) {
-            return false;
-        }
-        GenericDocument otherDocument = (GenericDocument) other;
-        return bundleEquals(this.mBundle, otherDocument.mBundle);
-    }
-
-    /**
-     * Deeply checks whether two bundles are equal.
-     *
-     * <p>Two bundles will be considered equal if they contain the same content.
-     */
-    @SuppressWarnings("unchecked")
-    private static boolean bundleEquals(Bundle one, Bundle two) {
-        if (one.size() != two.size()) {
-            return false;
-        }
-        Set<String> keySetOne = one.keySet();
-        Object valueOne;
-        Object valueTwo;
-        // Bundle inherit its equals() from Object.java, which only compare their memory address.
-        // We should iterate all keys and check their presents and values in both bundle.
-        for (String key : keySetOne) {
-            valueOne = one.get(key);
-            valueTwo = two.get(key);
-            if (valueOne instanceof Bundle
-                    && valueTwo instanceof Bundle
-                    && !bundleEquals((Bundle) valueOne, (Bundle) valueTwo)) {
-                return false;
-            } else if (valueOne == null && (valueTwo != null || !two.containsKey(key))) {
-                // If we call bundle.get(key) when the 'key' doesn't actually exist in the
-                // bundle, we'll get back a null. So make sure that both values are null and
-                // both keys exist in the bundle.
-                return false;
-            } else if (valueOne instanceof boolean[]) {
-                if (!(valueTwo instanceof boolean[])
-                        || !Arrays.equals((boolean[]) valueOne, (boolean[]) valueTwo)) {
-                    return false;
-                }
-            } else if (valueOne instanceof long[]) {
-                if (!(valueTwo instanceof long[])
-                        || !Arrays.equals((long[]) valueOne, (long[]) valueTwo)) {
-                    return false;
-                }
-            } else if (valueOne instanceof double[]) {
-                if (!(valueTwo instanceof double[])
-                        || !Arrays.equals((double[]) valueOne, (double[]) valueTwo)) {
-                    return false;
-                }
-            } else if (valueOne instanceof Bundle[]) {
-                if (!(valueTwo instanceof Bundle[])) {
-                    return false;
-                }
-                Bundle[] bundlesOne = (Bundle[]) valueOne;
-                Bundle[] bundlesTwo = (Bundle[]) valueTwo;
-                if (bundlesOne.length != bundlesTwo.length) {
-                    return false;
-                }
-                for (int i = 0; i < bundlesOne.length; i++) {
-                    if (!bundleEquals(bundlesOne[i], bundlesTwo[i])) {
-                        return false;
-                    }
-                }
-            } else if (valueOne instanceof ArrayList) {
-                if (!(valueTwo instanceof ArrayList)) {
-                    return false;
-                }
-                ArrayList<Bundle> bundlesOne = (ArrayList<Bundle>) valueOne;
-                ArrayList<Bundle> bundlesTwo = (ArrayList<Bundle>) valueTwo;
-                if (bundlesOne.size() != bundlesTwo.size()) {
-                    return false;
-                }
-                for (int i = 0; i < bundlesOne.size(); i++) {
-                    if (!bundleEquals(bundlesOne.get(i), bundlesTwo.get(i))) {
-                        return false;
-                    }
-                }
-            } else if (valueOne instanceof Object[]) {
-                if (!(valueTwo instanceof Object[])
-                        || !Arrays.equals((Object[]) valueOne, (Object[]) valueTwo)) {
-                    return false;
-                }
-            }
-        }
-        return true;
-    }
-
-    @Override
-    public int hashCode() {
-        if (mHashCode == null) {
-            mHashCode = bundleHashCode(mBundle);
-        }
-        return mHashCode;
-    }
-
-    /**
-     * Calculates the hash code for a bundle.
-     *
-     * <p>The hash code is only effected by the contents in the bundle. Bundles will get consistent
-     * hash code if they have same contents.
-     */
-    @SuppressWarnings("unchecked")
-    private static int bundleHashCode(Bundle bundle) {
-        int[] hashCodes = new int[bundle.size()];
-        int i = 0;
-        // Bundle inherit its hashCode() from Object.java, which only relative to their memory
-        // address. Bundle doesn't have an order, so we should iterate all keys and combine
-        // their value's hashcode into an array. And use the hashcode of the array to be
-        // the hashcode of the bundle.
-        for (String key : bundle.keySet()) {
-            Object value = bundle.get(key);
-            if (value instanceof boolean[]) {
-                hashCodes[i++] = Arrays.hashCode((boolean[]) value);
-            } else if (value instanceof long[]) {
-                hashCodes[i++] = Arrays.hashCode((long[]) value);
-            } else if (value instanceof double[]) {
-                hashCodes[i++] = Arrays.hashCode((double[]) value);
-            } else if (value instanceof String[]) {
-                hashCodes[i++] = Arrays.hashCode((Object[]) value);
-            } else if (value instanceof Bundle) {
-                hashCodes[i++] = bundleHashCode((Bundle) value);
-            } else if (value instanceof Bundle[]) {
-                Bundle[] bundles = (Bundle[]) value;
-                int[] innerHashCodes = new int[bundles.length];
-                for (int j = 0; j < innerHashCodes.length; j++) {
-                    innerHashCodes[j] = bundleHashCode(bundles[j]);
-                }
-                hashCodes[i++] = Arrays.hashCode(innerHashCodes);
-            } else if (value instanceof ArrayList) {
-                ArrayList<Bundle> bundles = (ArrayList<Bundle>) value;
-                int[] innerHashCodes = new int[bundles.size()];
-                for (int j = 0; j < innerHashCodes.length; j++) {
-                    innerHashCodes[j] = bundleHashCode(bundles.get(j));
-                }
-                hashCodes[i++] = Arrays.hashCode(innerHashCodes);
-            } else {
-                hashCodes[i++] = value.hashCode();
-            }
-        }
-        return Arrays.hashCode(hashCodes);
-    }
-
-    @Override
-    @NonNull
-    public String toString() {
-        return bundleToString(mBundle).toString();
-    }
-
-    @SuppressWarnings("unchecked")
-    private static StringBuilder bundleToString(Bundle bundle) {
-        StringBuilder stringBuilder = new StringBuilder();
-        try {
-            final Set<String> keySet = bundle.keySet();
-            String[] keys = keySet.toArray(new String[0]);
-            // Sort keys to make output deterministic. We need a custom comparator to handle
-            // nulls (arbitrarily putting them first, similar to Comparator.nullsFirst, which is
-            // only available since N).
-            Arrays.sort(
-                    keys,
-                    (@Nullable String s1, @Nullable String s2) -> {
-                        if (s1 == null) {
-                            return s2 == null ? 0 : -1;
-                        } else if (s2 == null) {
-                            return 1;
-                        } else {
-                            return s1.compareTo(s2);
-                        }
-                    });
-            for (String key : keys) {
-                stringBuilder.append("{ key: '").append(key).append("' value: ");
-                Object valueObject = bundle.get(key);
-                if (valueObject == null) {
-                    stringBuilder.append("<null>");
-                } else if (valueObject instanceof Bundle) {
-                    stringBuilder.append(bundleToString((Bundle) valueObject));
-                } else if (valueObject.getClass().isArray()) {
-                    stringBuilder.append("[ ");
-                    for (int i = 0; i < Array.getLength(valueObject); i++) {
-                        Object element = Array.get(valueObject, i);
-                        stringBuilder.append("'");
-                        if (element instanceof Bundle) {
-                            stringBuilder.append(bundleToString((Bundle) element));
-                        } else {
-                            stringBuilder.append(Array.get(valueObject, i));
-                        }
-                        stringBuilder.append("' ");
-                    }
-                    stringBuilder.append("]");
-                } else if (valueObject instanceof ArrayList) {
-                    for (Bundle innerBundle : (ArrayList<Bundle>) valueObject) {
-                        stringBuilder.append(bundleToString(innerBundle));
-                    }
-                } else {
-                    stringBuilder.append(valueObject.toString());
-                }
-                stringBuilder.append(" } ");
-            }
-        } catch (RuntimeException e) {
-            // Catch any exceptions here since corrupt Bundles can throw different types of
-            // exceptions (e.g. b/38445840 & b/68937025).
-            stringBuilder.append("<error>");
-        }
-        return stringBuilder;
-    }
-
-    /**
-     * The builder class for {@link GenericDocument}.
-     *
-     * @param <BuilderType> Type of subclass who extends this.
-     */
-    // This builder is specifically designed to be extended by classes deriving from
-    // GenericDocument.
-    @SuppressLint("StaticFinalBuilder")
-    public static class Builder<BuilderType extends Builder> {
-
-        private final Bundle mProperties = new Bundle();
-        private final Bundle mBundle = new Bundle();
-        private final BuilderType mBuilderTypeInstance;
-        private boolean mBuilt = false;
-
-        /**
-         * Create a new {@link GenericDocument.Builder}.
-         *
-         * @param uri The uri of {@link GenericDocument}.
-         * @param schemaType The schema type of the {@link GenericDocument}. The passed-in {@code
-         *     schemaType} must be defined using {@link AppSearchManager#setSchema} prior to
-         *     inserting a document of this {@code schemaType} into the AppSearch index using {@link
-         *     AppSearchManager#putDocuments}. Otherwise, the document will be rejected by {@link
-         *     AppSearchManager#putDocuments}.
-         */
-        @SuppressWarnings("unchecked")
-        public Builder(@NonNull String uri, @NonNull String schemaType) {
-            Preconditions.checkNotNull(uri);
-            Preconditions.checkNotNull(schemaType);
-            mBuilderTypeInstance = (BuilderType) this;
-            mBundle.putString(GenericDocument.URI_FIELD, uri);
-            mBundle.putString(GenericDocument.SCHEMA_TYPE_FIELD, schemaType);
-            mBundle.putString(GenericDocument.NAMESPACE_FIELD, DEFAULT_NAMESPACE);
-            // Set current timestamp for creation timestamp by default.
-            mBundle.putLong(
-                    GenericDocument.CREATION_TIMESTAMP_MILLIS_FIELD, System.currentTimeMillis());
-            mBundle.putLong(GenericDocument.TTL_MILLIS_FIELD, DEFAULT_TTL_MILLIS);
-            mBundle.putInt(GenericDocument.SCORE_FIELD, DEFAULT_SCORE);
-            mBundle.putBundle(PROPERTIES_FIELD, mProperties);
-        }
-
-        /**
-         * Sets the app-defined namespace this Document resides in. No special values are reserved
-         * or understood by the infrastructure.
-         *
-         * <p>URIs are unique within a namespace.
-         *
-         * <p>The number of namespaces per app should be kept small for efficiency reasons.
-         */
-        @NonNull
-        public BuilderType setNamespace(@NonNull String namespace) {
-            mBundle.putString(GenericDocument.NAMESPACE_FIELD, namespace);
-            return mBuilderTypeInstance;
-        }
-
-        /**
-         * Sets the score of the {@link GenericDocument}.
-         *
-         * <p>The score is a query-independent measure of the document's quality, relative to other
-         * {@link GenericDocument}s of the same type.
-         *
-         * <p>Results may be sorted by score using {@link SearchSpec.Builder#setRankingStrategy}.
-         * Documents with higher scores are considered better than documents with lower scores.
-         *
-         * <p>Any nonnegative integer can be used a score.
-         *
-         * @throws IllegalArgumentException If the provided value is negative.
-         */
-        @NonNull
-        public BuilderType setScore(@IntRange(from = 0, to = Integer.MAX_VALUE) int score) {
-            Preconditions.checkState(!mBuilt, "Builder has already been used");
-            if (score < 0) {
-                throw new IllegalArgumentException("Document score cannot be negative.");
-            }
-            mBundle.putInt(GenericDocument.SCORE_FIELD, score);
-            return mBuilderTypeInstance;
-        }
-
-        /**
-         * Sets the creation timestamp of the {@link GenericDocument}, in milliseconds.
-         *
-         * <p>Should be set using a value obtained from the {@link System#currentTimeMillis} time
-         * base.
-         */
-        @NonNull
-        public BuilderType setCreationTimestampMillis(long creationTimestampMillis) {
-            Preconditions.checkState(!mBuilt, "Builder has already been used");
-            mBundle.putLong(
-                    GenericDocument.CREATION_TIMESTAMP_MILLIS_FIELD, creationTimestampMillis);
-            return mBuilderTypeInstance;
-        }
-
-        /**
-         * Sets the TTL (Time To Live) of the {@link GenericDocument}, in milliseconds.
-         *
-         * <p>The TTL is measured against {@link #getCreationTimestampMillis}. At the timestamp of
-         * {@code creationTimestampMillis + ttlMillis}, measured in the {@link
-         * System#currentTimeMillis} time base, the document will be auto-deleted.
-         *
-         * <p>The default value is 0, which means the document is permanent and won't be
-         * auto-deleted until the app is uninstalled.
-         *
-         * @param ttlMillis A non-negative duration in milliseconds.
-         * @throws IllegalArgumentException If the provided value is negative.
-         */
-        @NonNull
-        public BuilderType setTtlMillis(long ttlMillis) {
-            Preconditions.checkState(!mBuilt, "Builder has already been used");
-            if (ttlMillis < 0) {
-                throw new IllegalArgumentException("Document ttlMillis cannot be negative.");
-            }
-            mBundle.putLong(GenericDocument.TTL_MILLIS_FIELD, ttlMillis);
-            return mBuilderTypeInstance;
-        }
-
-        /**
-         * Sets one or multiple {@code String} values for a property, replacing its previous values.
-         *
-         * @param key The key associated with the {@code values}.
-         * @param values The {@code String} values of the property.
-         */
-        @NonNull
-        public BuilderType setPropertyString(@NonNull String key, @NonNull String... values) {
-            Preconditions.checkState(!mBuilt, "Builder has already been used");
-            Preconditions.checkNotNull(key);
-            Preconditions.checkNotNull(values);
-            putInPropertyBundle(key, values);
-            return mBuilderTypeInstance;
-        }
-
-        /**
-         * Sets one or multiple {@code boolean} values for a property, replacing its previous
-         * values.
-         *
-         * @param key The key associated with the {@code values}.
-         * @param values The {@code boolean} values of the property.
-         */
-        @NonNull
-        public BuilderType setPropertyBoolean(@NonNull String key, @NonNull boolean... values) {
-            Preconditions.checkState(!mBuilt, "Builder has already been used");
-            Preconditions.checkNotNull(key);
-            Preconditions.checkNotNull(values);
-            putInPropertyBundle(key, values);
-            return mBuilderTypeInstance;
-        }
-
-        /**
-         * Sets one or multiple {@code long} values for a property, replacing its previous values.
-         *
-         * @param key The key associated with the {@code values}.
-         * @param values The {@code long} values of the property.
-         */
-        @NonNull
-        public BuilderType setPropertyLong(@NonNull String key, @NonNull long... values) {
-            Preconditions.checkState(!mBuilt, "Builder has already been used");
-            Preconditions.checkNotNull(key);
-            Preconditions.checkNotNull(values);
-            putInPropertyBundle(key, values);
-            return mBuilderTypeInstance;
-        }
-
-        /**
-         * Sets one or multiple {@code double} values for a property, replacing its previous values.
-         *
-         * @param key The key associated with the {@code values}.
-         * @param values The {@code double} values of the property.
-         */
-        @NonNull
-        public BuilderType setPropertyDouble(@NonNull String key, @NonNull double... values) {
-            Preconditions.checkState(!mBuilt, "Builder has already been used");
-            Preconditions.checkNotNull(key);
-            Preconditions.checkNotNull(values);
-            putInPropertyBundle(key, values);
-            return mBuilderTypeInstance;
-        }
-
-        /**
-         * Sets one or multiple {@code byte[]} for a property, replacing its previous values.
-         *
-         * @param key The key associated with the {@code values}.
-         * @param values The {@code byte[]} of the property.
-         */
-        @NonNull
-        public BuilderType setPropertyBytes(@NonNull String key, @NonNull byte[]... values) {
-            Preconditions.checkState(!mBuilt, "Builder has already been used");
-            Preconditions.checkNotNull(key);
-            Preconditions.checkNotNull(values);
-            putInPropertyBundle(key, values);
-            return mBuilderTypeInstance;
-        }
-
-        /**
-         * Sets one or multiple {@link GenericDocument} values for a property, replacing its
-         * previous values.
-         *
-         * @param key The key associated with the {@code values}.
-         * @param values The {@link GenericDocument} values of the property.
-         */
-        @NonNull
-        public BuilderType setPropertyDocument(
-                @NonNull String key, @NonNull GenericDocument... values) {
-            Preconditions.checkState(!mBuilt, "Builder has already been used");
-            Preconditions.checkNotNull(key);
-            Preconditions.checkNotNull(values);
-            putInPropertyBundle(key, values);
-            return mBuilderTypeInstance;
-        }
-
-        private void putInPropertyBundle(@NonNull String key, @NonNull String[] values)
-                throws IllegalArgumentException {
-            validateRepeatedPropertyLength(key, values.length);
-            for (int i = 0; i < values.length; i++) {
-                if (values[i] == null) {
-                    throw new IllegalArgumentException("The String at " + i + " is null.");
-                } else if (values[i].length() > MAX_STRING_LENGTH) {
-                    throw new IllegalArgumentException(
-                            "The String at "
-                                    + i
-                                    + " length is: "
-                                    + values[i].length()
-                                    + ", which exceeds length limit: "
-                                    + MAX_STRING_LENGTH
-                                    + ".");
-                }
-            }
-            mProperties.putStringArray(key, values);
-        }
-
-        private void putInPropertyBundle(@NonNull String key, @NonNull boolean[] values) {
-            validateRepeatedPropertyLength(key, values.length);
-            mProperties.putBooleanArray(key, values);
-        }
-
-        private void putInPropertyBundle(@NonNull String key, @NonNull double[] values) {
-            validateRepeatedPropertyLength(key, values.length);
-            mProperties.putDoubleArray(key, values);
-        }
-
-        private void putInPropertyBundle(@NonNull String key, @NonNull long[] values) {
-            validateRepeatedPropertyLength(key, values.length);
-            mProperties.putLongArray(key, values);
-        }
-
-        /**
-         * Converts and saves a byte[][] into {@link #mProperties}.
-         *
-         * <p>Bundle doesn't support for two dimension array byte[][], we are converting byte[][]
-         * into ArrayList<Bundle>, and each elements will contain a one dimension byte[].
-         */
-        private void putInPropertyBundle(@NonNull String key, @NonNull byte[][] values) {
-            validateRepeatedPropertyLength(key, values.length);
-            ArrayList<Bundle> bundles = new ArrayList<>(values.length);
-            for (int i = 0; i < values.length; i++) {
-                if (values[i] == null) {
-                    throw new IllegalArgumentException("The byte[] at " + i + " is null.");
-                }
-                Bundle bundle = new Bundle();
-                bundle.putByteArray(BYTE_ARRAY_FIELD, values[i]);
-                bundles.add(bundle);
-            }
-            mProperties.putParcelableArrayList(key, bundles);
-        }
-
-        private void putInPropertyBundle(@NonNull String key, @NonNull GenericDocument[] values) {
-            validateRepeatedPropertyLength(key, values.length);
-            Bundle[] documentBundles = new Bundle[values.length];
-            for (int i = 0; i < values.length; i++) {
-                if (values[i] == null) {
-                    throw new IllegalArgumentException("The document at " + i + " is null.");
-                }
-                documentBundles[i] = values[i].mBundle;
-            }
-            mProperties.putParcelableArray(key, documentBundles);
-        }
-
-        private static void validateRepeatedPropertyLength(@NonNull String key, int length) {
-            if (length == 0) {
-                throw new IllegalArgumentException("The input array is empty.");
-            } else if (length > MAX_REPEATED_PROPERTY_LENGTH) {
-                throw new IllegalArgumentException(
-                        "Repeated property \""
-                                + key
-                                + "\" has length "
-                                + length
-                                + ", which exceeds the limit of "
-                                + MAX_REPEATED_PROPERTY_LENGTH);
-            }
-        }
-
-        /** Builds the {@link GenericDocument} object. */
-        @NonNull
-        public GenericDocument build() {
-            Preconditions.checkState(!mBuilt, "Builder has already been used");
-            mBuilt = true;
-            return new GenericDocument(mBundle);
-        }
-    }
-}
diff --git a/apex/appsearch/framework/java/android/app/appsearch/GetByUriRequest.java b/apex/appsearch/framework/java/android/app/appsearch/GetByUriRequest.java
deleted file mode 100644
index b1cf504..0000000
--- a/apex/appsearch/framework/java/android/app/appsearch/GetByUriRequest.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * 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.
- */
-
-package android.app.appsearch;
-
-import android.annotation.NonNull;
-import android.util.ArraySet;
-
-import com.android.internal.util.Preconditions;
-
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Set;
-
-/**
- * Encapsulates a request to retrieve documents by namespace and URI.
- *
- * @see AppSearchManager#getByUri
- */
-public final class GetByUriRequest {
-    private final String mNamespace;
-    private final Set<String> mUris;
-
-    GetByUriRequest(@NonNull String namespace, @NonNull Set<String> uris) {
-        mNamespace = namespace;
-        mUris = uris;
-    }
-
-    /** Returns the namespace to get documents from. */
-    @NonNull
-    public String getNamespace() {
-        return mNamespace;
-    }
-
-    /** Returns the URIs to get from the namespace. */
-    @NonNull
-    public Set<String> getUris() {
-        return Collections.unmodifiableSet(mUris);
-    }
-
-    /** Builder for {@link GetByUriRequest} objects. */
-    public static final class Builder {
-        private String mNamespace = GenericDocument.DEFAULT_NAMESPACE;
-        private final Set<String> mUris = new ArraySet<>();
-        private boolean mBuilt = false;
-
-        /**
-         * Sets which namespace these documents will be retrieved from.
-         *
-         * <p>If this is not set, it defaults to {@link GenericDocument#DEFAULT_NAMESPACE}.
-         */
-        @NonNull
-        public Builder setNamespace(@NonNull String namespace) {
-            Preconditions.checkState(!mBuilt, "Builder has already been used");
-            Preconditions.checkNotNull(namespace);
-            mNamespace = namespace;
-            return this;
-        }
-
-        /** Adds one or more URIs to the request. */
-        @NonNull
-        public Builder addUri(@NonNull String... uris) {
-            Preconditions.checkNotNull(uris);
-            return addUri(Arrays.asList(uris));
-        }
-
-        /** Adds one or more URIs to the request. */
-        @NonNull
-        public Builder addUri(@NonNull Collection<String> uris) {
-            Preconditions.checkState(!mBuilt, "Builder has already been used");
-            Preconditions.checkNotNull(uris);
-            mUris.addAll(uris);
-            return this;
-        }
-
-        /** Builds a new {@link GetByUriRequest}. */
-        @NonNull
-        public GetByUriRequest build() {
-            Preconditions.checkState(!mBuilt, "Builder has already been used");
-            mBuilt = true;
-            return new GetByUriRequest(mNamespace, mUris);
-        }
-    }
-}
diff --git a/apex/appsearch/framework/java/android/app/appsearch/IAppSearchManager.aidl b/apex/appsearch/framework/java/android/app/appsearch/IAppSearchManager.aidl
index 22e00f2..1d7cb87 100644
--- a/apex/appsearch/framework/java/android/app/appsearch/IAppSearchManager.aidl
+++ b/apex/appsearch/framework/java/android/app/appsearch/IAppSearchManager.aidl
@@ -32,6 +32,8 @@
      *
      * @param databaseName  The databaseName this document resides in.
      * @param schemaBundles List of AppSearchSchema bundles.
+     * @param schemasNotPlatformSurfaceable Schema types that should not be surfaced on platform
+     *     surfaces.
      * @param forceOverride Whether to apply the new schema even if it is incompatible. All
      *     incompatible documents will be deleted.
      * @param callback {@link IAppSearchResultCallback#onResult} will be called with an
@@ -40,6 +42,7 @@
     void setSchema(
         in String databaseName,
         in List<Bundle> schemaBundles,
+        in List<String> schemasNotPlatformSurfaceable,
         boolean forceOverride,
         in IAppSearchResultCallback callback);
 
diff --git a/apex/appsearch/framework/java/android/app/appsearch/PutDocumentsRequest.java b/apex/appsearch/framework/java/android/app/appsearch/PutDocumentsRequest.java
deleted file mode 100644
index 1e37277b..0000000
--- a/apex/appsearch/framework/java/android/app/appsearch/PutDocumentsRequest.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * 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.
- */
-
-package android.app.appsearch;
-
-import android.annotation.NonNull;
-import android.annotation.SuppressLint;
-import android.app.appsearch.exceptions.AppSearchException;
-
-import com.android.internal.util.Preconditions;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-
-/**
- * Encapsulates a request to index a document into an {@link AppSearchManager} database.
- *
- * @see AppSearchManager#putDocuments
- */
-public final class PutDocumentsRequest {
-    private final List<GenericDocument> mDocuments;
-
-    PutDocumentsRequest(List<GenericDocument> documents) {
-        mDocuments = documents;
-    }
-
-    /** Returns the documents that are part of this request. */
-    @NonNull
-    public List<GenericDocument> getDocuments() {
-        return Collections.unmodifiableList(mDocuments);
-    }
-
-    /** Builder for {@link PutDocumentsRequest} objects. */
-    public static final class Builder {
-        private final List<GenericDocument> mDocuments = new ArrayList<>();
-        private boolean mBuilt = false;
-
-        /** Adds one or more documents to the request. */
-        @SuppressLint("MissingGetterMatchingBuilder") // Merged list available from getDocuments()
-        @NonNull
-        public Builder addGenericDocument(@NonNull GenericDocument... documents) {
-            Preconditions.checkNotNull(documents);
-            return addGenericDocument(Arrays.asList(documents));
-        }
-
-        /** Adds one or more documents to the request. */
-        @SuppressLint("MissingGetterMatchingBuilder") // Merged list available from getDocuments()
-        @NonNull
-        public Builder addGenericDocument(@NonNull Collection<GenericDocument> documents) {
-            Preconditions.checkState(!mBuilt, "Builder has already been used");
-            Preconditions.checkNotNull(documents);
-            mDocuments.addAll(documents);
-            return this;
-        }
-
-        /** Builds a new {@link PutDocumentsRequest}. */
-        @NonNull
-        public PutDocumentsRequest build() {
-            Preconditions.checkState(!mBuilt, "Builder has already been used");
-            mBuilt = true;
-            return new PutDocumentsRequest(mDocuments);
-        }
-    }
-}
diff --git a/apex/appsearch/framework/java/android/app/appsearch/RemoveByUriRequest.java b/apex/appsearch/framework/java/android/app/appsearch/RemoveByUriRequest.java
deleted file mode 100644
index 1c17547..0000000
--- a/apex/appsearch/framework/java/android/app/appsearch/RemoveByUriRequest.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * 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.
- */
-
-package android.app.appsearch;
-
-import android.annotation.NonNull;
-import android.util.ArraySet;
-
-import com.android.internal.util.Preconditions;
-
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Set;
-
-/**
- * Encapsulates a request to remove documents by namespace and URI.
- *
- * @see AppSearchManager#removeByUri
- */
-public final class RemoveByUriRequest {
-    private final String mNamespace;
-    private final Set<String> mUris;
-
-    RemoveByUriRequest(String namespace, Set<String> uris) {
-        mNamespace = namespace;
-        mUris = uris;
-    }
-
-    /** Returns the namespace to remove documents from. */
-    @NonNull
-    public String getNamespace() {
-        return mNamespace;
-    }
-
-    /** Returns the URIs to remove from the namespace. */
-    @NonNull
-    public Set<String> getUris() {
-        return Collections.unmodifiableSet(mUris);
-    }
-
-    /** Builder for {@link RemoveByUriRequest} objects. */
-    public static final class Builder {
-        private String mNamespace = GenericDocument.DEFAULT_NAMESPACE;
-        private final Set<String> mUris = new ArraySet<>();
-        private boolean mBuilt = false;
-
-        /**
-         * Sets which namespace these documents will be removed from.
-         *
-         * <p>If this is not set, it defaults to {@link GenericDocument#DEFAULT_NAMESPACE}.
-         */
-        @NonNull
-        public Builder setNamespace(@NonNull String namespace) {
-            Preconditions.checkState(!mBuilt, "Builder has already been used");
-            Preconditions.checkNotNull(namespace);
-            mNamespace = namespace;
-            return this;
-        }
-
-        /** Adds one or more URIs to the request. */
-        @NonNull
-        public Builder addUri(@NonNull String... uris) {
-            Preconditions.checkNotNull(uris);
-            return addUri(Arrays.asList(uris));
-        }
-
-        /** Adds one or more URIs to the request. */
-        @NonNull
-        public Builder addUri(@NonNull Collection<String> uris) {
-            Preconditions.checkState(!mBuilt, "Builder has already been used");
-            Preconditions.checkNotNull(uris);
-            mUris.addAll(uris);
-            return this;
-        }
-
-        /** Builds a new {@link RemoveByUriRequest}. */
-        @NonNull
-        public RemoveByUriRequest build() {
-            Preconditions.checkState(!mBuilt, "Builder has already been used");
-            mBuilt = true;
-            return new RemoveByUriRequest(mNamespace, mUris);
-        }
-    }
-}
diff --git a/apex/appsearch/framework/java/android/app/appsearch/SetSchemaRequest.java b/apex/appsearch/framework/java/android/app/appsearch/SetSchemaRequest.java
deleted file mode 100644
index 081fb72..0000000
--- a/apex/appsearch/framework/java/android/app/appsearch/SetSchemaRequest.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * 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.
- */
-
-package android.app.appsearch;
-
-import android.annotation.NonNull;
-import android.annotation.SuppressLint;
-import android.app.appsearch.exceptions.AppSearchException;
-import android.util.ArraySet;
-
-import com.android.internal.util.Preconditions;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.List;
-import java.util.Set;
-
-/**
- * Encapsulates a request to update the schema of an {@link AppSearchManager} database.
- *
- * @see AppSearchManager#setSchema
- */
-public final class SetSchemaRequest {
-    private final Set<AppSearchSchema> mSchemas;
-    private final boolean mForceOverride;
-
-    SetSchemaRequest(Set<AppSearchSchema> schemas, boolean forceOverride) {
-        mSchemas = schemas;
-        mForceOverride = forceOverride;
-    }
-
-    /** Returns the schemas that are part of this request. */
-    @NonNull
-    public Set<AppSearchSchema> getSchemas() {
-        return mSchemas;
-    }
-
-    /** Returns whether this request will force the schema to be overridden. */
-    public boolean isForceOverride() {
-        return mForceOverride;
-    }
-
-    /** Builder for {@link SetSchemaRequest} objects. */
-    public static final class Builder {
-        private final Set<AppSearchSchema> mSchemas = new ArraySet<>();
-        private boolean mForceOverride = false;
-        private boolean mBuilt = false;
-
-        /** Adds one or more types to the schema. */
-        @NonNull
-        public Builder addSchema(@NonNull AppSearchSchema... schemas) {
-            Preconditions.checkNotNull(schemas);
-            return addSchema(Arrays.asList(schemas));
-        }
-
-        /** Adds one or more types to the schema. */
-        @NonNull
-        public Builder addSchema(@NonNull Collection<AppSearchSchema> schemas) {
-            Preconditions.checkState(!mBuilt, "Builder has already been used");
-            Preconditions.checkNotNull(schemas);
-            mSchemas.addAll(schemas);
-            return this;
-        }
-
-        /**
-         * Configures the {@link SetSchemaRequest} to delete any existing documents that don't
-         * follow the new schema.
-         *
-         * <p>By default, this is {@code false} and schema incompatibility causes the {@link
-         * AppSearchManager#setSchema} call to fail.
-         *
-         * @see AppSearchManager#setSchema
-         */
-        @NonNull
-        public Builder setForceOverride(boolean forceOverride) {
-            mForceOverride = forceOverride;
-            return this;
-        }
-
-        /** Builds a new {@link SetSchemaRequest}. */
-        @NonNull
-        public SetSchemaRequest build() {
-            Preconditions.checkState(!mBuilt, "Builder has already been used");
-            mBuilt = true;
-            return new SetSchemaRequest(mSchemas, mForceOverride);
-        }
-    }
-}
diff --git a/apex/appsearch/framework/java/android/app/appsearch/AppSearchEmail.java b/apex/appsearch/framework/java/external/android/app/appsearch/AppSearchEmail.java
similarity index 100%
rename from apex/appsearch/framework/java/android/app/appsearch/AppSearchEmail.java
rename to apex/appsearch/framework/java/external/android/app/appsearch/AppSearchEmail.java
diff --git a/apex/appsearch/framework/java/external/android/app/appsearch/AppSearchSchema.java b/apex/appsearch/framework/java/external/android/app/appsearch/AppSearchSchema.java
new file mode 100644
index 0000000..62cf38b
--- /dev/null
+++ b/apex/appsearch/framework/java/external/android/app/appsearch/AppSearchSchema.java
@@ -0,0 +1,491 @@
+/*
+ * 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.
+ */
+
+package android.app.appsearch;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SuppressLint;
+import android.app.appsearch.exceptions.IllegalSchemaException;
+import android.app.appsearch.util.BundleUtil;
+import android.os.Bundle;
+import android.util.ArraySet;
+
+import com.android.internal.util.Preconditions;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+
+/**
+ * The AppSearch Schema for a particular type of document.
+ *
+ * <p>For example, an e-mail message or a music recording could be a schema type.
+ *
+ * <p>The schema consists of type information, properties, and config (like tokenization type).
+ *
+ * @see AppSearchSession#setSchema
+ */
+public final class AppSearchSchema {
+    private static final String SCHEMA_TYPE_FIELD = "schemaType";
+    private static final String PROPERTIES_FIELD = "properties";
+
+    private final Bundle mBundle;
+
+    /** @hide */
+    public AppSearchSchema(@NonNull Bundle bundle) {
+        Preconditions.checkNotNull(bundle);
+        mBundle = bundle;
+    }
+
+    /**
+     * Returns the {@link Bundle} populated by this builder.
+     *
+     * @hide
+     */
+    @NonNull
+    public Bundle getBundle() {
+        return mBundle;
+    }
+
+    @Override
+    public String toString() {
+        return mBundle.toString();
+    }
+
+    /** Returns the name of this schema type, e.g. Email. */
+    @NonNull
+    public String getSchemaType() {
+        return mBundle.getString(SCHEMA_TYPE_FIELD, "");
+    }
+
+    /**
+     * Returns the list of {@link PropertyConfig}s that are part of this schema.
+     *
+     * <p>This method creates a new list when called.
+     */
+    @NonNull
+    public List<PropertyConfig> getProperties() {
+        ArrayList<Bundle> propertyBundles =
+                mBundle.getParcelableArrayList(AppSearchSchema.PROPERTIES_FIELD);
+        if (propertyBundles.isEmpty()) {
+            return Collections.emptyList();
+        }
+        List<PropertyConfig> ret = new ArrayList<>(propertyBundles.size());
+        for (int i = 0; i < propertyBundles.size(); i++) {
+            ret.add(new PropertyConfig(propertyBundles.get(i)));
+        }
+        return ret;
+    }
+
+    @Override
+    public boolean equals(@Nullable Object other) {
+        if (this == other) {
+            return true;
+        }
+        if (!(other instanceof AppSearchSchema)) {
+            return false;
+        }
+        AppSearchSchema otherSchema = (AppSearchSchema) other;
+        if (!getSchemaType().equals(otherSchema.getSchemaType())) {
+            return false;
+        }
+        return getProperties().equals(otherSchema.getProperties());
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(getSchemaType(), getProperties());
+    }
+
+    /** Builder for {@link AppSearchSchema objects}. */
+    public static final class Builder {
+        private final String mSchemaType;
+        private final ArrayList<Bundle> mPropertyBundles = new ArrayList<>();
+        private final Set<String> mPropertyNames = new ArraySet<>();
+        private boolean mBuilt = false;
+
+        /** Creates a new {@link AppSearchSchema.Builder}. */
+        public Builder(@NonNull String schemaType) {
+            Preconditions.checkNotNull(schemaType);
+            mSchemaType = schemaType;
+        }
+
+        /** Adds a property to the given type. */
+        // TODO(b/171360120): MissingGetterMatchingBuilder expects a method called getPropertys, but
+        //  we provide the (correct) method getProperties. Once the bug referenced in this TODO is
+        //  fixed, remove this SuppressLint.
+        @SuppressLint("MissingGetterMatchingBuilder")
+        @NonNull
+        public AppSearchSchema.Builder addProperty(@NonNull PropertyConfig propertyConfig) {
+            Preconditions.checkState(!mBuilt, "Builder has already been used");
+            Preconditions.checkNotNull(propertyConfig);
+            String name = propertyConfig.getName();
+            if (!mPropertyNames.add(name)) {
+                throw new IllegalSchemaException("Property defined more than once: " + name);
+            }
+            mPropertyBundles.add(propertyConfig.mBundle);
+            return this;
+        }
+
+        /**
+         * Constructs a new {@link AppSearchSchema} from the contents of this builder.
+         *
+         * <p>After calling this method, the builder must no longer be used.
+         */
+        @NonNull
+        public AppSearchSchema build() {
+            Preconditions.checkState(!mBuilt, "Builder has already been used");
+            Bundle bundle = new Bundle();
+            bundle.putString(AppSearchSchema.SCHEMA_TYPE_FIELD, mSchemaType);
+            bundle.putParcelableArrayList(AppSearchSchema.PROPERTIES_FIELD, mPropertyBundles);
+            mBuilt = true;
+            return new AppSearchSchema(bundle);
+        }
+    }
+
+    /**
+     * Configuration for a single property (field) of a document type.
+     *
+     * <p>For example, an {@code EmailMessage} would be a type and the {@code subject} would be a
+     * property.
+     */
+    public static final class PropertyConfig {
+        private static final String NAME_FIELD = "name";
+        private static final String DATA_TYPE_FIELD = "dataType";
+        private static final String SCHEMA_TYPE_FIELD = "schemaType";
+        private static final String CARDINALITY_FIELD = "cardinality";
+        private static final String INDEXING_TYPE_FIELD = "indexingType";
+        private static final String TOKENIZER_TYPE_FIELD = "tokenizerType";
+
+        /**
+         * Physical data-types of the contents of the property.
+         *
+         * @hide
+         */
+        // NOTE: The integer values of these constants must match the proto enum constants in
+        // com.google.android.icing.proto.PropertyConfigProto.DataType.Code.
+        @IntDef(
+                value = {
+                    DATA_TYPE_STRING,
+                    DATA_TYPE_INT64,
+                    DATA_TYPE_DOUBLE,
+                    DATA_TYPE_BOOLEAN,
+                    DATA_TYPE_BYTES,
+                    DATA_TYPE_DOCUMENT,
+                })
+        @Retention(RetentionPolicy.SOURCE)
+        public @interface DataType {}
+
+        public static final int DATA_TYPE_STRING = 1;
+        public static final int DATA_TYPE_INT64 = 2;
+        public static final int DATA_TYPE_DOUBLE = 3;
+        public static final int DATA_TYPE_BOOLEAN = 4;
+
+        /** Unstructured BLOB. */
+        public static final int DATA_TYPE_BYTES = 5;
+
+        /**
+         * Indicates that the property is itself a {@link GenericDocument}, making it part of a
+         * hierarchical schema. Any property using this DataType MUST have a valid {@link
+         * PropertyConfig#getSchemaType}.
+         */
+        public static final int DATA_TYPE_DOCUMENT = 6;
+
+        /**
+         * The cardinality of the property (whether it is required, optional or repeated).
+         *
+         * @hide
+         */
+        // NOTE: The integer values of these constants must match the proto enum constants in
+        // com.google.android.icing.proto.PropertyConfigProto.Cardinality.Code.
+        @IntDef(
+                value = {
+                    CARDINALITY_REPEATED,
+                    CARDINALITY_OPTIONAL,
+                    CARDINALITY_REQUIRED,
+                })
+        @Retention(RetentionPolicy.SOURCE)
+        public @interface Cardinality {}
+
+        /** Any number of items (including zero) [0...*]. */
+        public static final int CARDINALITY_REPEATED = 1;
+
+        /** Zero or one value [0,1]. */
+        public static final int CARDINALITY_OPTIONAL = 2;
+
+        /** Exactly one value [1]. */
+        public static final int CARDINALITY_REQUIRED = 3;
+
+        /**
+         * Encapsulates the configurations on how AppSearch should query/index these terms.
+         *
+         * @hide
+         */
+        @IntDef(
+                value = {
+                    INDEXING_TYPE_NONE,
+                    INDEXING_TYPE_EXACT_TERMS,
+                    INDEXING_TYPE_PREFIXES,
+                })
+        @Retention(RetentionPolicy.SOURCE)
+        public @interface IndexingType {}
+
+        /**
+         * Content in this property will not be tokenized or indexed.
+         *
+         * <p>Useful if the data type is not made up of terms (e.g. {@link
+         * PropertyConfig#DATA_TYPE_DOCUMENT} or {@link PropertyConfig#DATA_TYPE_BYTES} type). None
+         * of the properties inside the nested property will be indexed regardless of the value of
+         * {@code indexingType} for the nested properties.
+         */
+        public static final int INDEXING_TYPE_NONE = 0;
+
+        /**
+         * Content in this property should only be returned for queries matching the exact tokens
+         * appearing in this property.
+         *
+         * <p>Ex. A property with "fool" should NOT match a query for "foo".
+         */
+        public static final int INDEXING_TYPE_EXACT_TERMS = 1;
+
+        /**
+         * Content in this property should be returned for queries that are either exact matches or
+         * query matches of the tokens appearing in this property.
+         *
+         * <p>Ex. A property with "fool" <b>should</b> match a query for "foo".
+         */
+        public static final int INDEXING_TYPE_PREFIXES = 2;
+
+        /**
+         * Configures how tokens should be extracted from this property.
+         *
+         * @hide
+         */
+        // NOTE: The integer values of these constants must match the proto enum constants in
+        // com.google.android.icing.proto.IndexingConfig.TokenizerType.Code.
+        @IntDef(
+                value = {
+                    TOKENIZER_TYPE_NONE,
+                    TOKENIZER_TYPE_PLAIN,
+                })
+        @Retention(RetentionPolicy.SOURCE)
+        public @interface TokenizerType {}
+
+        /**
+         * It is only valid for tokenizer_type to be 'NONE' if the data type is {@link
+         * PropertyConfig#DATA_TYPE_DOCUMENT}.
+         */
+        public static final int TOKENIZER_TYPE_NONE = 0;
+
+        /** Tokenization for plain text. */
+        public static final int TOKENIZER_TYPE_PLAIN = 1;
+
+        final Bundle mBundle;
+
+        @Nullable private Integer mHashCode;
+
+        PropertyConfig(@NonNull Bundle bundle) {
+            mBundle = Preconditions.checkNotNull(bundle);
+        }
+
+        @Override
+        public String toString() {
+            return mBundle.toString();
+        }
+
+        /** Returns the name of this property. */
+        @NonNull
+        public String getName() {
+            return mBundle.getString(NAME_FIELD, "");
+        }
+
+        /** Returns the type of data the property contains (e.g. string, int, bytes, etc). */
+        public @DataType int getDataType() {
+            return mBundle.getInt(DATA_TYPE_FIELD, -1);
+        }
+
+        /**
+         * Returns the logical schema-type of the contents of this property.
+         *
+         * <p>Only set when {@link #getDataType} is set to {@link #DATA_TYPE_DOCUMENT}. Otherwise,
+         * it is {@code null}.
+         */
+        @Nullable
+        public String getSchemaType() {
+            return mBundle.getString(SCHEMA_TYPE_FIELD);
+        }
+
+        /**
+         * Returns the cardinality of the property (whether it is optional, required or repeated).
+         */
+        public @Cardinality int getCardinality() {
+            return mBundle.getInt(CARDINALITY_FIELD, -1);
+        }
+
+        /** Returns how the property is indexed. */
+        public @IndexingType int getIndexingType() {
+            return mBundle.getInt(INDEXING_TYPE_FIELD);
+        }
+
+        /** Returns how this property is tokenized (split into words). */
+        public @TokenizerType int getTokenizerType() {
+            return mBundle.getInt(TOKENIZER_TYPE_FIELD);
+        }
+
+        @Override
+        public boolean equals(@Nullable Object other) {
+            if (this == other) {
+                return true;
+            }
+            if (!(other instanceof PropertyConfig)) {
+                return false;
+            }
+            PropertyConfig otherProperty = (PropertyConfig) other;
+            return BundleUtil.deepEquals(this.mBundle, otherProperty.mBundle);
+        }
+
+        @Override
+        public int hashCode() {
+            if (mHashCode == null) {
+                mHashCode = BundleUtil.deepHashCode(mBundle);
+            }
+            return mHashCode;
+        }
+
+        /**
+         * Builder for {@link PropertyConfig}.
+         *
+         * <p>The following properties must be set, or {@link PropertyConfig} construction will
+         * fail:
+         *
+         * <ul>
+         *   <li>dataType
+         *   <li>cardinality
+         * </ul>
+         *
+         * <p>In addition, if {@code schemaType} is {@link #DATA_TYPE_DOCUMENT}, {@code schemaType}
+         * is also required.
+         */
+        public static final class Builder {
+            private final Bundle mBundle = new Bundle();
+            private boolean mBuilt = false;
+
+            /** Creates a new {@link PropertyConfig.Builder}. */
+            public Builder(@NonNull String propertyName) {
+                mBundle.putString(NAME_FIELD, propertyName);
+            }
+
+            /**
+             * Type of data the property contains (e.g. string, int, bytes, etc).
+             *
+             * <p>This property must be set.
+             */
+            @NonNull
+            public PropertyConfig.Builder setDataType(@DataType int dataType) {
+                Preconditions.checkState(!mBuilt, "Builder has already been used");
+                Preconditions.checkArgumentInRange(
+                        dataType, DATA_TYPE_STRING, DATA_TYPE_DOCUMENT, "dataType");
+                mBundle.putInt(DATA_TYPE_FIELD, dataType);
+                return this;
+            }
+
+            /**
+             * The logical schema-type of the contents of this property.
+             *
+             * <p>Only required when {@link #setDataType} is set to {@link #DATA_TYPE_DOCUMENT}.
+             * Otherwise, it is ignored.
+             */
+            @NonNull
+            public PropertyConfig.Builder setSchemaType(@NonNull String schemaType) {
+                Preconditions.checkState(!mBuilt, "Builder has already been used");
+                Preconditions.checkNotNull(schemaType);
+                mBundle.putString(SCHEMA_TYPE_FIELD, schemaType);
+                return this;
+            }
+
+            /**
+             * The cardinality of the property (whether it is optional, required or repeated).
+             *
+             * <p>This property must be set.
+             */
+            @NonNull
+            public PropertyConfig.Builder setCardinality(@Cardinality int cardinality) {
+                Preconditions.checkState(!mBuilt, "Builder has already been used");
+                Preconditions.checkArgumentInRange(
+                        cardinality, CARDINALITY_REPEATED, CARDINALITY_REQUIRED, "cardinality");
+                mBundle.putInt(CARDINALITY_FIELD, cardinality);
+                return this;
+            }
+
+            /**
+             * Configures how a property should be indexed so that it can be retrieved by queries.
+             */
+            @NonNull
+            public PropertyConfig.Builder setIndexingType(@IndexingType int indexingType) {
+                Preconditions.checkState(!mBuilt, "Builder has already been used");
+                Preconditions.checkArgumentInRange(
+                        indexingType, INDEXING_TYPE_NONE, INDEXING_TYPE_PREFIXES, "indexingType");
+                mBundle.putInt(INDEXING_TYPE_FIELD, indexingType);
+                return this;
+            }
+
+            /** Configures how this property should be tokenized (split into words). */
+            @NonNull
+            public PropertyConfig.Builder setTokenizerType(@TokenizerType int tokenizerType) {
+                Preconditions.checkState(!mBuilt, "Builder has already been used");
+                Preconditions.checkArgumentInRange(
+                        tokenizerType, TOKENIZER_TYPE_NONE, TOKENIZER_TYPE_PLAIN, "tokenizerType");
+                mBundle.putInt(TOKENIZER_TYPE_FIELD, tokenizerType);
+                return this;
+            }
+
+            /**
+             * Constructs a new {@link PropertyConfig} from the contents of this builder.
+             *
+             * <p>After calling this method, the builder must no longer be used.
+             *
+             * @throws IllegalSchemaException If the property is not correctly populated (e.g.
+             *     missing {@code dataType}).
+             */
+            @NonNull
+            public PropertyConfig build() {
+                Preconditions.checkState(!mBuilt, "Builder has already been used");
+                // TODO(b/147692920): Send the schema to Icing Lib for official validation, instead
+                //     of partially reimplementing some of the validation Icing does here.
+                if (!mBundle.containsKey(DATA_TYPE_FIELD)) {
+                    throw new IllegalSchemaException("Missing field: dataType");
+                }
+                if (mBundle.getString(SCHEMA_TYPE_FIELD, "").isEmpty()
+                        && mBundle.getInt(DATA_TYPE_FIELD) == DATA_TYPE_DOCUMENT) {
+                    throw new IllegalSchemaException(
+                            "Missing field: schemaType (required for configs with "
+                                    + "dataType = DOCUMENT)");
+                }
+                if (!mBundle.containsKey(CARDINALITY_FIELD)) {
+                    throw new IllegalSchemaException("Missing field: cardinality");
+                }
+                mBuilt = true;
+                return new PropertyConfig(mBundle);
+            }
+        }
+    }
+}
diff --git a/apex/appsearch/framework/java/external/android/app/appsearch/GenericDocument.java b/apex/appsearch/framework/java/external/android/app/appsearch/GenericDocument.java
new file mode 100644
index 0000000..85207f7
--- /dev/null
+++ b/apex/appsearch/framework/java/external/android/app/appsearch/GenericDocument.java
@@ -0,0 +1,837 @@
+/*
+ * 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.
+ */
+
+package android.app.appsearch;
+
+import android.annotation.IntRange;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SuppressLint;
+import android.app.appsearch.exceptions.AppSearchException;
+import android.app.appsearch.util.BundleUtil;
+import android.os.Bundle;
+import android.util.Log;
+
+import com.android.internal.util.Preconditions;
+
+import java.lang.reflect.Array;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Set;
+
+/**
+ * Represents a document unit.
+ *
+ * <p>Documents are constructed via {@link GenericDocument.Builder}.
+ *
+ * @see AppSearchSession#putDocuments
+ * @see AppSearchSession#getByUri
+ * @see AppSearchSession#query
+ */
+public class GenericDocument {
+    private static final String TAG = "AppSearchGenericDocumen";
+
+    /** The default empty namespace. */
+    public static final String DEFAULT_NAMESPACE = "";
+
+    /**
+     * The maximum number of elements in a repeatable field. Will reject the request if exceed this
+     * limit.
+     */
+    private static final int MAX_REPEATED_PROPERTY_LENGTH = 100;
+
+    /**
+     * The maximum {@link String#length} of a {@link String} field. Will reject the request if
+     * {@link String}s longer than this.
+     */
+    private static final int MAX_STRING_LENGTH = 20_000;
+
+    /** The maximum number of indexed properties a document can have. */
+    private static final int MAX_INDEXED_PROPERTIES = 16;
+
+    /** The default score of document. */
+    private static final int DEFAULT_SCORE = 0;
+
+    /** The default time-to-live in millisecond of a document, which is infinity. */
+    private static final long DEFAULT_TTL_MILLIS = 0L;
+
+    private static final String PROPERTIES_FIELD = "properties";
+    private static final String BYTE_ARRAY_FIELD = "byteArray";
+    private static final String SCHEMA_TYPE_FIELD = "schemaType";
+    private static final String URI_FIELD = "uri";
+    private static final String SCORE_FIELD = "score";
+    private static final String TTL_MILLIS_FIELD = "ttlMillis";
+    private static final String CREATION_TIMESTAMP_MILLIS_FIELD = "creationTimestampMillis";
+    private static final String NAMESPACE_FIELD = "namespace";
+
+    /**
+     * The maximum number of indexed properties a document can have.
+     *
+     * <p>Indexed properties are properties where the {@link
+     * AppSearchSchema.PropertyConfig#getIndexingType()} constant is anything other than {@link
+     * AppSearchSchema.PropertyConfig.IndexingType#INDEXING_TYPE_NONE}.
+     */
+    public static int getMaxIndexedProperties() {
+        return MAX_INDEXED_PROPERTIES;
+    }
+
+    /** Contains {@link GenericDocument} basic information (uri, schemaType etc). */
+    @NonNull final Bundle mBundle;
+
+    /**
+     * Contains all properties in {@link GenericDocument} to support getting properties via keys.
+     */
+    @NonNull private final Bundle mProperties;
+
+    @NonNull private final String mUri;
+    @NonNull private final String mSchemaType;
+    private final long mCreationTimestampMillis;
+    @Nullable private Integer mHashCode;
+
+    /**
+     * Rebuilds a {@link GenericDocument} by the a bundle.
+     *
+     * @param bundle Contains {@link GenericDocument} basic information (uri, schemaType etc) and a
+     *     properties bundle contains all properties in {@link GenericDocument} to support getting
+     *     properties via keys.
+     * @hide
+     */
+    public GenericDocument(@NonNull Bundle bundle) {
+        Preconditions.checkNotNull(bundle);
+        mBundle = bundle;
+        mProperties = Preconditions.checkNotNull(bundle.getParcelable(PROPERTIES_FIELD));
+        mUri = Preconditions.checkNotNull(mBundle.getString(URI_FIELD));
+        mSchemaType = Preconditions.checkNotNull(mBundle.getString(SCHEMA_TYPE_FIELD));
+        mCreationTimestampMillis =
+                mBundle.getLong(CREATION_TIMESTAMP_MILLIS_FIELD, System.currentTimeMillis());
+    }
+
+    /**
+     * Creates a new {@link GenericDocument} from an existing instance.
+     *
+     * <p>This method should be only used by constructor of a subclass.
+     */
+    protected GenericDocument(@NonNull GenericDocument document) {
+        this(document.mBundle);
+    }
+
+    /**
+     * Returns the {@link Bundle} populated by this builder.
+     *
+     * @hide
+     */
+    @NonNull
+    public Bundle getBundle() {
+        return mBundle;
+    }
+
+    /** Returns the URI of the {@link GenericDocument}. */
+    @NonNull
+    public String getUri() {
+        return mUri;
+    }
+
+    /** Returns the namespace of the {@link GenericDocument}. */
+    @NonNull
+    public String getNamespace() {
+        return mBundle.getString(NAMESPACE_FIELD, DEFAULT_NAMESPACE);
+    }
+
+    /** Returns the schema type of the {@link GenericDocument}. */
+    @NonNull
+    public String getSchemaType() {
+        return mSchemaType;
+    }
+
+    /**
+     * Returns the creation timestamp of the {@link GenericDocument}, in milliseconds.
+     *
+     * <p>The value is in the {@link System#currentTimeMillis} time base.
+     */
+    public long getCreationTimestampMillis() {
+        return mCreationTimestampMillis;
+    }
+
+    /**
+     * Returns the TTL (Time To Live) of the {@link GenericDocument}, in milliseconds.
+     *
+     * <p>The TTL is measured against {@link #getCreationTimestampMillis}. At the timestamp of
+     * {@code creationTimestampMillis + ttlMillis}, measured in the {@link System#currentTimeMillis}
+     * time base, the document will be auto-deleted.
+     *
+     * <p>The default value is 0, which means the document is permanent and won't be auto-deleted
+     * until the app is uninstalled.
+     */
+    public long getTtlMillis() {
+        return mBundle.getLong(TTL_MILLIS_FIELD, DEFAULT_TTL_MILLIS);
+    }
+
+    /**
+     * Returns the score of the {@link GenericDocument}.
+     *
+     * <p>The score is a query-independent measure of the document's quality, relative to other
+     * {@link GenericDocument}s of the same type.
+     *
+     * <p>Results may be sorted by score using {@link SearchSpec.Builder#setRankingStrategy}.
+     * Documents with higher scores are considered better than documents with lower scores.
+     *
+     * <p>Any nonnegative integer can be used a score.
+     */
+    public int getScore() {
+        return mBundle.getInt(SCORE_FIELD, DEFAULT_SCORE);
+    }
+
+    /** Returns the names of all properties defined in this document. */
+    @NonNull
+    public Set<String> getPropertyNames() {
+        return Collections.unmodifiableSet(mProperties.keySet());
+    }
+
+    /**
+     * Retrieves a {@link String} value by key.
+     *
+     * @param key The key to look for.
+     * @return The first {@link String} associated with the given key or {@code null} if there is no
+     *     such key or the value is of a different type.
+     */
+    @Nullable
+    public String getPropertyString(@NonNull String key) {
+        Preconditions.checkNotNull(key);
+        String[] propertyArray = getPropertyStringArray(key);
+        if (propertyArray == null || propertyArray.length == 0) {
+            return null;
+        }
+        warnIfSinglePropertyTooLong("String", key, propertyArray.length);
+        return propertyArray[0];
+    }
+
+    /**
+     * Retrieves a {@code long} value by key.
+     *
+     * @param key The key to look for.
+     * @return The first {@code long} associated with the given key or default value {@code 0} if
+     *     there is no such key or the value is of a different type.
+     */
+    public long getPropertyLong(@NonNull String key) {
+        Preconditions.checkNotNull(key);
+        long[] propertyArray = getPropertyLongArray(key);
+        if (propertyArray == null || propertyArray.length == 0) {
+            return 0;
+        }
+        warnIfSinglePropertyTooLong("Long", key, propertyArray.length);
+        return propertyArray[0];
+    }
+
+    /**
+     * Retrieves a {@code double} value by key.
+     *
+     * @param key The key to look for.
+     * @return The first {@code double} associated with the given key or default value {@code 0.0}
+     *     if there is no such key or the value is of a different type.
+     */
+    public double getPropertyDouble(@NonNull String key) {
+        Preconditions.checkNotNull(key);
+        double[] propertyArray = getPropertyDoubleArray(key);
+        if (propertyArray == null || propertyArray.length == 0) {
+            return 0.0;
+        }
+        warnIfSinglePropertyTooLong("Double", key, propertyArray.length);
+        return propertyArray[0];
+    }
+
+    /**
+     * Retrieves a {@code boolean} value by key.
+     *
+     * @param key The key to look for.
+     * @return The first {@code boolean} associated with the given key or default value {@code
+     *     false} if there is no such key or the value is of a different type.
+     */
+    public boolean getPropertyBoolean(@NonNull String key) {
+        Preconditions.checkNotNull(key);
+        boolean[] propertyArray = getPropertyBooleanArray(key);
+        if (propertyArray == null || propertyArray.length == 0) {
+            return false;
+        }
+        warnIfSinglePropertyTooLong("Boolean", key, propertyArray.length);
+        return propertyArray[0];
+    }
+
+    /**
+     * Retrieves a {@code byte[]} value by key.
+     *
+     * @param key The key to look for.
+     * @return The first {@code byte[]} associated with the given key or {@code null} if there is no
+     *     such key or the value is of a different type.
+     */
+    @Nullable
+    public byte[] getPropertyBytes(@NonNull String key) {
+        Preconditions.checkNotNull(key);
+        byte[][] propertyArray = getPropertyBytesArray(key);
+        if (propertyArray == null || propertyArray.length == 0) {
+            return null;
+        }
+        warnIfSinglePropertyTooLong("ByteArray", key, propertyArray.length);
+        return propertyArray[0];
+    }
+
+    /**
+     * Retrieves a {@link GenericDocument} value by key.
+     *
+     * @param key The key to look for.
+     * @return The first {@link GenericDocument} associated with the given key or {@code null} if
+     *     there is no such key or the value is of a different type.
+     */
+    @Nullable
+    public GenericDocument getPropertyDocument(@NonNull String key) {
+        Preconditions.checkNotNull(key);
+        GenericDocument[] propertyArray = getPropertyDocumentArray(key);
+        if (propertyArray == null || propertyArray.length == 0) {
+            return null;
+        }
+        warnIfSinglePropertyTooLong("Document", key, propertyArray.length);
+        return propertyArray[0];
+    }
+
+    /** Prints a warning to logcat if the given propertyLength is greater than 1. */
+    private static void warnIfSinglePropertyTooLong(
+            @NonNull String propertyType, @NonNull String key, int propertyLength) {
+        if (propertyLength > 1) {
+            Log.w(
+                    TAG,
+                    "The value for \""
+                            + key
+                            + "\" contains "
+                            + propertyLength
+                            + " elements. Only the first one will be returned from "
+                            + "getProperty"
+                            + propertyType
+                            + "(). Try getProperty"
+                            + propertyType
+                            + "Array().");
+        }
+    }
+
+    /**
+     * Retrieves a repeated {@code String} property by key.
+     *
+     * @param key The key to look for.
+     * @return The {@code String[]} associated with the given key, or {@code null} if no value is
+     *     set or the value is of a different type.
+     */
+    @Nullable
+    public String[] getPropertyStringArray(@NonNull String key) {
+        Preconditions.checkNotNull(key);
+        return getAndCastPropertyArray(key, String[].class);
+    }
+
+    /**
+     * Retrieves a repeated {@link String} property by key.
+     *
+     * @param key The key to look for.
+     * @return The {@code long[]} associated with the given key, or {@code null} if no value is set
+     *     or the value is of a different type.
+     */
+    @Nullable
+    public long[] getPropertyLongArray(@NonNull String key) {
+        Preconditions.checkNotNull(key);
+        return getAndCastPropertyArray(key, long[].class);
+    }
+
+    /**
+     * Retrieves a repeated {@code double} property by key.
+     *
+     * @param key The key to look for.
+     * @return The {@code double[]} associated with the given key, or {@code null} if no value is
+     *     set or the value is of a different type.
+     */
+    @Nullable
+    public double[] getPropertyDoubleArray(@NonNull String key) {
+        Preconditions.checkNotNull(key);
+        return getAndCastPropertyArray(key, double[].class);
+    }
+
+    /**
+     * Retrieves a repeated {@code boolean} property by key.
+     *
+     * @param key The key to look for.
+     * @return The {@code boolean[]} associated with the given key, or {@code null} if no value is
+     *     set or the value is of a different type.
+     */
+    @Nullable
+    public boolean[] getPropertyBooleanArray(@NonNull String key) {
+        Preconditions.checkNotNull(key);
+        return getAndCastPropertyArray(key, boolean[].class);
+    }
+
+    /**
+     * Retrieves a {@code byte[][]} property by key.
+     *
+     * @param key The key to look for.
+     * @return The {@code byte[][]} associated with the given key, or {@code null} if no value is
+     *     set or the value is of a different type.
+     */
+    @SuppressLint("ArrayReturn")
+    @Nullable
+    @SuppressWarnings("unchecked")
+    public byte[][] getPropertyBytesArray(@NonNull String key) {
+        Preconditions.checkNotNull(key);
+        ArrayList<Bundle> bundles = getAndCastPropertyArray(key, ArrayList.class);
+        if (bundles == null || bundles.size() == 0) {
+            return null;
+        }
+        byte[][] bytes = new byte[bundles.size()][];
+        for (int i = 0; i < bundles.size(); i++) {
+            Bundle bundle = bundles.get(i);
+            if (bundle == null) {
+                Log.e(TAG, "The inner bundle is null at " + i + ", for key: " + key);
+                continue;
+            }
+            byte[] innerBytes = bundle.getByteArray(BYTE_ARRAY_FIELD);
+            if (innerBytes == null) {
+                Log.e(TAG, "The bundle at " + i + " contains a null byte[].");
+                continue;
+            }
+            bytes[i] = innerBytes;
+        }
+        return bytes;
+    }
+
+    /**
+     * Retrieves a repeated {@link GenericDocument} property by key.
+     *
+     * @param key The key to look for.
+     * @return The {@link GenericDocument}[] associated with the given key, or {@code null} if no
+     *     value is set or the value is of a different type.
+     */
+    @SuppressLint("ArrayReturn")
+    @Nullable
+    public GenericDocument[] getPropertyDocumentArray(@NonNull String key) {
+        Preconditions.checkNotNull(key);
+        Bundle[] bundles = getAndCastPropertyArray(key, Bundle[].class);
+        if (bundles == null || bundles.length == 0) {
+            return null;
+        }
+        GenericDocument[] documents = new GenericDocument[bundles.length];
+        for (int i = 0; i < bundles.length; i++) {
+            if (bundles[i] == null) {
+                Log.e(TAG, "The inner bundle is null at " + i + ", for key: " + key);
+                continue;
+            }
+            documents[i] = new GenericDocument(bundles[i]);
+        }
+        return documents;
+    }
+
+    /**
+     * Gets a repeated property of the given key, and casts it to the given class type, which must
+     * be an array class type.
+     */
+    @Nullable
+    private <T> T getAndCastPropertyArray(@NonNull String key, @NonNull Class<T> tClass) {
+        Object value = mProperties.get(key);
+        if (value == null) {
+            return null;
+        }
+        try {
+            return tClass.cast(value);
+        } catch (ClassCastException e) {
+            Log.w(TAG, "Error casting to requested type for key \"" + key + "\"", e);
+            return null;
+        }
+    }
+
+    @Override
+    public boolean equals(@Nullable Object other) {
+        if (this == other) {
+            return true;
+        }
+        if (!(other instanceof GenericDocument)) {
+            return false;
+        }
+        GenericDocument otherDocument = (GenericDocument) other;
+        return BundleUtil.deepEquals(this.mBundle, otherDocument.mBundle);
+    }
+
+    @Override
+    public int hashCode() {
+        if (mHashCode == null) {
+            mHashCode = BundleUtil.deepHashCode(mBundle);
+        }
+        return mHashCode;
+    }
+
+    @Override
+    @NonNull
+    public String toString() {
+        return bundleToString(mBundle).toString();
+    }
+
+    @SuppressWarnings("unchecked")
+    private static StringBuilder bundleToString(Bundle bundle) {
+        StringBuilder stringBuilder = new StringBuilder();
+        try {
+            final Set<String> keySet = bundle.keySet();
+            String[] keys = keySet.toArray(new String[0]);
+            // Sort keys to make output deterministic. We need a custom comparator to handle
+            // nulls (arbitrarily putting them first, similar to Comparator.nullsFirst, which is
+            // only available since N).
+            Arrays.sort(
+                    keys,
+                    (@Nullable String s1, @Nullable String s2) -> {
+                        if (s1 == null) {
+                            return s2 == null ? 0 : -1;
+                        } else if (s2 == null) {
+                            return 1;
+                        } else {
+                            return s1.compareTo(s2);
+                        }
+                    });
+            for (String key : keys) {
+                stringBuilder.append("{ key: '").append(key).append("' value: ");
+                Object valueObject = bundle.get(key);
+                if (valueObject == null) {
+                    stringBuilder.append("<null>");
+                } else if (valueObject instanceof Bundle) {
+                    stringBuilder.append(bundleToString((Bundle) valueObject));
+                } else if (valueObject.getClass().isArray()) {
+                    stringBuilder.append("[ ");
+                    for (int i = 0; i < Array.getLength(valueObject); i++) {
+                        Object element = Array.get(valueObject, i);
+                        stringBuilder.append("'");
+                        if (element instanceof Bundle) {
+                            stringBuilder.append(bundleToString((Bundle) element));
+                        } else {
+                            stringBuilder.append(Array.get(valueObject, i));
+                        }
+                        stringBuilder.append("' ");
+                    }
+                    stringBuilder.append("]");
+                } else if (valueObject instanceof ArrayList) {
+                    for (Bundle innerBundle : (ArrayList<Bundle>) valueObject) {
+                        stringBuilder.append(bundleToString(innerBundle));
+                    }
+                } else {
+                    stringBuilder.append(valueObject.toString());
+                }
+                stringBuilder.append(" } ");
+            }
+        } catch (RuntimeException e) {
+            // Catch any exceptions here since corrupt Bundles can throw different types of
+            // exceptions (e.g. b/38445840 & b/68937025).
+            stringBuilder.append("<error>");
+        }
+        return stringBuilder;
+    }
+
+    /**
+     * The builder class for {@link GenericDocument}.
+     *
+     * @param <BuilderType> Type of subclass who extends this.
+     */
+    // This builder is specifically designed to be extended by classes deriving from
+    // GenericDocument.
+    @SuppressLint("StaticFinalBuilder")
+    public static class Builder<BuilderType extends Builder> {
+
+        private final Bundle mProperties = new Bundle();
+        private final Bundle mBundle = new Bundle();
+        private final BuilderType mBuilderTypeInstance;
+        private boolean mBuilt = false;
+
+        /**
+         * Create a new {@link GenericDocument.Builder}.
+         *
+         * @param uri The uri of {@link GenericDocument}.
+         * @param schemaType The schema type of the {@link GenericDocument}. The passed-in {@code
+         *     schemaType} must be defined using {@link AppSearchSession#setSchema} prior to
+         *     inserting a document of this {@code schemaType} into the AppSearch index using {@link
+         *     AppSearchSession#putDocuments}. Otherwise, the document will be rejected by {@link
+         *     AppSearchSession#putDocuments}.
+         */
+        @SuppressWarnings("unchecked")
+        public Builder(@NonNull String uri, @NonNull String schemaType) {
+            Preconditions.checkNotNull(uri);
+            Preconditions.checkNotNull(schemaType);
+            mBuilderTypeInstance = (BuilderType) this;
+            mBundle.putString(GenericDocument.URI_FIELD, uri);
+            mBundle.putString(GenericDocument.SCHEMA_TYPE_FIELD, schemaType);
+            mBundle.putString(GenericDocument.NAMESPACE_FIELD, DEFAULT_NAMESPACE);
+            // Set current timestamp for creation timestamp by default.
+            mBundle.putLong(
+                    GenericDocument.CREATION_TIMESTAMP_MILLIS_FIELD, System.currentTimeMillis());
+            mBundle.putLong(GenericDocument.TTL_MILLIS_FIELD, DEFAULT_TTL_MILLIS);
+            mBundle.putInt(GenericDocument.SCORE_FIELD, DEFAULT_SCORE);
+            mBundle.putBundle(PROPERTIES_FIELD, mProperties);
+        }
+
+        /**
+         * Sets the app-defined namespace this Document resides in. No special values are reserved
+         * or understood by the infrastructure.
+         *
+         * <p>URIs are unique within a namespace.
+         *
+         * <p>The number of namespaces per app should be kept small for efficiency reasons.
+         */
+        @NonNull
+        public BuilderType setNamespace(@NonNull String namespace) {
+            mBundle.putString(GenericDocument.NAMESPACE_FIELD, namespace);
+            return mBuilderTypeInstance;
+        }
+
+        /**
+         * Sets the score of the {@link GenericDocument}.
+         *
+         * <p>The score is a query-independent measure of the document's quality, relative to other
+         * {@link GenericDocument}s of the same type.
+         *
+         * <p>Results may be sorted by score using {@link SearchSpec.Builder#setRankingStrategy}.
+         * Documents with higher scores are considered better than documents with lower scores.
+         *
+         * <p>Any nonnegative integer can be used a score.
+         *
+         * @throws IllegalArgumentException If the provided value is negative.
+         */
+        @NonNull
+        public BuilderType setScore(@IntRange(from = 0, to = Integer.MAX_VALUE) int score) {
+            Preconditions.checkState(!mBuilt, "Builder has already been used");
+            if (score < 0) {
+                throw new IllegalArgumentException("Document score cannot be negative.");
+            }
+            mBundle.putInt(GenericDocument.SCORE_FIELD, score);
+            return mBuilderTypeInstance;
+        }
+
+        /**
+         * Sets the creation timestamp of the {@link GenericDocument}, in milliseconds.
+         *
+         * <p>Should be set using a value obtained from the {@link System#currentTimeMillis} time
+         * base.
+         */
+        @NonNull
+        public BuilderType setCreationTimestampMillis(long creationTimestampMillis) {
+            Preconditions.checkState(!mBuilt, "Builder has already been used");
+            mBundle.putLong(
+                    GenericDocument.CREATION_TIMESTAMP_MILLIS_FIELD, creationTimestampMillis);
+            return mBuilderTypeInstance;
+        }
+
+        /**
+         * Sets the TTL (Time To Live) of the {@link GenericDocument}, in milliseconds.
+         *
+         * <p>The TTL is measured against {@link #getCreationTimestampMillis}. At the timestamp of
+         * {@code creationTimestampMillis + ttlMillis}, measured in the {@link
+         * System#currentTimeMillis} time base, the document will be auto-deleted.
+         *
+         * <p>The default value is 0, which means the document is permanent and won't be
+         * auto-deleted until the app is uninstalled.
+         *
+         * @param ttlMillis A non-negative duration in milliseconds.
+         * @throws IllegalArgumentException If the provided value is negative.
+         */
+        @NonNull
+        public BuilderType setTtlMillis(long ttlMillis) {
+            Preconditions.checkState(!mBuilt, "Builder has already been used");
+            if (ttlMillis < 0) {
+                throw new IllegalArgumentException("Document ttlMillis cannot be negative.");
+            }
+            mBundle.putLong(GenericDocument.TTL_MILLIS_FIELD, ttlMillis);
+            return mBuilderTypeInstance;
+        }
+
+        /**
+         * Sets one or multiple {@code String} values for a property, replacing its previous values.
+         *
+         * @param key The key associated with the {@code values}.
+         * @param values The {@code String} values of the property.
+         */
+        @NonNull
+        public BuilderType setPropertyString(@NonNull String key, @NonNull String... values) {
+            Preconditions.checkState(!mBuilt, "Builder has already been used");
+            Preconditions.checkNotNull(key);
+            Preconditions.checkNotNull(values);
+            putInPropertyBundle(key, values);
+            return mBuilderTypeInstance;
+        }
+
+        /**
+         * Sets one or multiple {@code boolean} values for a property, replacing its previous
+         * values.
+         *
+         * @param key The key associated with the {@code values}.
+         * @param values The {@code boolean} values of the property.
+         */
+        @NonNull
+        public BuilderType setPropertyBoolean(@NonNull String key, @NonNull boolean... values) {
+            Preconditions.checkState(!mBuilt, "Builder has already been used");
+            Preconditions.checkNotNull(key);
+            Preconditions.checkNotNull(values);
+            putInPropertyBundle(key, values);
+            return mBuilderTypeInstance;
+        }
+
+        /**
+         * Sets one or multiple {@code long} values for a property, replacing its previous values.
+         *
+         * @param key The key associated with the {@code values}.
+         * @param values The {@code long} values of the property.
+         */
+        @NonNull
+        public BuilderType setPropertyLong(@NonNull String key, @NonNull long... values) {
+            Preconditions.checkState(!mBuilt, "Builder has already been used");
+            Preconditions.checkNotNull(key);
+            Preconditions.checkNotNull(values);
+            putInPropertyBundle(key, values);
+            return mBuilderTypeInstance;
+        }
+
+        /**
+         * Sets one or multiple {@code double} values for a property, replacing its previous values.
+         *
+         * @param key The key associated with the {@code values}.
+         * @param values The {@code double} values of the property.
+         */
+        @NonNull
+        public BuilderType setPropertyDouble(@NonNull String key, @NonNull double... values) {
+            Preconditions.checkState(!mBuilt, "Builder has already been used");
+            Preconditions.checkNotNull(key);
+            Preconditions.checkNotNull(values);
+            putInPropertyBundle(key, values);
+            return mBuilderTypeInstance;
+        }
+
+        /**
+         * Sets one or multiple {@code byte[]} for a property, replacing its previous values.
+         *
+         * @param key The key associated with the {@code values}.
+         * @param values The {@code byte[]} of the property.
+         */
+        @NonNull
+        public BuilderType setPropertyBytes(@NonNull String key, @NonNull byte[]... values) {
+            Preconditions.checkState(!mBuilt, "Builder has already been used");
+            Preconditions.checkNotNull(key);
+            Preconditions.checkNotNull(values);
+            putInPropertyBundle(key, values);
+            return mBuilderTypeInstance;
+        }
+
+        /**
+         * Sets one or multiple {@link GenericDocument} values for a property, replacing its
+         * previous values.
+         *
+         * @param key The key associated with the {@code values}.
+         * @param values The {@link GenericDocument} values of the property.
+         */
+        @NonNull
+        public BuilderType setPropertyDocument(
+                @NonNull String key, @NonNull GenericDocument... values) {
+            Preconditions.checkState(!mBuilt, "Builder has already been used");
+            Preconditions.checkNotNull(key);
+            Preconditions.checkNotNull(values);
+            putInPropertyBundle(key, values);
+            return mBuilderTypeInstance;
+        }
+
+        private void putInPropertyBundle(@NonNull String key, @NonNull String[] values)
+                throws IllegalArgumentException {
+            validateRepeatedPropertyLength(key, values.length);
+            for (int i = 0; i < values.length; i++) {
+                if (values[i] == null) {
+                    throw new IllegalArgumentException("The String at " + i + " is null.");
+                } else if (values[i].length() > MAX_STRING_LENGTH) {
+                    throw new IllegalArgumentException(
+                            "The String at "
+                                    + i
+                                    + " length is: "
+                                    + values[i].length()
+                                    + ", which exceeds length limit: "
+                                    + MAX_STRING_LENGTH
+                                    + ".");
+                }
+            }
+            mProperties.putStringArray(key, values);
+        }
+
+        private void putInPropertyBundle(@NonNull String key, @NonNull boolean[] values) {
+            validateRepeatedPropertyLength(key, values.length);
+            mProperties.putBooleanArray(key, values);
+        }
+
+        private void putInPropertyBundle(@NonNull String key, @NonNull double[] values) {
+            validateRepeatedPropertyLength(key, values.length);
+            mProperties.putDoubleArray(key, values);
+        }
+
+        private void putInPropertyBundle(@NonNull String key, @NonNull long[] values) {
+            validateRepeatedPropertyLength(key, values.length);
+            mProperties.putLongArray(key, values);
+        }
+
+        /**
+         * Converts and saves a byte[][] into {@link #mProperties}.
+         *
+         * <p>Bundle doesn't support for two dimension array byte[][], we are converting byte[][]
+         * into ArrayList<Bundle>, and each elements will contain a one dimension byte[].
+         */
+        private void putInPropertyBundle(@NonNull String key, @NonNull byte[][] values) {
+            validateRepeatedPropertyLength(key, values.length);
+            ArrayList<Bundle> bundles = new ArrayList<>(values.length);
+            for (int i = 0; i < values.length; i++) {
+                if (values[i] == null) {
+                    throw new IllegalArgumentException("The byte[] at " + i + " is null.");
+                }
+                Bundle bundle = new Bundle();
+                bundle.putByteArray(BYTE_ARRAY_FIELD, values[i]);
+                bundles.add(bundle);
+            }
+            mProperties.putParcelableArrayList(key, bundles);
+        }
+
+        private void putInPropertyBundle(@NonNull String key, @NonNull GenericDocument[] values) {
+            validateRepeatedPropertyLength(key, values.length);
+            Bundle[] documentBundles = new Bundle[values.length];
+            for (int i = 0; i < values.length; i++) {
+                if (values[i] == null) {
+                    throw new IllegalArgumentException("The document at " + i + " is null.");
+                }
+                documentBundles[i] = values[i].mBundle;
+            }
+            mProperties.putParcelableArray(key, documentBundles);
+        }
+
+        private static void validateRepeatedPropertyLength(@NonNull String key, int length) {
+            if (length == 0) {
+                throw new IllegalArgumentException("The input array is empty.");
+            } else if (length > MAX_REPEATED_PROPERTY_LENGTH) {
+                throw new IllegalArgumentException(
+                        "Repeated property \""
+                                + key
+                                + "\" has length "
+                                + length
+                                + ", which exceeds the limit of "
+                                + MAX_REPEATED_PROPERTY_LENGTH);
+            }
+        }
+
+        /** Builds the {@link GenericDocument} object. */
+        @NonNull
+        public GenericDocument build() {
+            Preconditions.checkState(!mBuilt, "Builder has already been used");
+            mBuilt = true;
+            return new GenericDocument(mBundle);
+        }
+    }
+}
diff --git a/apex/appsearch/framework/java/external/android/app/appsearch/GetByUriRequest.java b/apex/appsearch/framework/java/external/android/app/appsearch/GetByUriRequest.java
new file mode 100644
index 0000000..74afdd2
--- /dev/null
+++ b/apex/appsearch/framework/java/external/android/app/appsearch/GetByUriRequest.java
@@ -0,0 +1,98 @@
+/*
+ * 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.
+ */
+
+package android.app.appsearch;
+
+import android.annotation.NonNull;
+import android.util.ArraySet;
+
+import com.android.internal.util.Preconditions;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Set;
+
+/**
+ * Encapsulates a request to retrieve documents by namespace and URI.
+ *
+ * @see AppSearchSession#getByUri
+ */
+public final class GetByUriRequest {
+    private final String mNamespace;
+    private final Set<String> mUris;
+
+    GetByUriRequest(@NonNull String namespace, @NonNull Set<String> uris) {
+        mNamespace = namespace;
+        mUris = uris;
+    }
+
+    /** Returns the namespace to get documents from. */
+    @NonNull
+    public String getNamespace() {
+        return mNamespace;
+    }
+
+    /** Returns the URIs to get from the namespace. */
+    @NonNull
+    public Set<String> getUris() {
+        return Collections.unmodifiableSet(mUris);
+    }
+
+    /** Builder for {@link GetByUriRequest} objects. */
+    public static final class Builder {
+        private String mNamespace = GenericDocument.DEFAULT_NAMESPACE;
+        private final Set<String> mUris = new ArraySet<>();
+        private boolean mBuilt = false;
+
+        /**
+         * Sets which namespace these documents will be retrieved from.
+         *
+         * <p>If this is not set, it defaults to {@link GenericDocument#DEFAULT_NAMESPACE}.
+         */
+        @NonNull
+        public Builder setNamespace(@NonNull String namespace) {
+            Preconditions.checkState(!mBuilt, "Builder has already been used");
+            Preconditions.checkNotNull(namespace);
+            mNamespace = namespace;
+            return this;
+        }
+
+        /** Adds one or more URIs to the request. */
+        @NonNull
+        public Builder addUri(@NonNull String... uris) {
+            Preconditions.checkNotNull(uris);
+            return addUri(Arrays.asList(uris));
+        }
+
+        /** Adds one or more URIs to the request. */
+        @NonNull
+        public Builder addUri(@NonNull Collection<String> uris) {
+            Preconditions.checkState(!mBuilt, "Builder has already been used");
+            Preconditions.checkNotNull(uris);
+            mUris.addAll(uris);
+            return this;
+        }
+
+        /** Builds a new {@link GetByUriRequest}. */
+        @NonNull
+        public GetByUriRequest build() {
+            Preconditions.checkState(!mBuilt, "Builder has already been used");
+            mBuilt = true;
+            return new GetByUriRequest(mNamespace, mUris);
+        }
+    }
+}
diff --git a/apex/appsearch/framework/java/external/android/app/appsearch/PutDocumentsRequest.java b/apex/appsearch/framework/java/external/android/app/appsearch/PutDocumentsRequest.java
new file mode 100644
index 0000000..1c360a6
--- /dev/null
+++ b/apex/appsearch/framework/java/external/android/app/appsearch/PutDocumentsRequest.java
@@ -0,0 +1,80 @@
+/*
+ * 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.
+ */
+
+package android.app.appsearch;
+
+import android.annotation.NonNull;
+import android.annotation.SuppressLint;
+import android.app.appsearch.exceptions.AppSearchException;
+
+import com.android.internal.util.Preconditions;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Encapsulates a request to index a document into an {@link AppSearchSession} database.
+ *
+ * @see AppSearchSession#putDocuments
+ */
+public final class PutDocumentsRequest {
+    private final List<GenericDocument> mDocuments;
+
+    PutDocumentsRequest(List<GenericDocument> documents) {
+        mDocuments = documents;
+    }
+
+    /** Returns the documents that are part of this request. */
+    @NonNull
+    public List<GenericDocument> getDocuments() {
+        return Collections.unmodifiableList(mDocuments);
+    }
+
+    /** Builder for {@link PutDocumentsRequest} objects. */
+    public static final class Builder {
+        private final List<GenericDocument> mDocuments = new ArrayList<>();
+        private boolean mBuilt = false;
+
+        /** Adds one or more documents to the request. */
+        @SuppressLint("MissingGetterMatchingBuilder") // Merged list available from getDocuments()
+        @NonNull
+        public Builder addGenericDocument(@NonNull GenericDocument... documents) {
+            Preconditions.checkNotNull(documents);
+            return addGenericDocument(Arrays.asList(documents));
+        }
+
+        /** Adds one or more documents to the request. */
+        @SuppressLint("MissingGetterMatchingBuilder") // Merged list available from getDocuments()
+        @NonNull
+        public Builder addGenericDocument(@NonNull Collection<GenericDocument> documents) {
+            Preconditions.checkState(!mBuilt, "Builder has already been used");
+            Preconditions.checkNotNull(documents);
+            mDocuments.addAll(documents);
+            return this;
+        }
+
+        /** Builds a new {@link PutDocumentsRequest}. */
+        @NonNull
+        public PutDocumentsRequest build() {
+            Preconditions.checkState(!mBuilt, "Builder has already been used");
+            mBuilt = true;
+            return new PutDocumentsRequest(mDocuments);
+        }
+    }
+}
diff --git a/apex/appsearch/framework/java/external/android/app/appsearch/RemoveByUriRequest.java b/apex/appsearch/framework/java/external/android/app/appsearch/RemoveByUriRequest.java
new file mode 100644
index 0000000..be6d157
--- /dev/null
+++ b/apex/appsearch/framework/java/external/android/app/appsearch/RemoveByUriRequest.java
@@ -0,0 +1,98 @@
+/*
+ * 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.
+ */
+
+package android.app.appsearch;
+
+import android.annotation.NonNull;
+import android.util.ArraySet;
+
+import com.android.internal.util.Preconditions;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Set;
+
+/**
+ * Encapsulates a request to remove documents by namespace and URI.
+ *
+ * @see AppSearchSession#removeByUri
+ */
+public final class RemoveByUriRequest {
+    private final String mNamespace;
+    private final Set<String> mUris;
+
+    RemoveByUriRequest(String namespace, Set<String> uris) {
+        mNamespace = namespace;
+        mUris = uris;
+    }
+
+    /** Returns the namespace to remove documents from. */
+    @NonNull
+    public String getNamespace() {
+        return mNamespace;
+    }
+
+    /** Returns the URIs to remove from the namespace. */
+    @NonNull
+    public Set<String> getUris() {
+        return Collections.unmodifiableSet(mUris);
+    }
+
+    /** Builder for {@link RemoveByUriRequest} objects. */
+    public static final class Builder {
+        private String mNamespace = GenericDocument.DEFAULT_NAMESPACE;
+        private final Set<String> mUris = new ArraySet<>();
+        private boolean mBuilt = false;
+
+        /**
+         * Sets which namespace these documents will be removed from.
+         *
+         * <p>If this is not set, it defaults to {@link GenericDocument#DEFAULT_NAMESPACE}.
+         */
+        @NonNull
+        public Builder setNamespace(@NonNull String namespace) {
+            Preconditions.checkState(!mBuilt, "Builder has already been used");
+            Preconditions.checkNotNull(namespace);
+            mNamespace = namespace;
+            return this;
+        }
+
+        /** Adds one or more URIs to the request. */
+        @NonNull
+        public Builder addUri(@NonNull String... uris) {
+            Preconditions.checkNotNull(uris);
+            return addUri(Arrays.asList(uris));
+        }
+
+        /** Adds one or more URIs to the request. */
+        @NonNull
+        public Builder addUri(@NonNull Collection<String> uris) {
+            Preconditions.checkState(!mBuilt, "Builder has already been used");
+            Preconditions.checkNotNull(uris);
+            mUris.addAll(uris);
+            return this;
+        }
+
+        /** Builds a new {@link RemoveByUriRequest}. */
+        @NonNull
+        public RemoveByUriRequest build() {
+            Preconditions.checkState(!mBuilt, "Builder has already been used");
+            mBuilt = true;
+            return new RemoveByUriRequest(mNamespace, mUris);
+        }
+    }
+}
diff --git a/apex/appsearch/framework/java/android/app/appsearch/SearchResult.java b/apex/appsearch/framework/java/external/android/app/appsearch/SearchResult.java
similarity index 100%
rename from apex/appsearch/framework/java/android/app/appsearch/SearchResult.java
rename to apex/appsearch/framework/java/external/android/app/appsearch/SearchResult.java
diff --git a/apex/appsearch/framework/java/android/app/appsearch/SearchResultPage.java b/apex/appsearch/framework/java/external/android/app/appsearch/SearchResultPage.java
similarity index 100%
rename from apex/appsearch/framework/java/android/app/appsearch/SearchResultPage.java
rename to apex/appsearch/framework/java/external/android/app/appsearch/SearchResultPage.java
diff --git a/apex/appsearch/framework/java/android/app/appsearch/SearchSpec.java b/apex/appsearch/framework/java/external/android/app/appsearch/SearchSpec.java
similarity index 100%
rename from apex/appsearch/framework/java/android/app/appsearch/SearchSpec.java
rename to apex/appsearch/framework/java/external/android/app/appsearch/SearchSpec.java
diff --git a/apex/appsearch/framework/java/external/android/app/appsearch/SetSchemaRequest.java b/apex/appsearch/framework/java/external/android/app/appsearch/SetSchemaRequest.java
new file mode 100644
index 0000000..0e03131
--- /dev/null
+++ b/apex/appsearch/framework/java/external/android/app/appsearch/SetSchemaRequest.java
@@ -0,0 +1,179 @@
+/*
+ * 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.
+ */
+
+package android.app.appsearch;
+
+import android.annotation.NonNull;
+import android.annotation.SuppressLint;
+import android.app.appsearch.exceptions.AppSearchException;
+import android.util.ArraySet;
+
+import com.android.internal.util.Preconditions;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Encapsulates a request to update the schema of an {@link AppSearchSession} database.
+ *
+ * @see AppSearchSession#setSchema
+ */
+public final class SetSchemaRequest {
+    private final Set<AppSearchSchema> mSchemas;
+    private final Set<String> mSchemasNotPlatformSurfaceable;
+    private final boolean mForceOverride;
+
+    SetSchemaRequest(
+            @NonNull Set<AppSearchSchema> schemas,
+            @NonNull Set<String> schemasNotPlatformSurfaceable,
+            boolean forceOverride) {
+        mSchemas = Preconditions.checkNotNull(schemas);
+        mSchemasNotPlatformSurfaceable = Preconditions.checkNotNull(schemasNotPlatformSurfaceable);
+        mForceOverride = forceOverride;
+    }
+
+    /** Returns the schemas that are part of this request. */
+    @NonNull
+    public Set<AppSearchSchema> getSchemas() {
+        return Collections.unmodifiableSet(mSchemas);
+    }
+
+    /**
+     * Returns the set of schema types that have opted out of being visible on system UI surfaces.
+     *
+     * @hide
+     */
+    @NonNull
+    public Set<String> getSchemasNotPlatformSurfaceable() {
+        return Collections.unmodifiableSet(mSchemasNotPlatformSurfaceable);
+    }
+
+    /** Returns whether this request will force the schema to be overridden. */
+    public boolean isForceOverride() {
+        return mForceOverride;
+    }
+
+    /** Builder for {@link SetSchemaRequest} objects. */
+    public static final class Builder {
+        private final Set<AppSearchSchema> mSchemas = new ArraySet<>();
+        private final Set<String> mSchemasNotPlatformSurfaceable = new ArraySet<>();
+        private boolean mForceOverride = false;
+        private boolean mBuilt = false;
+
+        /**
+         * Adds one or more types to the schema.
+         *
+         * <p>Any documents of these types will be visible on system UI surfaces by default.
+         */
+        @NonNull
+        public Builder addSchema(@NonNull AppSearchSchema... schemas) {
+            Preconditions.checkNotNull(schemas);
+            return addSchema(Arrays.asList(schemas));
+        }
+
+        /**
+         * Adds one or more types to the schema.
+         *
+         * <p>Any documents of these types will be visible on system UI surfaces by default.
+         */
+        @NonNull
+        public Builder addSchema(@NonNull Collection<AppSearchSchema> schemas) {
+            Preconditions.checkState(!mBuilt, "Builder has already been used");
+            Preconditions.checkNotNull(schemas);
+            mSchemas.addAll(schemas);
+            return this;
+        }
+
+        /**
+         * Sets visibility on system UI surfaces for schema types.
+         *
+         * @hide
+         */
+        @NonNull
+        public Builder setSchemaTypeVisibilityForSystemUi(
+                boolean visible, @NonNull String... schemaTypes) {
+            Preconditions.checkNotNull(schemaTypes);
+            return this.setSchemaTypeVisibilityForSystemUi(visible, Arrays.asList(schemaTypes));
+        }
+
+        /**
+         * Sets visibility on system UI surfaces for schema types.
+         *
+         * @hide
+         */
+        @NonNull
+        public Builder setSchemaTypeVisibilityForSystemUi(
+                boolean visible, @NonNull Collection<String> schemaTypes) {
+            Preconditions.checkState(!mBuilt, "Builder has already been used");
+            Preconditions.checkNotNull(schemaTypes);
+            if (visible) {
+                mSchemasNotPlatformSurfaceable.removeAll(schemaTypes);
+            } else {
+                mSchemasNotPlatformSurfaceable.addAll(schemaTypes);
+            }
+            return this;
+        }
+
+        /**
+         * Configures the {@link SetSchemaRequest} to delete any existing documents that don't
+         * follow the new schema.
+         *
+         * <p>By default, this is {@code false} and schema incompatibility causes the {@link
+         * AppSearchSession#setSchema} call to fail.
+         *
+         * @see AppSearchSession#setSchema
+         */
+        @NonNull
+        public Builder setForceOverride(boolean forceOverride) {
+            mForceOverride = forceOverride;
+            return this;
+        }
+
+        /**
+         * Builds a new {@link SetSchemaRequest}.
+         *
+         * @throws IllegalArgumentException If schema types were referenced, but the corresponding
+         *     {@link AppSearchSchema} was never added.
+         */
+        @NonNull
+        public SetSchemaRequest build() {
+            Preconditions.checkState(!mBuilt, "Builder has already been used");
+            mBuilt = true;
+
+            // Verify that any schema types with visibility settings refer to a real schema.
+            // Create a copy because we're going to remove from the set for verification purposes.
+            Set<String> schemasNotPlatformSurfaceableCopy =
+                    new ArraySet<>(mSchemasNotPlatformSurfaceable);
+            for (AppSearchSchema schema : mSchemas) {
+                schemasNotPlatformSurfaceableCopy.remove(schema.getSchemaType());
+            }
+            if (!schemasNotPlatformSurfaceableCopy.isEmpty()) {
+                // We still have schema types that weren't seen in our mSchemas set. This means
+                // there wasn't a corresponding AppSearchSchema.
+                throw new IllegalArgumentException(
+                        "Schema types "
+                                + schemasNotPlatformSurfaceableCopy
+                                + " referenced, but were not added.");
+            }
+
+            return new SetSchemaRequest(mSchemas, mSchemasNotPlatformSurfaceable, mForceOverride);
+        }
+    }
+}
diff --git a/apex/appsearch/framework/java/android/app/appsearch/exceptions/AppSearchException.java b/apex/appsearch/framework/java/external/android/app/appsearch/exceptions/AppSearchException.java
similarity index 100%
rename from apex/appsearch/framework/java/android/app/appsearch/exceptions/AppSearchException.java
rename to apex/appsearch/framework/java/external/android/app/appsearch/exceptions/AppSearchException.java
diff --git a/apex/appsearch/framework/java/android/app/appsearch/exceptions/IllegalSchemaException.java b/apex/appsearch/framework/java/external/android/app/appsearch/exceptions/IllegalSchemaException.java
similarity index 100%
rename from apex/appsearch/framework/java/android/app/appsearch/exceptions/IllegalSchemaException.java
rename to apex/appsearch/framework/java/external/android/app/appsearch/exceptions/IllegalSchemaException.java
diff --git a/apex/appsearch/framework/java/android/app/appsearch/exceptions/IllegalSearchSpecException.java b/apex/appsearch/framework/java/external/android/app/appsearch/exceptions/IllegalSearchSpecException.java
similarity index 100%
rename from apex/appsearch/framework/java/android/app/appsearch/exceptions/IllegalSearchSpecException.java
rename to apex/appsearch/framework/java/external/android/app/appsearch/exceptions/IllegalSearchSpecException.java
diff --git a/apex/appsearch/framework/java/external/android/app/appsearch/util/BundleUtil.java b/apex/appsearch/framework/java/external/android/app/appsearch/util/BundleUtil.java
new file mode 100644
index 0000000..1b4d284
--- /dev/null
+++ b/apex/appsearch/framework/java/external/android/app/appsearch/util/BundleUtil.java
@@ -0,0 +1,221 @@
+/*
+ * 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.
+ */
+
+package android.app.appsearch.util;
+
+import android.annotation.Nullable;
+import android.os.Bundle;
+import android.util.SparseArray;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+
+/**
+ * Utilities for working with {@link android.os.Bundle}.
+ *
+ * @hide
+ */
+public final class BundleUtil {
+    private BundleUtil() {}
+
+    /**
+     * Deeply checks two bundles are equal or not.
+     *
+     * <p>Two bundles will be considered equal if they contain the same keys, and each value is also
+     * equal. Bundle values are compared using deepEquals.
+     */
+    public static boolean deepEquals(@Nullable Bundle one, @Nullable Bundle two) {
+        if (one == null && two == null) {
+            return true;
+        }
+        if (one == null || two == null) {
+            return false;
+        }
+        if (one.size() != two.size()) {
+            return false;
+        }
+        if (!one.keySet().equals(two.keySet())) {
+            return false;
+        }
+        // Bundle inherit its equals() from Object.java, which only compare their memory address.
+        // We should iterate all keys and check their presents and values in both bundle.
+        for (String key : one.keySet()) {
+            if (!bundleValueEquals(one.get(key), two.get(key))) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Deeply checks whether two values in a Bundle are equal or not.
+     *
+     * <p>Values of type Bundle are compared using {@link #deepEquals}.
+     */
+    private static boolean bundleValueEquals(@Nullable Object one, @Nullable Object two) {
+        if (one == null && two == null) {
+            return true;
+        }
+        if (one == null || two == null) {
+            return false;
+        }
+        if (one.equals(two)) {
+            return true;
+        }
+        if (one instanceof Bundle && two instanceof Bundle) {
+            return deepEquals((Bundle) one, (Bundle) two);
+        } else if (one instanceof int[] && two instanceof int[]) {
+            return Arrays.equals((int[]) one, (int[]) two);
+        } else if (one instanceof byte[] && two instanceof byte[]) {
+            return Arrays.equals((byte[]) one, (byte[]) two);
+        } else if (one instanceof char[] && two instanceof char[]) {
+            return Arrays.equals((char[]) one, (char[]) two);
+        } else if (one instanceof long[] && two instanceof long[]) {
+            return Arrays.equals((long[]) one, (long[]) two);
+        } else if (one instanceof float[] && two instanceof float[]) {
+            return Arrays.equals((float[]) one, (float[]) two);
+        } else if (one instanceof short[] && two instanceof short[]) {
+            return Arrays.equals((short[]) one, (short[]) two);
+        } else if (one instanceof double[] && two instanceof double[]) {
+            return Arrays.equals((double[]) one, (double[]) two);
+        } else if (one instanceof boolean[] && two instanceof boolean[]) {
+            return Arrays.equals((boolean[]) one, (boolean[]) two);
+        } else if (one instanceof Object[] && two instanceof Object[]) {
+            Object[] arrayOne = (Object[]) one;
+            Object[] arrayTwo = (Object[]) two;
+            if (arrayOne.length != arrayTwo.length) {
+                return false;
+            }
+            if (Arrays.equals(arrayOne, arrayTwo)) {
+                return true;
+            }
+            for (int i = 0; i < arrayOne.length; i++) {
+                if (!bundleValueEquals(arrayOne[i], arrayTwo[i])) {
+                    return false;
+                }
+            }
+            return true;
+        } else if (one instanceof ArrayList && two instanceof ArrayList) {
+            ArrayList<?> listOne = (ArrayList<?>) one;
+            ArrayList<?> listTwo = (ArrayList<?>) two;
+            if (listOne.size() != listTwo.size()) {
+                return false;
+            }
+            for (int i = 0; i < listOne.size(); i++) {
+                if (!bundleValueEquals(listOne.get(i), listTwo.get(i))) {
+                    return false;
+                }
+            }
+            return true;
+        } else if (one instanceof SparseArray && two instanceof SparseArray) {
+            SparseArray<?> arrayOne = (SparseArray<?>) one;
+            SparseArray<?> arrayTwo = (SparseArray<?>) two;
+            if (arrayOne.size() != arrayTwo.size()) {
+                return false;
+            }
+            for (int i = 0; i < arrayOne.size(); i++) {
+                if (arrayOne.keyAt(i) != arrayTwo.keyAt(i)
+                        || !bundleValueEquals(arrayOne.valueAt(i), arrayTwo.valueAt(i))) {
+                    return false;
+                }
+            }
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Calculates the hash code for a bundle.
+     *
+     * <p>The hash code is only effected by the contents in the bundle. Bundles will get consistent
+     * hash code if they have same contents.
+     */
+    public static int deepHashCode(@Nullable Bundle bundle) {
+        if (bundle == null) {
+            return 0;
+        }
+        int[] hashCodes = new int[bundle.size()];
+        int i = 0;
+        // Bundle inherit its hashCode() from Object.java, which only relative to their memory
+        // address. Bundle doesn't have an order, so we should iterate all keys and combine
+        // their value's hashcode into an array. And use the hashcode of the array to be
+        // the hashcode of the bundle.
+        for (String key : bundle.keySet()) {
+            Object value = bundle.get(key);
+            if (value instanceof Bundle) {
+                hashCodes[i++] = deepHashCode((Bundle) value);
+            } else if (value instanceof int[]) {
+                hashCodes[i++] = Arrays.hashCode((int[]) value);
+            } else if (value instanceof byte[]) {
+                hashCodes[i++] = Arrays.hashCode((byte[]) value);
+            } else if (value instanceof char[]) {
+                hashCodes[i++] = Arrays.hashCode((char[]) value);
+            } else if (value instanceof long[]) {
+                hashCodes[i++] = Arrays.hashCode((long[]) value);
+            } else if (value instanceof float[]) {
+                hashCodes[i++] = Arrays.hashCode((float[]) value);
+            } else if (value instanceof short[]) {
+                hashCodes[i++] = Arrays.hashCode((short[]) value);
+            } else if (value instanceof double[]) {
+                hashCodes[i++] = Arrays.hashCode((double[]) value);
+            } else if (value instanceof boolean[]) {
+                hashCodes[i++] = Arrays.hashCode((boolean[]) value);
+            } else if (value instanceof String[]) {
+                // Optimization to avoid Object[] handler creating an inner array for common cases
+                hashCodes[i++] = Arrays.hashCode((String[]) value);
+            } else if (value instanceof Object[]) {
+                Object[] array = (Object[]) value;
+                int[] innerHashCodes = new int[array.length];
+                for (int j = 0; j < array.length; j++) {
+                    if (array[j] instanceof Bundle) {
+                        innerHashCodes[j] = deepHashCode((Bundle) array[j]);
+                    } else if (array[j] != null) {
+                        innerHashCodes[j] = array[j].hashCode();
+                    }
+                }
+                hashCodes[i++] = Arrays.hashCode(innerHashCodes);
+            } else if (value instanceof ArrayList) {
+                ArrayList<?> list = (ArrayList<?>) value;
+                int[] innerHashCodes = new int[list.size()];
+                for (int j = 0; j < innerHashCodes.length; j++) {
+                    Object item = list.get(j);
+                    if (item instanceof Bundle) {
+                        innerHashCodes[j] = deepHashCode((Bundle) item);
+                    } else if (item != null) {
+                        innerHashCodes[j] = item.hashCode();
+                    }
+                }
+                hashCodes[i++] = Arrays.hashCode(innerHashCodes);
+            } else if (value instanceof SparseArray) {
+                SparseArray<?> array = (SparseArray<?>) value;
+                int[] innerHashCodes = new int[array.size() * 2];
+                for (int j = 0; j < array.size(); j++) {
+                    innerHashCodes[j * 2] = array.keyAt(j);
+                    Object item = array.valueAt(j);
+                    if (item instanceof Bundle) {
+                        innerHashCodes[j * 2 + 1] = deepHashCode((Bundle) item);
+                    } else if (item != null) {
+                        innerHashCodes[j * 2 + 1] = item.hashCode();
+                    }
+                }
+                hashCodes[i++] = Arrays.hashCode(innerHashCodes);
+            } else {
+                hashCodes[i++] = value.hashCode();
+            }
+        }
+        return Arrays.hashCode(hashCodes);
+    }
+}
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java b/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java
index d5146dd..551347c 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java
@@ -33,15 +33,14 @@
 import android.os.ParcelableException;
 import android.os.RemoteException;
 import android.os.UserHandle;
-import android.util.ArraySet;
 import android.util.Log;
 
 import com.android.internal.util.Preconditions;
 import com.android.server.SystemService;
 import com.android.server.appsearch.external.localstorage.AppSearchImpl;
 
+import java.util.ArrayList;
 import java.util.List;
-import java.util.Set;
 
 /**
  * TODO(b/142567528): add comments when implement this class
@@ -64,6 +63,7 @@
         public void setSchema(
                 @NonNull String databaseName,
                 @NonNull List<Bundle> schemaBundles,
+                @NonNull List<String> schemasNotPlatformSurfaceable,
                 boolean forceOverride,
                 @NonNull IAppSearchResultCallback callback) {
             Preconditions.checkNotNull(databaseName);
@@ -73,13 +73,13 @@
             int callingUserId = UserHandle.getUserId(callingUid);
             final long callingIdentity = Binder.clearCallingIdentity();
             try {
-                Set<AppSearchSchema> schemas = new ArraySet<>(schemaBundles.size());
+                List<AppSearchSchema> schemas = new ArrayList<>(schemaBundles.size());
                 for (int i = 0; i < schemaBundles.size(); i++) {
                     schemas.add(new AppSearchSchema(schemaBundles.get(i)));
                 }
                 AppSearchImpl impl = ImplInstanceManager.getInstance(getContext(), callingUserId);
                 databaseName = rewriteDatabaseNameWithUid(databaseName, callingUid);
-                impl.setSchema(databaseName, schemas, forceOverride);
+                impl.setSchema(databaseName, schemas, schemasNotPlatformSurfaceable, forceOverride);
                 invokeCallbackOnResult(callback,
                         AppSearchResult.newSuccessfulResult(/*result=*/ null));
             } catch (Throwable t) {
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchImpl.java b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchImpl.java
index 247089b..62b81d0 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchImpl.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchImpl.java
@@ -60,6 +60,7 @@
 import com.google.android.icing.proto.StatusProto;
 
 import java.io.File;
+import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
@@ -226,13 +227,16 @@
      *
      * @param databaseName The name of the database where this schema lives.
      * @param schemas Schemas to set for this app.
+     * @param schemasNotPlatformSurfaceable Schema types that should not be surfaced on platform
+     *     surfaces.
      * @param forceOverride Whether to force-apply the schema even if it is incompatible. Documents
      *     which do not comply with the new schema will be deleted.
      * @throws AppSearchException on IcingSearchEngine error.
      */
     public void setSchema(
             @NonNull String databaseName,
-            @NonNull Set<AppSearchSchema> schemas,
+            @NonNull List<AppSearchSchema> schemas,
+            @NonNull List<String> schemasNotPlatformSurfaceable,
             boolean forceOverride)
             throws AppSearchException {
         mReadWriteLock.writeLock().lock();
@@ -240,8 +244,9 @@
             SchemaProto.Builder existingSchemaBuilder = getSchemaProtoLocked().toBuilder();
 
             SchemaProto.Builder newSchemaBuilder = SchemaProto.newBuilder();
-            for (AppSearchSchema schema : schemas) {
-                SchemaTypeConfigProto schemaTypeProto = SchemaToProtoConverter.convert(schema);
+            for (int i = 0; i < schemas.size(); i++) {
+                SchemaTypeConfigProto schemaTypeProto =
+                        SchemaToProtoConverter.toSchemaTypeConfigProto(schemas.get(i));
                 newSchemaBuilder.addTypes(schemaTypeProto);
             }
 
@@ -276,8 +281,16 @@
 
             // Update derived data structures.
             mSchemaMapLocked.put(databaseName, rewrittenSchemaResults.mRewrittenQualifiedTypes);
-            mVisibilityStoreLocked.updateSchemas(
-                    databaseName, rewrittenSchemaResults.mDeletedQualifiedTypes);
+
+            String databasePrefix = getDatabasePrefix(databaseName);
+            Set<String> qualifiedSchemasNotPlatformSurfaceable =
+                    new ArraySet<>(schemasNotPlatformSurfaceable.size());
+            for (int i = 0; i < schemasNotPlatformSurfaceable.size(); i++) {
+                qualifiedSchemasNotPlatformSurfaceable.add(
+                        databasePrefix + schemasNotPlatformSurfaceable.get(i));
+            }
+            mVisibilityStoreLocked.setVisibility(
+                    databaseName, qualifiedSchemasNotPlatformSurfaceable);
 
             // Determine whether to schedule an immediate optimize.
             if (setSchemaResultProto.getDeletedSchemaTypesCount() > 0
@@ -294,38 +307,55 @@
     }
 
     /**
-     * Update the visibility settings for this app.
+     * Retrieves the AppSearch schema for this database.
      *
-     * <p>This method belongs to the mutate group
+     * <p>This method belongs to query group.
      *
-     * @param databaseName The name of the database where the visibility settings will apply.
-     * @param schemasHiddenFromPlatformSurfaces Schemas that should be hidden from platform surfaces
-     * @throws AppSearchException on IcingSearchEngine error
+     * @param databaseName The name of the database where this schema lives.
+     * @throws AppSearchException on IcingSearchEngine error.
      */
-    public void setVisibility(
-            @NonNull String databaseName, @NonNull Set<String> schemasHiddenFromPlatformSurfaces)
-            throws AppSearchException {
-        mReadWriteLock.writeLock().lock();
+    @NonNull
+    public List<AppSearchSchema> getSchema(@NonNull String databaseName) throws AppSearchException {
+        SchemaProto fullSchema;
+        mReadWriteLock.readLock().lock();
         try {
-            String databasePrefix = getDatabasePrefix(databaseName);
-            Set<String> qualifiedSchemasHiddenFromPlatformSurface =
-                    new ArraySet<>(schemasHiddenFromPlatformSurfaces.size());
-            for (String schema : schemasHiddenFromPlatformSurfaces) {
-                Set<String> existingSchemas = mSchemaMapLocked.get(databaseName);
-                if (existingSchemas == null || !existingSchemas.contains(databasePrefix + schema)) {
-                    throw new AppSearchException(
-                            AppSearchResult.RESULT_NOT_FOUND,
-                            "Unknown schema(s): "
-                                    + schemasHiddenFromPlatformSurfaces
-                                    + " provided during setVisibility.");
-                }
-                qualifiedSchemasHiddenFromPlatformSurface.add(databasePrefix + schema);
-            }
-            mVisibilityStoreLocked.setVisibility(
-                    databaseName, qualifiedSchemasHiddenFromPlatformSurface);
+            fullSchema = getSchemaProtoLocked();
         } finally {
-            mReadWriteLock.writeLock().lock();
+            mReadWriteLock.readLock().unlock();
         }
+
+        List<AppSearchSchema> result = new ArrayList<>();
+        for (int i = 0; i < fullSchema.getTypesCount(); i++) {
+            String typeDatabase = getDatabaseName(fullSchema.getTypes(i).getSchemaType());
+            if (!databaseName.equals(typeDatabase)) {
+                continue;
+            }
+            // Rewrite SchemaProto.types.schema_type
+            SchemaTypeConfigProto.Builder typeConfigBuilder = fullSchema.getTypes(i).toBuilder();
+            String newSchemaType =
+                    typeConfigBuilder.getSchemaType().substring(databaseName.length() + 1);
+            typeConfigBuilder.setSchemaType(newSchemaType);
+
+            // Rewrite SchemaProto.types.properties.schema_type
+            for (int propertyIdx = 0;
+                    propertyIdx < typeConfigBuilder.getPropertiesCount();
+                    propertyIdx++) {
+                PropertyConfigProto.Builder propertyConfigBuilder =
+                        typeConfigBuilder.getProperties(propertyIdx).toBuilder();
+                if (!propertyConfigBuilder.getSchemaType().isEmpty()) {
+                    String newPropertySchemaType =
+                            propertyConfigBuilder
+                                    .getSchemaType()
+                                    .substring(databaseName.length() + 1);
+                    propertyConfigBuilder.setSchemaType(newPropertySchemaType);
+                    typeConfigBuilder.setProperties(propertyIdx, propertyConfigBuilder);
+                }
+            }
+
+            AppSearchSchema schema = SchemaToProtoConverter.toAppSearchSchema(typeConfigBuilder);
+            result.add(schema);
+        }
+        return result;
     }
 
     /**
@@ -340,7 +370,7 @@
     public void putDocument(@NonNull String databaseName, @NonNull GenericDocument document)
             throws AppSearchException {
         DocumentProto.Builder documentBuilder =
-                GenericDocumentToProtoConverter.convert(document).toBuilder();
+                GenericDocumentToProtoConverter.toDocumentProto(document).toBuilder();
         addPrefixToDocument(documentBuilder, getDatabasePrefix(databaseName));
 
         PutResultProto putResultProto;
@@ -384,7 +414,7 @@
 
         DocumentProto.Builder documentBuilder = getResultProto.getDocument().toBuilder();
         removeDatabasesFromDocument(documentBuilder);
-        return GenericDocumentToProtoConverter.convert(documentBuilder.build());
+        return GenericDocumentToProtoConverter.toGenericDocument(documentBuilder.build());
     }
 
     /**
@@ -969,7 +999,7 @@
                 resultsBuilder.setResults(i, resultBuilder);
             }
         }
-        return SearchResultToProtoConverter.convertToSearchResultPage(resultsBuilder);
+        return SearchResultToProtoConverter.toSearchResultPage(resultsBuilder);
     }
 
     @GuardedBy("mReadWriteLock")
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/VisibilityStore.java b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/VisibilityStore.java
index 4722822..0b68ebc 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/VisibilityStore.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/VisibilityStore.java
@@ -53,19 +53,23 @@
 class VisibilityStore {
     // Schema type for documents that hold AppSearch's metadata, e.g. visibility settings
     @VisibleForTesting static final String SCHEMA_TYPE = "Visibility";
+
     // Property that holds the list of platform-hidden schemas, as part of the visibility
     // settings.
-    @VisibleForTesting static final String PLATFORM_HIDDEN_PROPERTY = "platformHidden";
+    @VisibleForTesting
+    static final String NOT_PLATFORM_SURFACEABLE_PROPERTY = "notPlatformSurfaceable";
     // Database name to prefix all visibility schemas and documents with. Special-cased to
     // minimize the chance of collision with a client-supplied database.
+
     @VisibleForTesting static final String DATABASE_NAME = "$$__AppSearch__Database";
+
     // Namespace of documents that contain visibility settings
     private static final String NAMESPACE = "namespace";
     private final AppSearchImpl mAppSearchImpl;
 
     // The map contains schemas that are platform-hidden for each database. All schemas in the map
     // have a database name prefix.
-    private final Map<String, Set<String>> mPlatformHiddenMap = new ArrayMap<>();
+    private final Map<String, Set<String>> mNotPlatformSurfaceableMap = new ArrayMap<>();
 
     /**
      * Creates an uninitialized VisibilityStore object. Callers must also call {@link #initialize()}
@@ -82,8 +86,8 @@
      *
      * <p>This is kept separate from the constructor because this will call methods on
      * AppSearchImpl. Some may even then recursively call back into VisibilityStore (for example,
-     * {@link AppSearchImpl#setSchema} will call {@link #updateSchemas}. We need to have both
-     * AppSearchImpl and VisibilityStore fully initialized for this call flow to work.
+     * {@link AppSearchImpl#setSchema} will call {@link #setVisibility(String, Set)}. We need to
+     * have both AppSearchImpl and VisibilityStore fully initialized for this call flow to work.
      *
      * @throws AppSearchException AppSearchException on AppSearchImpl error.
      */
@@ -92,11 +96,11 @@
             // Schema type doesn't exist yet. Add it.
             mAppSearchImpl.setSchema(
                     DATABASE_NAME,
-                    Collections.singleton(
+                    Collections.singletonList(
                             new AppSearchSchema.Builder(SCHEMA_TYPE)
                                     .addProperty(
                                             new AppSearchSchema.PropertyConfig.Builder(
-                                                            PLATFORM_HIDDEN_PROPERTY)
+                                                            NOT_PLATFORM_SURFACEABLE_PROPERTY)
                                                     .setDataType(
                                                             AppSearchSchema.PropertyConfig
                                                                     .DATA_TYPE_STRING)
@@ -105,6 +109,7 @@
                                                                     .CARDINALITY_REPEATED)
                                                     .build())
                                     .build()),
+                    /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
                     /*forceOverride=*/ false);
         }
 
@@ -120,8 +125,9 @@
                 GenericDocument document =
                         mAppSearchImpl.getDocument(DATABASE_NAME, NAMESPACE, /*uri=*/ database);
 
-                String[] schemas = document.getPropertyStringArray(PLATFORM_HIDDEN_PROPERTY);
-                mPlatformHiddenMap.put(database, new ArraySet<>(Arrays.asList(schemas)));
+                String[] schemas =
+                        document.getPropertyStringArray(NOT_PLATFORM_SURFACEABLE_PROPERTY);
+                mNotPlatformSurfaceableMap.put(database, new ArraySet<>(Arrays.asList(schemas)));
             } catch (AppSearchException e) {
                 if (e.getResultCode() == AppSearchResult.RESULT_NOT_FOUND) {
                     // TODO(b/172068212): This indicates some desync error. We were expecting a
@@ -136,94 +142,33 @@
     }
 
     /**
-     * Update visibility settings for the {@code databaseName}.
-     *
-     * @param schemasToRemove Database-prefixed schemas that should be removed
-     */
-    public void updateSchemas(@NonNull String databaseName, @NonNull Set<String> schemasToRemove)
-            throws AppSearchException {
-        Preconditions.checkNotNull(databaseName);
-        Preconditions.checkNotNull(schemasToRemove);
-
-        GenericDocument visibilityDocument;
-        try {
-            visibilityDocument =
-                    mAppSearchImpl.getDocument(DATABASE_NAME, NAMESPACE, /*uri=*/ databaseName);
-        } catch (AppSearchException e) {
-            if (e.getResultCode() == AppSearchResult.RESULT_NOT_FOUND) {
-                // This might be the first time we're seeing visibility changes for a database.
-                // Create a new visibility document.
-                mAppSearchImpl.putDocument(
-                        DATABASE_NAME,
-                        new GenericDocument.Builder(/*uri=*/ databaseName, SCHEMA_TYPE)
-                                .setNamespace(NAMESPACE)
-                                .build());
-
-                // Since we know there was nothing that existed before, we don't need to remove
-                // anything either. Return early.
-                return;
-            }
-            // Otherwise, this is some real error we should pass up.
-            throw e;
-        }
-
-        String[] hiddenSchemas =
-                visibilityDocument.getPropertyStringArray(PLATFORM_HIDDEN_PROPERTY);
-        if (hiddenSchemas == null) {
-            // Nothing to remove.
-            return;
-        }
-
-        // Create a new set so we can remove from it.
-        Set<String> remainingSchemas = new ArraySet<>(Arrays.asList(hiddenSchemas));
-        boolean changed = remainingSchemas.removeAll(schemasToRemove);
-        if (!changed) {
-            // Nothing was actually removed. Can return early.
-            return;
-        }
-
-        // Update our persisted document
-        // TODO(b/171882200): Switch to a .toBuilder API when it's available.
-        GenericDocument.Builder newVisibilityDocument =
-                new GenericDocument.Builder(/*uri=*/ databaseName, SCHEMA_TYPE)
-                        .setNamespace(NAMESPACE);
-        if (!remainingSchemas.isEmpty()) {
-            newVisibilityDocument.setPropertyString(
-                    PLATFORM_HIDDEN_PROPERTY, remainingSchemas.toArray(new String[0]));
-        }
-        mAppSearchImpl.putDocument(DATABASE_NAME, newVisibilityDocument.build());
-
-        // Update derived data structures
-        mPlatformHiddenMap.put(databaseName, remainingSchemas);
-    }
-
-    /**
      * Sets visibility settings for {@code databaseName}. Any previous visibility settings will be
      * overwritten.
      *
-     * @param databaseName Database name that owns the {@code platformHiddenSchemas}.
-     * @param platformHiddenSchemas Set of database-qualified schemas that should be hidden from the
-     *     platform.
+     * @param databaseName Database name that owns the {@code schemasNotPlatformSurfaceable}.
+     * @param schemasNotPlatformSurfaceable Set of database-qualified schemas that should be hidden
+     *     from the platform.
      * @throws AppSearchException on AppSearchImpl error.
      */
     public void setVisibility(
-            @NonNull String databaseName, @NonNull Set<String> platformHiddenSchemas)
+            @NonNull String databaseName, @NonNull Set<String> schemasNotPlatformSurfaceable)
             throws AppSearchException {
         Preconditions.checkNotNull(databaseName);
-        Preconditions.checkNotNull(platformHiddenSchemas);
+        Preconditions.checkNotNull(schemasNotPlatformSurfaceable);
 
         // Persist the document
         GenericDocument.Builder visibilityDocument =
                 new GenericDocument.Builder(/*uri=*/ databaseName, SCHEMA_TYPE)
                         .setNamespace(NAMESPACE);
-        if (!platformHiddenSchemas.isEmpty()) {
+        if (!schemasNotPlatformSurfaceable.isEmpty()) {
             visibilityDocument.setPropertyString(
-                    PLATFORM_HIDDEN_PROPERTY, platformHiddenSchemas.toArray(new String[0]));
+                    NOT_PLATFORM_SURFACEABLE_PROPERTY,
+                    schemasNotPlatformSurfaceable.toArray(new String[0]));
         }
         mAppSearchImpl.putDocument(DATABASE_NAME, visibilityDocument.build());
 
         // Update derived data structures.
-        mPlatformHiddenMap.put(databaseName, platformHiddenSchemas);
+        mNotPlatformSurfaceableMap.put(databaseName, schemasNotPlatformSurfaceable);
     }
 
     /**
@@ -235,13 +180,13 @@
      *     none exist.
      */
     @NonNull
-    public Set<String> getPlatformHiddenSchemas(@NonNull String databaseName) {
+    public Set<String> getSchemasNotPlatformSurfaceable(@NonNull String databaseName) {
         Preconditions.checkNotNull(databaseName);
-        Set<String> platformHiddenSchemas = mPlatformHiddenMap.get(databaseName);
-        if (platformHiddenSchemas == null) {
+        Set<String> schemasNotPlatformSurfaceable = mNotPlatformSurfaceableMap.get(databaseName);
+        if (schemasNotPlatformSurfaceable == null) {
             return Collections.emptySet();
         }
-        return platformHiddenSchemas;
+        return schemasNotPlatformSurfaceable;
     }
 
     /**
@@ -251,7 +196,7 @@
      * @throws AppSearchException on AppSearchImpl error.
      */
     public void handleReset() throws AppSearchException {
-        mPlatformHiddenMap.clear();
+        mNotPlatformSurfaceableMap.clear();
         initialize();
     }
 }
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/GenericDocumentToProtoConverter.java b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/GenericDocumentToProtoConverter.java
index 8f4e7ff6..5474cd0 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/GenericDocumentToProtoConverter.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/GenericDocumentToProtoConverter.java
@@ -39,7 +39,7 @@
     /** Converts a {@link GenericDocument} into a {@link DocumentProto}. */
     @NonNull
     @SuppressWarnings("unchecked")
-    public static DocumentProto convert(@NonNull GenericDocument document) {
+    public static DocumentProto toDocumentProto(@NonNull GenericDocument document) {
         Preconditions.checkNotNull(document);
         DocumentProto.Builder mProtoBuilder = DocumentProto.newBuilder();
         mProtoBuilder
@@ -82,7 +82,7 @@
                 }
             } else if (documentValues != null) {
                 for (int j = 0; j < documentValues.length; j++) {
-                    DocumentProto proto = convert(documentValues[j]);
+                    DocumentProto proto = toDocumentProto(documentValues[j]);
                     propertyProto.addDocumentValues(proto);
                 }
             } else {
@@ -96,7 +96,7 @@
 
     /** Converts a {@link DocumentProto} into a {@link GenericDocument}. */
     @NonNull
-    public static GenericDocument convert(@NonNull DocumentProto proto) {
+    public static GenericDocument toGenericDocument(@NonNull DocumentProto proto) {
         Preconditions.checkNotNull(proto);
         GenericDocument.Builder<?> documentBuilder =
                 new GenericDocument.Builder<>(proto.getUri(), proto.getSchema())
@@ -141,7 +141,7 @@
             } else if (property.getDocumentValuesCount() > 0) {
                 GenericDocument[] values = new GenericDocument[property.getDocumentValuesCount()];
                 for (int j = 0; j < values.length; j++) {
-                    values[j] = convert(property.getDocumentValues(j));
+                    values[j] = toGenericDocument(property.getDocumentValues(j));
                 }
                 documentBuilder.setPropertyDocument(name, values);
             } else {
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/SchemaToProtoConverter.java b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/SchemaToProtoConverter.java
index 642c2a7..4165af31 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/SchemaToProtoConverter.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/SchemaToProtoConverter.java
@@ -18,11 +18,13 @@
 
 import android.annotation.NonNull;
 import android.app.appsearch.AppSearchSchema;
+import android.util.Log;
 
 import com.android.internal.util.Preconditions;
 
 import com.google.android.icing.proto.PropertyConfigProto;
 import com.google.android.icing.proto.SchemaTypeConfigProto;
+import com.google.android.icing.proto.SchemaTypeConfigProtoOrBuilder;
 import com.google.android.icing.proto.StringIndexingConfig;
 import com.google.android.icing.proto.TermMatchType;
 
@@ -34,6 +36,8 @@
  * @hide
  */
 public final class SchemaToProtoConverter {
+    private static final String TAG = "AppSearchSchemaToProtoC";
+
     private SchemaToProtoConverter() {}
 
     /**
@@ -41,23 +45,23 @@
      * SchemaTypeConfigProto}.
      */
     @NonNull
-    public static SchemaTypeConfigProto convert(@NonNull AppSearchSchema schema) {
+    public static SchemaTypeConfigProto toSchemaTypeConfigProto(@NonNull AppSearchSchema schema) {
         Preconditions.checkNotNull(schema);
         SchemaTypeConfigProto.Builder protoBuilder =
                 SchemaTypeConfigProto.newBuilder().setSchemaType(schema.getSchemaType());
         List<AppSearchSchema.PropertyConfig> properties = schema.getProperties();
         for (int i = 0; i < properties.size(); i++) {
-            PropertyConfigProto propertyProto = convertProperty(properties.get(i));
+            PropertyConfigProto propertyProto = toPropertyConfigProto(properties.get(i));
             protoBuilder.addProperties(propertyProto);
         }
         return protoBuilder.build();
     }
 
     @NonNull
-    private static PropertyConfigProto convertProperty(
+    private static PropertyConfigProto toPropertyConfigProto(
             @NonNull AppSearchSchema.PropertyConfig property) {
         Preconditions.checkNotNull(property);
-        PropertyConfigProto.Builder propertyConfigProto =
+        PropertyConfigProto.Builder builder =
                 PropertyConfigProto.newBuilder().setPropertyName(property.getName());
         StringIndexingConfig.Builder indexingConfig = StringIndexingConfig.newBuilder();
 
@@ -68,12 +72,12 @@
         if (dataTypeProto == null) {
             throw new IllegalArgumentException("Invalid dataType: " + dataType);
         }
-        propertyConfigProto.setDataType(dataTypeProto);
+        builder.setDataType(dataTypeProto);
 
         // Set schemaType
         String schemaType = property.getSchemaType();
         if (schemaType != null) {
-            propertyConfigProto.setSchemaType(schemaType);
+            builder.setSchemaType(schemaType);
         }
 
         // Set cardinality
@@ -83,7 +87,7 @@
         if (cardinalityProto == null) {
             throw new IllegalArgumentException("Invalid cardinality: " + dataType);
         }
-        propertyConfigProto.setCardinality(cardinalityProto);
+        builder.setCardinality(cardinalityProto);
 
         // Set indexingType
         @AppSearchSchema.PropertyConfig.IndexingType int indexingType = property.getIndexingType();
@@ -114,7 +118,63 @@
         indexingConfig.setTokenizerType(tokenizerTypeProto);
 
         // Build!
-        propertyConfigProto.setStringIndexingConfig(indexingConfig);
-        return propertyConfigProto.build();
+        builder.setStringIndexingConfig(indexingConfig);
+        return builder.build();
+    }
+
+    /**
+     * Converts a {@link SchemaTypeConfigProto} into an {@link
+     * android.app.appsearch.AppSearchSchema}.
+     */
+    @NonNull
+    public static AppSearchSchema toAppSearchSchema(@NonNull SchemaTypeConfigProtoOrBuilder proto) {
+        Preconditions.checkNotNull(proto);
+        AppSearchSchema.Builder builder = new AppSearchSchema.Builder(proto.getSchemaType());
+        List<PropertyConfigProto> properties = proto.getPropertiesList();
+        for (int i = 0; i < properties.size(); i++) {
+            AppSearchSchema.PropertyConfig propertyConfig = toPropertyConfig(properties.get(i));
+            builder.addProperty(propertyConfig);
+        }
+        return builder.build();
+    }
+
+    @NonNull
+    private static AppSearchSchema.PropertyConfig toPropertyConfig(
+            @NonNull PropertyConfigProto proto) {
+        Preconditions.checkNotNull(proto);
+        AppSearchSchema.PropertyConfig.Builder builder =
+                new AppSearchSchema.PropertyConfig.Builder(proto.getPropertyName())
+                        .setDataType(proto.getDataType().getNumber())
+                        .setCardinality(proto.getCardinality().getNumber())
+                        .setTokenizerType(
+                                proto.getStringIndexingConfig().getTokenizerType().getNumber());
+
+        // Set schema
+        if (!proto.getSchemaType().isEmpty()) {
+            builder.setSchemaType(proto.getSchemaType());
+        }
+
+        // Set indexingType
+        @AppSearchSchema.PropertyConfig.IndexingType int indexingType;
+        TermMatchType.Code termMatchTypeProto = proto.getStringIndexingConfig().getTermMatchType();
+        switch (termMatchTypeProto) {
+            case UNKNOWN:
+                indexingType = AppSearchSchema.PropertyConfig.INDEXING_TYPE_NONE;
+                break;
+            case EXACT_ONLY:
+                indexingType = AppSearchSchema.PropertyConfig.INDEXING_TYPE_EXACT_TERMS;
+                break;
+            case PREFIX:
+                indexingType = AppSearchSchema.PropertyConfig.INDEXING_TYPE_PREFIXES;
+                break;
+            default:
+                // Avoid crashing in the 'read' path; we should try to interpret the document to the
+                // extent possible.
+                Log.w(TAG, "Invalid indexingType: " + termMatchTypeProto.getNumber());
+                indexingType = AppSearchSchema.PropertyConfig.INDEXING_TYPE_NONE;
+        }
+        builder.setIndexingType(indexingType);
+
+        return builder.build();
     }
 }
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/SearchResultToProtoConverter.java b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/SearchResultToProtoConverter.java
index b91a393..4d107a9 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/SearchResultToProtoConverter.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/SearchResultToProtoConverter.java
@@ -39,13 +39,12 @@
 
     /** Translate a {@link SearchResultProto} into {@link SearchResultPage}. */
     @NonNull
-    public static SearchResultPage convertToSearchResultPage(
-            @NonNull SearchResultProtoOrBuilder proto) {
+    public static SearchResultPage toSearchResultPage(@NonNull SearchResultProtoOrBuilder proto) {
         Bundle bundle = new Bundle();
         bundle.putLong(SearchResultPage.NEXT_PAGE_TOKEN_FIELD, proto.getNextPageToken());
         ArrayList<Bundle> resultBundles = new ArrayList<>(proto.getResultsCount());
         for (int i = 0; i < proto.getResultsCount(); i++) {
-            resultBundles.add(convertToSearchResultBundle(proto.getResults(i)));
+            resultBundles.add(toSearchResultBundle(proto.getResults(i)));
         }
         bundle.putParcelableArrayList(SearchResultPage.RESULTS_FIELD, resultBundles);
         return new SearchResultPage(bundle);
@@ -53,10 +52,11 @@
 
     /** Translate a {@link SearchResultProto.ResultProto} into {@link SearchResult}. */
     @NonNull
-    private static Bundle convertToSearchResultBundle(
+    private static Bundle toSearchResultBundle(
             @NonNull SearchResultProto.ResultProtoOrBuilder proto) {
         Bundle bundle = new Bundle();
-        GenericDocument document = GenericDocumentToProtoConverter.convert(proto.getDocument());
+        GenericDocument document =
+                GenericDocumentToProtoConverter.toGenericDocument(proto.getDocument());
         bundle.putBundle(SearchResult.DOCUMENT_FIELD, document.getBundle());
 
         ArrayList<Bundle> matchList = new ArrayList<>();
diff --git a/apex/appsearch/synced_jetpack_changeid.txt b/apex/appsearch/synced_jetpack_changeid.txt
index a2bf0d5..57c48d8 100644
--- a/apex/appsearch/synced_jetpack_changeid.txt
+++ b/apex/appsearch/synced_jetpack_changeid.txt
@@ -1 +1 @@
-I2decd83fab4c4d58fe38c9970f804046479c942c
+If5fd2bd705d5507d044706701a94b2e1496ef1df
diff --git a/apex/jobscheduler/OWNERS b/apex/jobscheduler/OWNERS
index d004eed..0fe6cdf 100644
--- a/apex/jobscheduler/OWNERS
+++ b/apex/jobscheduler/OWNERS
@@ -1,6 +1,6 @@
 [email protected]
 [email protected]
[email protected]
[email protected]
 [email protected]
 [email protected]
 [email protected]
\ No newline at end of file
diff --git a/apex/jobscheduler/framework/java/android/app/job/OWNERS b/apex/jobscheduler/framework/java/android/app/job/OWNERS
new file mode 100644
index 0000000..b4a45f5
--- /dev/null
+++ b/apex/jobscheduler/framework/java/android/app/job/OWNERS
@@ -0,0 +1,7 @@
+# Bug component: 330738
+
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
index 9ea402c..99a9b97 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
@@ -2044,7 +2044,6 @@
 
                 }
                 maybeRunPendingJobsLocked();
-                // Don't remove JOB_EXPIRED in case one came along while processing the queue.
             }
         }
     }
@@ -2110,6 +2109,15 @@
      * as many as we can.
      */
     private void queueReadyJobsForExecutionLocked() {
+        // This method will check and capture all ready jobs, so we don't need to keep any messages
+        // in the queue.
+        mHandler.removeMessages(MSG_CHECK_JOB_GREEDY);
+        // MSG_CHECK_JOB is a weaker form of _GREEDY. Since we're checking and queueing all ready
+        // jobs, we don't need to keep any MSG_CHECK_JOB messages in the queue.
+        mHandler.removeMessages(MSG_CHECK_JOB);
+        // This method will capture all expired jobs that are ready, so there's no need to keep
+        // the _EXPIRED messages in the queue.
+        mHandler.removeMessages(MSG_JOB_EXPIRED);
         if (DEBUG) {
             Slog.d(TAG, "queuing all ready jobs for execution:");
         }
diff --git a/apex/permission/apex_manifest.json b/apex/permission/apex_manifest.json
index 7960598..6350d54 100644
--- a/apex/permission/apex_manifest.json
+++ b/apex/permission/apex_manifest.json
@@ -1,4 +1,4 @@
 {
   "name": "com.android.permission",
-  "version": 300000000
+  "version": 309999999
 }
diff --git a/apex/statsd/.clang-format b/apex/statsd/.clang-format
deleted file mode 100644
index cead3a0..0000000
--- a/apex/statsd/.clang-format
+++ /dev/null
@@ -1,17 +0,0 @@
-BasedOnStyle: Google
-AllowShortIfStatementsOnASingleLine: true
-AllowShortFunctionsOnASingleLine: false
-AllowShortLoopsOnASingleLine: true
-BinPackArguments: true
-BinPackParameters: true
-ColumnLimit: 100
-CommentPragmas: NOLINT:.*
-ContinuationIndentWidth: 8
-DerivePointerAlignment: false
-IndentWidth: 4
-PointerAlignment: Left
-TabWidth: 4
-AccessModifierOffset: -4
-IncludeCategories:
-  - Regex:    '^"Log\.h"'
-    Priority:    -1
diff --git a/apex/statsd/Android.bp b/apex/statsd/Android.bp
deleted file mode 100644
index f13861e..0000000
--- a/apex/statsd/Android.bp
+++ /dev/null
@@ -1,83 +0,0 @@
-// Copyright (C) 2019 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.
-
-apex {
-    name: "com.android.os.statsd",
-    defaults: ["com.android.os.statsd-defaults"],
-    manifest: "apex_manifest.json",
-}
-
-apex_defaults {
-    jni_libs: [
-        "libstats_jni",
-    ],
-    native_shared_libs: [
-        "libstatspull",
-        "libstatssocket",
-    ],
-    binaries: ["statsd"],
-    java_libs: [
-        "framework-statsd",
-        "service-statsd",
-    ],
-    compile_multilib: "both",
-    prebuilts: ["com.android.os.statsd.init.rc"],
-    name: "com.android.os.statsd-defaults",
-    updatable: true,
-    min_sdk_version: "30",
-    key: "com.android.os.statsd.key",
-    certificate: ":com.android.os.statsd.certificate",
-}
-
-apex_key {
-    name: "com.android.os.statsd.key",
-    public_key: "com.android.os.statsd.avbpubkey",
-    private_key: "com.android.os.statsd.pem",
-}
-
-android_app_certificate {
-    name: "com.android.os.statsd.certificate",
-    // This will use com.android.os.statsd.x509.pem (the cert) and
-    // com.android.os.statsd.pk8 (the private key)
-    certificate: "com.android.os.statsd",
-}
-
-prebuilt_etc {
-    name: "com.android.os.statsd.init.rc",
-    src: "statsd.rc",
-    filename: "init.rc",
-    installable: false,
-}
-
-// JNI library for StatsLog.write
-cc_library_shared {
-    name: "libstats_jni",
-    srcs: ["jni/**/*.cpp"],
-    header_libs: ["libnativehelper_header_only"],
-    shared_libs: [
-        "liblog",  // Has a stable abi - should not be copied into apex.
-        "libstatssocket",
-    ],
-    stl: "libc++_static",
-    cflags: [
-        "-Wall",
-        "-Werror",
-        "-Wextra",
-        "-Wno-unused-parameter",
-    ],
-    apex_available: [
-        "com.android.os.statsd",
-        "test_com.android.os.statsd",
-    ],
-}
diff --git a/apex/statsd/OWNERS b/apex/statsd/OWNERS
deleted file mode 100644
index bed9600..0000000
--- a/apex/statsd/OWNERS
+++ /dev/null
@@ -1,9 +0,0 @@
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
\ No newline at end of file
diff --git a/apex/statsd/TEST_MAPPING b/apex/statsd/TEST_MAPPING
deleted file mode 100644
index 331fe77..0000000
--- a/apex/statsd/TEST_MAPPING
+++ /dev/null
@@ -1,19 +0,0 @@
-{
-  "presubmit" : [
-    {
-      "name" : "FrameworkStatsdTest"
-    },
-    {
-      "name" : "LibStatsPullTests"
-    }
-  ],
-
-  "postsubmit" : [
-    {
-      "name" : "CtsStatsdHostTestCases"
-    },
-    {
-      "name" : "GtsStatsdHostTestCases"
-    }
-  ]
-}
diff --git a/apex/statsd/aidl/Android.bp b/apex/statsd/aidl/Android.bp
deleted file mode 100644
index f66cf7c..0000000
--- a/apex/statsd/aidl/Android.bp
+++ /dev/null
@@ -1,52 +0,0 @@
-//
-// Copyright (C) 2019 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.
-//
-filegroup {
-    name: "framework-statsd-aidl-sources",
-    srcs: ["**/*.aidl"],
-}
-
-aidl_interface {
-    name: "statsd-aidl",
-    unstable: true,
-    srcs: [
-        "android/os/IPendingIntentRef.aidl",
-        "android/os/IPullAtomCallback.aidl",
-        "android/os/IPullAtomResultReceiver.aidl",
-        "android/os/IStatsCompanionService.aidl",
-        "android/os/IStatsd.aidl",
-        "android/os/StatsDimensionsValueParcel.aidl",
-        "android/util/StatsEventParcel.aidl",
-    ],
-    host_supported: true,
-    backend: {
-        java: {
-            enabled: false, // framework-statsd and service-statsd use framework-statsd-aidl-sources
-        },
-        cpp: {
-            enabled: false,
-        },
-        ndk: {
-            enabled: true,
-            apex_available: [
-                // TODO(b/145923087): Remove this once statsd binary is in apex
-                "//apex_available:platform",
-
-                "com.android.os.statsd",
-                "test_com.android.os.statsd",
-            ],
-        },
-    }
-}
diff --git a/apex/statsd/aidl/android/os/IPendingIntentRef.aidl b/apex/statsd/aidl/android/os/IPendingIntentRef.aidl
deleted file mode 100644
index 000a699..0000000
--- a/apex/statsd/aidl/android/os/IPendingIntentRef.aidl
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2019 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.StatsDimensionsValueParcel;
-
-/**
-  * Binder interface to hold a PendingIntent for StatsCompanionService.
-  * {@hide}
-  */
-interface IPendingIntentRef {
-
-    /**
-     * Sends a broadcast to the specified PendingIntent that it should getData now.
-     * This should be only called from StatsCompanionService.
-     */
-     oneway void sendDataBroadcast(long lastReportTimeNs);
-
-    /**
-     * Send a broadcast to the specified PendingIntent notifying it that the list of active configs
-     * has changed. This should be only called from StatsCompanionService.
-     */
-     oneway void sendActiveConfigsChangedBroadcast(in long[] configIds);
-
-     /**
-      * Send a broadcast to the specified PendingIntent, along with the other information
-      * specified. This should only be called from StatsCompanionService.
-      */
-     oneway void sendSubscriberBroadcast(long configUid, long configId, long subscriptionId,
-                                         long subscriptionRuleId, in String[] cookies,
-                                         in StatsDimensionsValueParcel dimensionsValueParcel);
-}
diff --git a/apex/statsd/aidl/android/os/IPullAtomCallback.aidl b/apex/statsd/aidl/android/os/IPullAtomCallback.aidl
deleted file mode 100644
index ff0b97b..0000000
--- a/apex/statsd/aidl/android/os/IPullAtomCallback.aidl
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2019 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.IPullAtomResultReceiver;
-
-/**
-  * Binder interface to pull atoms for the stats service.
-  * {@hide}
-  */
-interface IPullAtomCallback {
-    /**
-     * Initiate a request for a pull for an atom.
-     */
-     oneway void onPullAtom(int atomTag, IPullAtomResultReceiver resultReceiver);
-
-}
diff --git a/apex/statsd/aidl/android/os/IPullAtomResultReceiver.aidl b/apex/statsd/aidl/android/os/IPullAtomResultReceiver.aidl
deleted file mode 100644
index 00d026e..0000000
--- a/apex/statsd/aidl/android/os/IPullAtomResultReceiver.aidl
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2019 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.util.StatsEventParcel;
-
-/**
-  * Binder interface to pull atoms for the stats service.
-  * {@hide}
-  */
-interface IPullAtomResultReceiver {
-
-    /**
-     * Indicate that a pull request for an atom is complete.
-     */
-     oneway void pullFinished(int atomTag, boolean success, in StatsEventParcel[] output);
-
-}
diff --git a/apex/statsd/aidl/android/os/IStatsCompanionService.aidl b/apex/statsd/aidl/android/os/IStatsCompanionService.aidl
deleted file mode 100644
index d56a4bd..0000000
--- a/apex/statsd/aidl/android/os/IStatsCompanionService.aidl
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2017 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;
-
-/**
-  * Binder interface to communicate with the Java-based statistics service helper.
-  * {@hide}
-  */
-interface IStatsCompanionService {
-    /**
-     * Tell statscompanion that stastd is up and running.
-     */
-    oneway void statsdReady();
-
-    /**
-      * Register a repeating alarm for pulling to fire at the given timestamp and every
-      * intervalMs thereafter (in ms since epoch).
-      * If polling alarm had already been registered, it will be replaced by new one.
-      * Uses AlarmManager.setRepeating API, so if the timestamp is in past, alarm fires immediately,
-      * and alarm is inexact.
-      */
-    oneway void setPullingAlarm(long nextPullTimeMs);
-
-    /** Cancel any repeating pulling alarm. */
-    oneway void cancelPullingAlarm();
-
-    /**
-      * Register an alarm when we want to trigger subscribers at the given
-      * timestamp (in ms since epoch).
-      * If an alarm had already been registered, it will be replaced by new one.
-      */
-    oneway void setAlarmForSubscriberTriggering(long timestampMs);
-
-    /** Cancel any alarm for the purpose of subscriber triggering. */
-    oneway void cancelAlarmForSubscriberTriggering();
-
-    /**
-     * Ask StatsCompanionService if the given permission is allowed for a particular process
-     * and user ID. statsd is incapable of doing this check itself because checkCallingPermission
-     * is not currently supported by libbinder_ndk.
-     */
-    boolean checkPermission(String permission, int pid, int uid);
-}
diff --git a/apex/statsd/aidl/android/os/IStatsManagerService.aidl b/apex/statsd/aidl/android/os/IStatsManagerService.aidl
deleted file mode 100644
index b59a97e..0000000
--- a/apex/statsd/aidl/android/os/IStatsManagerService.aidl
+++ /dev/null
@@ -1,136 +0,0 @@
-/**
- * Copyright (c) 2019, 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.app.PendingIntent;
-import android.os.IPullAtomCallback;
-
-/**
-  * Binder interface to communicate with the Java-based statistics service helper.
-  * Contains parcelable objects available only in Java.
-  * {@hide}
-  */
-interface IStatsManagerService {
-
-    /**
-     * Registers the given pending intent for this config key. This intent is invoked when the
-     * memory consumed by the metrics for this configuration approach the pre-defined limits. There
-     * can be at most one listener per config key.
-     *
-     * Requires Manifest.permission.DUMP and Manifest.permission.PACKAGE_USAGE_STATS.
-     */
-    void setDataFetchOperation(long configId, in PendingIntent pendingIntent,
-        in String packageName);
-
-    /**
-     * Removes the data fetch operation for the specified configuration.
-     *
-     * Requires Manifest.permission.DUMP and Manifest.permission.PACKAGE_USAGE_STATS.
-     */
-    void removeDataFetchOperation(long configId, in String packageName);
-
-    /**
-     * Registers the given pending intent for this packagename. This intent is invoked when the
-     * active status of any of the configs sent by this package changes and will contain a list of
-     * config ids that are currently active. It also returns the list of configs that are currently
-     * active. There can be at most one active configs changed listener per package.
-     *
-     * Requires Manifest.permission.DUMP and Manifest.permission.PACKAGE_USAGE_STATS.
-     */
-    long[] setActiveConfigsChangedOperation(in PendingIntent pendingIntent, in String packageName);
-
-    /**
-     * Removes the active configs changed operation for the specified package name.
-     *
-     * Requires Manifest.permission.DUMP and Manifest.permission.PACKAGE_USAGE_STATS.
-     */
-    void removeActiveConfigsChangedOperation(in String packageName);
-
-    /**
-     * Set the PendingIntent to be used when broadcasting subscriber
-     * information to the given subscriberId within the given config.
-     *
-     * Suppose that the calling uid has added a config with key configKey, and that in this config
-     * it is specified that when a particular anomaly is detected, a broadcast should be sent to
-     * a BroadcastSubscriber with id subscriberId. This function links the given pendingIntent with
-     * that subscriberId (for that config), so that this pendingIntent is used to send the broadcast
-     * when the anomaly is detected.
-     *
-     * This function can only be called by the owner (uid) of the config. It must be called each
-     * time statsd starts. Later calls overwrite previous calls; only one PendingIntent is stored.
-     *
-     * Requires Manifest.permission.DUMP and Manifest.permission.PACKAGE_USAGE_STATS.
-     */
-    void setBroadcastSubscriber(long configKey, long subscriberId, in PendingIntent pendingIntent,
-                                in String packageName);
-
-    /**
-     * Undoes setBroadcastSubscriber() for the (configKey, subscriberId) pair.
-     * Any broadcasts associated with subscriberId will henceforth not be sent.
-     * No-op if this (configKey, subscriberId) pair was not associated with an PendingIntent.
-     *
-     * Requires Manifest.permission.DUMP and Manifest.permission.PACKAGE_USAGE_STATS.
-     */
-    void unsetBroadcastSubscriber(long configKey, long subscriberId, in String packageName);
-
-    /**
-     * Returns the most recently registered experiment IDs.
-     *
-     * Requires Manifest.permission.DUMP and Manifest.permission.PACKAGE_USAGE_STATS.
-     */
-    long[] getRegisteredExperimentIds();
-
-    /**
-     * Fetches metadata across statsd. Returns byte array representing wire-encoded proto.
-     *
-     * Requires Manifest.permission.DUMP and Manifest.permission.PACKAGE_USAGE_STATS.
-     */
-    byte[] getMetadata(in String packageName);
-
-    /**
-     * Fetches data for the specified configuration key. Returns a byte array representing proto
-     * wire-encoded of ConfigMetricsReportList.
-     *
-     * Requires Manifest.permission.DUMP and Manifest.permission.PACKAGE_USAGE_STATS.
-     */
-    byte[] getData(in long key, in String packageName);
-
-    /**
-     * Sets a configuration with the specified config id and subscribes to updates for this
-     * configuration id. Broadcasts will be sent if this configuration needs to be collected.
-     * The configuration must be a wire-encoded StatsdConfig. The receiver for this data is
-     * registered in a separate function.
-     *
-     * Requires Manifest.permission.DUMP and Manifest.permission.PACKAGE_USAGE_STATS.
-     */
-    void addConfiguration(in long configId, in byte[] config, in String packageName);
-
-    /**
-     * Removes the configuration with the matching config id. No-op if this config id does not
-     * exist.
-     *
-     * Requires Manifest.permission.DUMP and Manifest.permission.PACKAGE_USAGE_STATS.
-     */
-    void removeConfiguration(in long configId, in String packageName);
-
-    /** Tell StatsManagerService to register a puller for the given atom tag with statsd. */
-    oneway void registerPullAtomCallback(int atomTag, long coolDownMillis, long timeoutMillis,
-            in int[] additiveFields, IPullAtomCallback pullerCallback);
-
-    /** Tell StatsManagerService to unregister the pulller for the given atom tag from statsd. */
-    oneway void unregisterPullAtomCallback(int atomTag);
-}
diff --git a/apex/statsd/aidl/android/os/IStatsd.aidl b/apex/statsd/aidl/android/os/IStatsd.aidl
deleted file mode 100644
index 066412a..0000000
--- a/apex/statsd/aidl/android/os/IStatsd.aidl
+++ /dev/null
@@ -1,230 +0,0 @@
-/**
- * Copyright (c) 2017, 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.IPendingIntentRef;
-import android.os.IPullAtomCallback;
-import android.os.ParcelFileDescriptor;
-
-/**
-  * Binder interface to communicate with the statistics management service.
-  * {@hide}
-  */
-interface IStatsd {
-    /**
-     * Tell the stats daemon that the android system server is up and running.
-     */
-    oneway void systemRunning();
-
-    /**
-     * Tell the stats daemon that the android system has finished booting.
-     */
-    oneway void bootCompleted();
-
-    /**
-     * Tell the stats daemon that the StatsCompanionService is up and running.
-     * Two-way binder call so that caller knows message received.
-     */
-    void statsCompanionReady();
-
-    /**
-     * Tells statsd that it is time to poll some stats. Statsd will be responsible for determing
-     * what stats to poll and initiating the polling.
-     * Two-way binder call so that caller's method (and corresponding wakelocks) will linger.
-     */
-    void informPollAlarmFired();
-
-    /**
-     * Tells statsd that it is time to handle periodic alarms. Statsd will be responsible for
-     * determing what alarm subscriber to trigger.
-     * Two-way binder call so that caller's method (and corresponding wakelocks) will linger.
-     */
-    void informAlarmForSubscriberTriggeringFired();
-
-    /**
-     * Tells statsd that the device is about to shutdown.
-     */
-    void informDeviceShutdown();
-
-    /**
-     * Inform statsd about a file descriptor for a pipe through which we will pipe version
-     * and package information for each uid.
-     * Versions and package information are supplied via UidData proto where info for each app
-     * is captured in its own element of a repeated ApplicationInfo message.
-     */
-    oneway void informAllUidData(in ParcelFileDescriptor fd);
-
-    /**
-     * Inform statsd what the uid, version, version_string, and installer are for one app that was
-     * updated.
-     */
-    oneway void informOnePackage(in String app, in int uid, in long version,
-        in String version_string, in String installer);
-
-    /**
-     * Inform stats that an app was removed.
-     */
-    oneway void informOnePackageRemoved(in String app, in int uid);
-
-    /**
-     * Fetches data for the specified configuration key. Returns a byte array representing proto
-     * wire-encoded of ConfigMetricsReportList.
-     *
-     * Requires Manifest.permission.DUMP.
-     */
-    byte[] getData(in long key, int callingUid);
-
-    /**
-     * Fetches metadata across statsd. Returns byte array representing wire-encoded proto.
-     *
-     * Requires Manifest.permission.DUMP.
-     */
-    byte[] getMetadata();
-
-    /**
-     * Sets a configuration with the specified config id and subscribes to updates for this
-     * configuration key. Broadcasts will be sent if this configuration needs to be collected.
-     * The configuration must be a wire-encoded StatsdConfig. The receiver for this data is
-     * registered in a separate function.
-     *
-     * Requires Manifest.permission.DUMP.
-     */
-    void addConfiguration(in long configId, in byte[] config, in int callingUid);
-
-    /**
-     * Registers the given pending intent for this config key. This intent is invoked when the
-     * memory consumed by the metrics for this configuration approach the pre-defined limits. There
-     * can be at most one listener per config key.
-     *
-     * Requires Manifest.permission.DUMP.
-     */
-    void setDataFetchOperation(long configId, in IPendingIntentRef pendingIntentRef,
-                               int callingUid);
-
-    /**
-     * Removes the data fetch operation for the specified configuration.
-     *
-     * Requires Manifest.permission.DUMP.
-     */
-    void removeDataFetchOperation(long configId, int callingUid);
-
-    /**
-     * Registers the given pending intent for this packagename. This intent is invoked when the
-     * active status of any of the configs sent by this package changes and will contain a list of
-     * config ids that are currently active. It also returns the list of configs that are currently
-     * active. There can be at most one active configs changed listener per package.
-     *
-     * Requires Manifest.permission.DUMP and Manifest.permission.PACKAGE_USAGE_STATS.
-     */
-    long[] setActiveConfigsChangedOperation(in IPendingIntentRef pendingIntentRef, int callingUid);
-
-    /**
-     * Removes the active configs changed operation for the specified package name.
-     *
-     * Requires Manifest.permission.DUMP and Manifest.permission.PACKAGE_USAGE_STATS.
-     */
-    void removeActiveConfigsChangedOperation(int callingUid);
-
-    /**
-     * Removes the configuration with the matching config id. No-op if this config id does not
-     * exist.
-     *
-     * Requires Manifest.permission.DUMP.
-     */
-    void removeConfiguration(in long configId, in int callingUid);
-
-    /**
-     * Set the PendingIntentRef to be used when broadcasting subscriber
-     * information to the given subscriberId within the given config.
-     *
-     * Suppose that the calling uid has added a config with key configId, and that in this config
-     * it is specified that when a particular anomaly is detected, a broadcast should be sent to
-     * a BroadcastSubscriber with id subscriberId. This function links the given pendingIntent with
-     * that subscriberId (for that config), so that this pendingIntent is used to send the broadcast
-     * when the anomaly is detected.
-     *
-     * This function can only be called by the owner (uid) of the config. It must be called each
-     * time statsd starts. Later calls overwrite previous calls; only one pendingIntent is stored.
-     *
-     * Requires Manifest.permission.DUMP.
-     */
-    void setBroadcastSubscriber(long configId, long subscriberId, in IPendingIntentRef pir,
-                                int callingUid);
-
-    /**
-     * Undoes setBroadcastSubscriber() for the (configId, subscriberId) pair.
-     * Any broadcasts associated with subscriberId will henceforth not be sent.
-     * No-op if this (configKey, subscriberId) pair was not associated with an PendingIntentRef.
-     *
-     * Requires Manifest.permission.DUMP.
-     */
-    void unsetBroadcastSubscriber(long configId, long subscriberId, int callingUid);
-
-    /**
-     * Tell the stats daemon that all the pullers registered during boot have been sent.
-     */
-    oneway void allPullersFromBootRegistered();
-
-    /**
-     * Registers a puller callback function that, when invoked, pulls the data
-     * for the specified atom tag.
-     */
-    oneway void registerPullAtomCallback(int uid, int atomTag, long coolDownMillis,
-                                         long timeoutMillis,in int[] additiveFields,
-                                         IPullAtomCallback pullerCallback);
-
-    /**
-     * Registers a puller callback function that, when invoked, pulls the data
-     * for the specified atom tag.
-     *
-     * Enforces the REGISTER_STATS_PULL_ATOM permission.
-     */
-    oneway void registerNativePullAtomCallback(int atomTag, long coolDownMillis, long timeoutMillis,
-                           in int[] additiveFields, IPullAtomCallback pullerCallback);
-
-    /**
-     * Unregisters any pullAtomCallback for the given uid/atom.
-     */
-    oneway void unregisterPullAtomCallback(int uid, int atomTag);
-
-    /**
-     * Unregisters any pullAtomCallback for the given atom + caller.
-     *
-     * Enforces the REGISTER_STATS_PULL_ATOM permission.
-     */
-    oneway void unregisterNativePullAtomCallback(int atomTag);
-
-    /**
-     * The install requires staging.
-     */
-    const int FLAG_REQUIRE_STAGING = 0x01;
-
-    /**
-     * Rollback is enabled with this install.
-     */
-    const int FLAG_ROLLBACK_ENABLED = 0x02;
-
-    /**
-     * Requires low latency monitoring.
-     */
-    const int FLAG_REQUIRE_LOW_LATENCY_MONITOR = 0x04;
-
-    /**
-     * Returns the most recently registered experiment IDs.
-     */
-    long[] getRegisteredExperimentIds();
-}
diff --git a/apex/statsd/aidl/android/os/StatsDimensionsValueParcel.aidl b/apex/statsd/aidl/android/os/StatsDimensionsValueParcel.aidl
deleted file mode 100644
index 05f78d0..0000000
--- a/apex/statsd/aidl/android/os/StatsDimensionsValueParcel.aidl
+++ /dev/null
@@ -1,21 +0,0 @@
-package android.os;
-
-/**
- * @hide
- */
-parcelable StatsDimensionsValueParcel {
-    // Field equals atomTag for top level StatsDimensionsValueParcels or
-    // positions in depth (1-indexed) for lower level parcels.
-    int field;
-
-    // Indicator for which type of value is stored. Should be set to one
-    // of the constants in StatsDimensionsValue.java.
-    int valueType;
-
-    String stringValue;
-    int intValue;
-    long longValue;
-    boolean boolValue;
-    float floatValue;
-    StatsDimensionsValueParcel[] tupleValue;
-}
diff --git a/apex/statsd/aidl/android/util/StatsEventParcel.aidl b/apex/statsd/aidl/android/util/StatsEventParcel.aidl
deleted file mode 100644
index add8bfb..0000000
--- a/apex/statsd/aidl/android/util/StatsEventParcel.aidl
+++ /dev/null
@@ -1,8 +0,0 @@
-package android.util;
-
-/**
- * @hide
- */
-parcelable StatsEventParcel {
-    byte[] buffer;
-}
diff --git a/apex/statsd/apex_manifest.json b/apex/statsd/apex_manifest.json
deleted file mode 100644
index 1d029c6..0000000
--- a/apex/statsd/apex_manifest.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
-  "name": "com.android.os.statsd",
-  "version": 309999900
-}
-
diff --git a/apex/statsd/com.android.os.statsd.avbpubkey b/apex/statsd/com.android.os.statsd.avbpubkey
deleted file mode 100644
index d78af8b..0000000
--- a/apex/statsd/com.android.os.statsd.avbpubkey
+++ /dev/null
Binary files differ
diff --git a/apex/statsd/com.android.os.statsd.pem b/apex/statsd/com.android.os.statsd.pem
deleted file mode 100644
index 558e17f..0000000
--- a/apex/statsd/com.android.os.statsd.pem
+++ /dev/null
@@ -1,51 +0,0 @@
------BEGIN RSA PRIVATE KEY-----
-MIIJKgIBAAKCAgEA893bbpkivKEiNgfknYBSlzC0csaKU/ddBm5Pb4ZFuab+LQSR
-9DDc5JrsmxyrsrvuwL/zAtMbkyYWzEiUxJtx/w0bw8rC90GoPRSCmxyI0ZK8FuPy
-IAQ7UeNfTWZ485mAUaTSasGIfQ3DY4F0P+aUSijeG3NUY02nALHDMqJX7lXR+mL1
-DUYDg05KB0jxQwlYqBeujTPPiAzEqm3PlBoHuan8/qgK2wdQMTVg/fieUD3lupmV
-Wj2dRZgqfBPA16ZbV4Uo0j0bZSf+fQLiXlU2VJGb5i/FQfjLqMKGABDI0MgK7Sc2
-m4ySpV4g4XKDv/vw6Dw4kwWC7mATEVAkH+q6V7uiZeN6a7w30UMtPI8fPaUvAP3L
-VBjCBIv/3m+CKkWcNxOZ3sQBQl5bS05dxcfiVsBvBLYbvQgC+Wy0Sc3b+1pXFT/E
-uAsbZ4CyVsi1+PAdx3h5e2QAyNCXgZDOcvTUyxY6JLTE0LOVHmI4fJEujBex//Oz
-PCRHvC8K+KiljyQWf/NYrLSD3QGYAjVMtQh7yu2yhzWzgBUxyhuv3rY4ATXsN3bJ
-wW4w7/L/RSLSW5+lp/NoJOD9utbsKTyGMHOY6K8JLOmhv3ORoAEmLYlFTI+FqBi9
-AH1HQEKCyh8Z/bYHLUzGWl6FqAMtcnuintv40BbKyt0/D1ItdbSNKmOZ5rkCAwEA
-AQKCAgAY7ll8mRNADYkd1Pi+UVwgMM6B3WJO6z8LZUOhtyxxqmzZ1VnGiShMBrqh
-sPCsuSHTeswxQbvT81TpVZI/91RUKtbn0VbVSFUWyX4AtY4XPtUT0gHy2/vkh0Y6
-93ruDIdd0Wfhmh+GCV4sUhO8ZKpMWpk6XTQHYuzr2UCHcKlkqElrO6qpzLqXNe3D
-iOWBYPc7WBB0RxO0aPnCIq/SCEc55/MBZdSWR80e+sILtNsagPl3djQaoanub3wI
-a0yPv2YfMHHX7H9cfBY8WYsi8bs4MhqqEcAs2m6XtitU3mJpVcooLJYcmOZ1GYZr
-BfYKLouWcnGmNi4IiLHqVzMaQDkEhAZsRaAXCkoVVrFBedLlmLPpiUIQlINF4vxe
-3IcekTKWyMzkU6h+K8T15MU5mLSqeL2Gji1JIwKJno51FZ9uc++pUJVtfYQmNny8
-8RKvQ1hv/S5yLQKgN+VkNbaWlUoMP73dtUe3m/At71/2Dj7xB0KtcgT1lEMrM1GR
-oynJAJLz/d0n5RUUREwkZZMcA4fQVC7Db6vpK69jPiQMShpZ3JKCEjfYLUuN0slt
-FPhjiR175E0vTRuLoIj4kXNwLLswH0c9zqrKM2S92SCxAV3E4JJGKhUZalvT9s1g
-LrPhMCl6CsOES98T87d3RyAIK0iVRCnRUG3bc+8rzyRd4fzkAQKCAQEA/UjmCSm3
-H46t/1w7YBZPew7SFQOAJe81iDzbonc3fNPD2R8lxtD3MwdvrQ5f9fhT4+uveWNr
-dyBX7ppnissyM3LZRN+7BdeIVVeIPVen6Ou9W2i7q18ZoQx9IpRcZEw5tGJFZaGx
-EmyPN4i1K0ccUkGbBvbXXQ/tcG3wElRpBAc5/TQ8vrpUgHll2/MbYhowx6P9uHv5
-thoyG98X+7Fbg8ikzw5GtyuedXfyX1CpJ7yUQVS2PEaOMXOkZdx2bbWRAYYCpsqB
-dMmjs2PsFhZHu6CpLhlocHbfUiRztCUCaMZJPQXFSVmy8QDMvZEdVLvad9Poi8ny
-lmHVRgxaNbAtIQKCAQEA9nscqRaaO7hIX9bOUxcDbI0486Ws4H0hAFApIN+6/LP4
-hkxey3xWArTYWrvSG1d5GkJAdn99ayWzo2PevmJlrhIJiO1QqYBAk+87cnhwSCmB
-kb0sGkNWcc/xNRy7eqdhyCmVhaUnIbORee+cD6qiu/l2BAclTf2ZARFOGXjhQkvt
-cDbc/9ZR467ceXbiTIU34Be4xnNAY1mo59jvwl9eqxgpefYTqPhcZ7OmlDli77Hd
-XuRfuxLZCscv7A9M5Enc2zwOEP5VwRNwYzYtMm2Yh9CQZxNWC7JVh1Gw5MPFzsGl
-sgEdb4WGneN6PPLQHK7NF0f7wYSNnF0i3XSME9MumQKCAQEA0qMbWydr+TyJC0LC
-xigHtUkgAQXGPsXuePxTk4sdhBwAVcKHgg4qZi+a+gpoV4BLE9LfPU4nAwzM08to
-rI5Lk2nBsnt1Z2hVItQGoy0QoK3b7fbti5ktETf3oRhMtcSGgLLxD5ImVjId8Isq
-T3F15hpVOLdzZxtl1Qg4jKXSJ91yplYY5mzC9Yz/3qkQbsdlJcIFsLS5eG3UmkUw
-Bsr6VmA4X1F6Eb6eqwYzdHz6D+fOS36NhxcODaYkY+myO46xptixv8/NVTiTgQ5q
-OfwRb8Iur/3FUzIoioFyD7Bvjn7ITY1NArEsFS0bF9Nk1yDakKiUThyGN/Xojbac
-FuYKwQKCAQEAxOWJ+qU8phJLdowBHC0ZJiEWasRhep9auoZOpJ01IWOfV6EwZLs5
-dkYDQ1Agwoi5DDn6hu7HQM3IV/CS4mF2OnzcMw7ozc7PR53nTkVZ5LuLbuHAlmZO
-avKjDDucpJmLqjtV34IT5X8t6kt3zqgQAbuBBCy1Jz07ebfaPMzsnWpMDcU1/AW4
-OvrX0wweMOSGwzQP/i/ZMsRQAo2w0gQfeuv9Thk+kU99ebXwjx3co//hCEnFE4s1
-6L8/0AJU+VTr4hJyZi7WUDt4HzkLF+qm22/Hux+eMA/Q9R1UAxtFLCpTdAQiAJGY
-/Q3X+1I434DgAwYU3f1Gpq9cB65vq/KamQKCAQEAjIub5wde/ttHlLALvnOXrbqe
-nUIfWHExMzhul/rkr8fFEJwij2nZUuN2EWUGzBWQQoNXw5QKHLZyPsyFUOa/P2BS
-osnffAa+sumL4k36E71xFdTVV5ExyTXZVB49sPmUpivP9gEucFFqDHKjGsF45dBF
-+DZdykLUIv+/jQUzXGkZ5Wv/r52YUNho4EZdwnlJ2so7cxnsYnjW+c1nlp17tkq5
-DfwktkeD9iFzlaZ66vLoO44luaBm+lC3xM2sHinOTwbk0gvhJAIoLfkOYhpmGc8A
-4W/E1OHfVz6xqVDsMBFhRbQpHNkf8XZNqkIoqHVMTaMOJJlM+lb0+A9B8Bm/XA==
------END RSA PRIVATE KEY-----
diff --git a/apex/statsd/com.android.os.statsd.pk8 b/apex/statsd/com.android.os.statsd.pk8
deleted file mode 100644
index 49910f8..0000000
--- a/apex/statsd/com.android.os.statsd.pk8
+++ /dev/null
Binary files differ
diff --git a/apex/statsd/com.android.os.statsd.x509.pem b/apex/statsd/com.android.os.statsd.x509.pem
deleted file mode 100644
index e7b16b2..0000000
--- a/apex/statsd/com.android.os.statsd.x509.pem
+++ /dev/null
@@ -1,30 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIFDTCCAvWgAwIBAgIUCnta1LAl5fMMLLQx//4zWz9A2A8wDQYJKoZIhvcNAQEL
-BQAwFTETMBEGA1UECgwKR29vZ2xlIExMQzAgFw0xOTA4MTIyMjM5MzBaGA80NzU3
-MDcwODIyMzkzMFowFTETMBEGA1UECgwKR29vZ2xlIExMQzCCAiIwDQYJKoZIhvcN
-AQEBBQADggIPADCCAgoCggIBAOranWZ19jkXCF9WIlXv01tUUvLKMHWKV7X9Earw
-cL7/aax0pFbNJutgyBUiOszbR+0T7quZxz6jACu+6y7iaMJnvMluZsfTi+p2UvQt
-y6Ql7ZUOQ7bVluCFIW5hZ+8d9RrLmZdvX1r4YfF6HufDBkAbj+os+y6407OezJAV
-8EATpemc9gsCC4RJZpwzTs1RUXMD4UoNrLZAE8+7iaJZeBxmz0MAPj92pYc9M7/d
-xInzYvOR08/uEpHt8jlMdVgSQS/FaRlIOIqcGBk3cjkjDlpVATQ4Hyjy+IPQPjTD
-bJUmDJiYeBCyY/pYZQvTQjl8s+fvykTsF9Lfb+E+PhZ0+N8pRi7sUSpisZHSiqaN
-W3oxYWc0YQSuzygHHog8HH/azHX5L805g/+Rwfb/cUF9eJgjq0vrkFnsz4UKgKNV
-hHL90mfqpbc2UvJ8VY8BvIjbsHQ77LrBKlqI9VMPorttpTOuwHHJPKsyN972F0Ul
-lRB6CwFE8csVGWXoNaDZWBv7xTDdbdirmlKDNueg9pw6ksYV2Is9Dv8PxmsZvb+4
-oftC/hb4X1Pudn01PPs9Tx44CwHuVLENUwlDEVzG5zNetsv9kAuCYt3VRVF+NYqj
-NAfLbxCKLe25wGzJrZUEJ1YrYIjpUbfwnttEad/9Pu13DAS7HZwn5vwqEKB/1LlT
-NSUXAgMBAAGjUzBRMB0GA1UdDgQWBBSKElkhJSbzgh8+iysye8SrkmJ62DAfBgNV
-HSMEGDAWgBSKElkhJSbzgh8+iysye8SrkmJ62DAPBgNVHRMBAf8EBTADAQH/MA0G
-CSqGSIb3DQEBCwUAA4ICAQANFGnc2wJBrFbh2nzhl06g4TjPKGRCw365vZ1A3T9O
-jXP0lToHDxB33TpKk6d7zszR1uPphQQxgzhSVZB/jx8q4kWSSoKoF9Dlx7h8rAt+
-2TM5DaBvxrwu5mqOALwQuF81wap1Pl2L2fFHvygCm8b+Ci4iS5vcr0axNnp1rK1b
-vUtRWY4mfxTjJYcgeCVUGskqTb+cCxQZ6Icno6VTKajT1FybRmD3KZJaUuLbNEN+
-IE4nGTMG2WZ5Hl2vR8JJp1sYYn8T3ElMAb0MSNFkqsfI+tToEwGsuJDgYEdtEnzf
-lTycQvn5NhrIZRRN3pqSyWpAU7p9mmyTK0PHMz2D/Rtfb7lE692vXzxCmZND51mc
-YXCCoanV6eZZ7Sbqzh60+5QV38hgFBst5l8CcFaWWSFK9nBWdzS5lhs9lmQ4aiYd
-IE0qsNZgMob+TTP1VW39hu4EDjNmOrKfimM9J2tcPZ5QP01DgETPvAsB7vn2Xz9J
-HGt5ntiSV4W2izDP8viQ1M5NvfdBaUhcnNsE6/sxfU0USRs2hrEp1oiqrv4p6V0P
-qOt7C2/YtJzkrxfsHZAxBUSRHa7LwtzgeiJDUivHn94VnAzSAH8MLx6CzDPQ8HWN
-NiZFxTKfMVyjEmbQ2PalHWB8pWtpdEh7X4rzaqhnLBTis3pGssASgo3ArLIYleAU
-+g==
------END CERTIFICATE-----
diff --git a/apex/statsd/framework/Android.bp b/apex/statsd/framework/Android.bp
deleted file mode 100644
index e4299f5..0000000
--- a/apex/statsd/framework/Android.bp
+++ /dev/null
@@ -1,85 +0,0 @@
-// Copyright (C) 2019 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 {
-    default_visibility: [ ":__pkg__" ]
-}
-
-genrule {
-    name: "statslog-statsd-java-gen",
-    tools: ["stats-log-api-gen"],
-    cmd: "$(location stats-log-api-gen) --java $(out) --module statsd" +
-         " --javaPackage com.android.internal.statsd --javaClass StatsdStatsLog",
-    out: ["com/android/internal/statsd/StatsdStatsLog.java"],
-}
-
-java_library_static {
-    name: "statslog-statsd",
-    srcs: [
-        ":statslog-statsd-java-gen",
-    ],
-    visibility: [
-        "//cts/hostsidetests/statsd/apps:__subpackages__",
-        "//vendor:__subpackages__",
-    ],
-}
-
-filegroup {
-    name: "framework-statsd-sources",
-    srcs: [
-        "java/**/*.java",
-        ":framework-statsd-aidl-sources",
-        ":statslog-statsd-java-gen",
-    ],
-    visibility: [
-        "//frameworks/base", // For the "global" stubs.
-        "//frameworks/base/apex/statsd:__subpackages__",
-        "//packages/modules/StatsD/apex:__subpackages__",
-    ],
-}
-java_sdk_library {
-    name: "framework-statsd",
-    defaults: ["framework-module-defaults"],
-    installable: true,
-
-    srcs: [
-        ":framework-statsd-sources",
-    ],
-
-    permitted_packages: [
-        "android.app",
-        "android.os",
-        "android.util",
-        // From :statslog-statsd-java-gen
-        "com.android.internal.statsd",
-    ],
-
-    api_packages: [
-        "android.app",
-        "android.os",
-        "android.util",
-    ],
-
-    hostdex: true, // for hiddenapi check
-
-    impl_library_visibility: [
-        "//frameworks/base/apex/statsd/framework/test:__subpackages__",
-        "//packages/modules/StatsD/apex/framework/test:__subpackages__",
-    ],
-
-    apex_available: [
-        "com.android.os.statsd",
-        "test_com.android.os.statsd",
-    ],
-}
diff --git a/apex/statsd/framework/api/current.txt b/apex/statsd/framework/api/current.txt
deleted file mode 100644
index a655693..0000000
--- a/apex/statsd/framework/api/current.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-// Signature format: 2.0
-package android.util {
-
-  public final class StatsLog {
-    method @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public static boolean logBinaryPushStateChanged(@NonNull String, long, int, int, @NonNull long[]);
-    method public static boolean logEvent(int);
-    method public static boolean logStart(int);
-    method public static boolean logStop(int);
-  }
-
-}
-
diff --git a/apex/statsd/framework/api/module-lib-current.txt b/apex/statsd/framework/api/module-lib-current.txt
deleted file mode 100644
index 8b6e217..0000000
--- a/apex/statsd/framework/api/module-lib-current.txt
+++ /dev/null
@@ -1,10 +0,0 @@
-// Signature format: 2.0
-package android.os {
-
-  public class StatsFrameworkInitializer {
-    method public static void registerServiceWrappers();
-    method public static void setStatsServiceManager(@NonNull android.os.StatsServiceManager);
-  }
-
-}
-
diff --git a/apex/statsd/framework/api/module-lib-removed.txt b/apex/statsd/framework/api/module-lib-removed.txt
deleted file mode 100644
index d802177..0000000
--- a/apex/statsd/framework/api/module-lib-removed.txt
+++ /dev/null
@@ -1 +0,0 @@
-// Signature format: 2.0
diff --git a/apex/statsd/framework/api/removed.txt b/apex/statsd/framework/api/removed.txt
deleted file mode 100644
index d802177..0000000
--- a/apex/statsd/framework/api/removed.txt
+++ /dev/null
@@ -1 +0,0 @@
-// Signature format: 2.0
diff --git a/apex/statsd/framework/api/system-current.txt b/apex/statsd/framework/api/system-current.txt
deleted file mode 100644
index 3ea5724..0000000
--- a/apex/statsd/framework/api/system-current.txt
+++ /dev/null
@@ -1,111 +0,0 @@
-// Signature format: 2.0
-package android.app {
-
-  public final class StatsManager {
-    method @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public void addConfig(long, byte[]) throws android.app.StatsManager.StatsUnavailableException;
-    method @Deprecated @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public boolean addConfiguration(long, byte[]);
-    method @RequiresPermission(android.Manifest.permission.REGISTER_STATS_PULL_ATOM) public void clearPullAtomCallback(int);
-    method @Deprecated @Nullable @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public byte[] getData(long);
-    method @Deprecated @Nullable @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public byte[] getMetadata();
-    method @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public long[] getRegisteredExperimentIds() throws android.app.StatsManager.StatsUnavailableException;
-    method @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public byte[] getReports(long) throws android.app.StatsManager.StatsUnavailableException;
-    method @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public byte[] getStatsMetadata() throws android.app.StatsManager.StatsUnavailableException;
-    method @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public void removeConfig(long) throws android.app.StatsManager.StatsUnavailableException;
-    method @Deprecated @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public boolean removeConfiguration(long);
-    method @NonNull @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public long[] setActiveConfigsChangedOperation(@Nullable android.app.PendingIntent) throws android.app.StatsManager.StatsUnavailableException;
-    method @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public void setBroadcastSubscriber(android.app.PendingIntent, long, long) throws android.app.StatsManager.StatsUnavailableException;
-    method @Deprecated @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public boolean setBroadcastSubscriber(long, long, android.app.PendingIntent);
-    method @Deprecated @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public boolean setDataFetchOperation(long, android.app.PendingIntent);
-    method @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public void setFetchReportsOperation(android.app.PendingIntent, long) throws android.app.StatsManager.StatsUnavailableException;
-    method @RequiresPermission(android.Manifest.permission.REGISTER_STATS_PULL_ATOM) public void setPullAtomCallback(int, @Nullable android.app.StatsManager.PullAtomMetadata, @NonNull java.util.concurrent.Executor, @NonNull android.app.StatsManager.StatsPullAtomCallback);
-    field public static final String ACTION_STATSD_STARTED = "android.app.action.STATSD_STARTED";
-    field public static final String EXTRA_STATS_ACTIVE_CONFIG_KEYS = "android.app.extra.STATS_ACTIVE_CONFIG_KEYS";
-    field public static final String EXTRA_STATS_BROADCAST_SUBSCRIBER_COOKIES = "android.app.extra.STATS_BROADCAST_SUBSCRIBER_COOKIES";
-    field public static final String EXTRA_STATS_CONFIG_KEY = "android.app.extra.STATS_CONFIG_KEY";
-    field public static final String EXTRA_STATS_CONFIG_UID = "android.app.extra.STATS_CONFIG_UID";
-    field public static final String EXTRA_STATS_DIMENSIONS_VALUE = "android.app.extra.STATS_DIMENSIONS_VALUE";
-    field public static final String EXTRA_STATS_SUBSCRIPTION_ID = "android.app.extra.STATS_SUBSCRIPTION_ID";
-    field public static final String EXTRA_STATS_SUBSCRIPTION_RULE_ID = "android.app.extra.STATS_SUBSCRIPTION_RULE_ID";
-    field public static final int PULL_SKIP = 1; // 0x1
-    field public static final int PULL_SUCCESS = 0; // 0x0
-  }
-
-  public static class StatsManager.PullAtomMetadata {
-    method @Nullable public int[] getAdditiveFields();
-    method public long getCoolDownMillis();
-    method public long getTimeoutMillis();
-  }
-
-  public static class StatsManager.PullAtomMetadata.Builder {
-    ctor public StatsManager.PullAtomMetadata.Builder();
-    method @NonNull public android.app.StatsManager.PullAtomMetadata build();
-    method @NonNull public android.app.StatsManager.PullAtomMetadata.Builder setAdditiveFields(@NonNull int[]);
-    method @NonNull public android.app.StatsManager.PullAtomMetadata.Builder setCoolDownMillis(long);
-    method @NonNull public android.app.StatsManager.PullAtomMetadata.Builder setTimeoutMillis(long);
-  }
-
-  public static interface StatsManager.StatsPullAtomCallback {
-    method public int onPullAtom(int, @NonNull java.util.List<android.util.StatsEvent>);
-  }
-
-  public static class StatsManager.StatsUnavailableException extends android.util.AndroidException {
-    ctor public StatsManager.StatsUnavailableException(String);
-    ctor public StatsManager.StatsUnavailableException(String, Throwable);
-  }
-
-}
-
-package android.os {
-
-  public final class StatsDimensionsValue implements android.os.Parcelable {
-    method public int describeContents();
-    method public boolean getBooleanValue();
-    method public int getField();
-    method public float getFloatValue();
-    method public int getIntValue();
-    method public long getLongValue();
-    method public String getStringValue();
-    method public java.util.List<android.os.StatsDimensionsValue> getTupleValueList();
-    method public int getValueType();
-    method public boolean isValueType(int);
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final int BOOLEAN_VALUE_TYPE = 5; // 0x5
-    field @NonNull public static final android.os.Parcelable.Creator<android.os.StatsDimensionsValue> CREATOR;
-    field public static final int FLOAT_VALUE_TYPE = 6; // 0x6
-    field public static final int INT_VALUE_TYPE = 3; // 0x3
-    field public static final int LONG_VALUE_TYPE = 4; // 0x4
-    field public static final int STRING_VALUE_TYPE = 2; // 0x2
-    field public static final int TUPLE_VALUE_TYPE = 7; // 0x7
-  }
-
-}
-
-package android.util {
-
-  public final class StatsEvent {
-    method @NonNull public static android.util.StatsEvent.Builder newBuilder();
-  }
-
-  public static final class StatsEvent.Builder {
-    method @NonNull public android.util.StatsEvent.Builder addBooleanAnnotation(byte, boolean);
-    method @NonNull public android.util.StatsEvent.Builder addIntAnnotation(byte, int);
-    method @NonNull public android.util.StatsEvent build();
-    method @NonNull public android.util.StatsEvent.Builder setAtomId(int);
-    method @NonNull public android.util.StatsEvent.Builder usePooledBuffer();
-    method @NonNull public android.util.StatsEvent.Builder writeAttributionChain(@NonNull int[], @NonNull String[]);
-    method @NonNull public android.util.StatsEvent.Builder writeBoolean(boolean);
-    method @NonNull public android.util.StatsEvent.Builder writeByteArray(@NonNull byte[]);
-    method @NonNull public android.util.StatsEvent.Builder writeFloat(float);
-    method @NonNull public android.util.StatsEvent.Builder writeInt(int);
-    method @NonNull public android.util.StatsEvent.Builder writeKeyValuePairs(@Nullable android.util.SparseIntArray, @Nullable android.util.SparseLongArray, @Nullable android.util.SparseArray<java.lang.String>, @Nullable android.util.SparseArray<java.lang.Float>);
-    method @NonNull public android.util.StatsEvent.Builder writeLong(long);
-    method @NonNull public android.util.StatsEvent.Builder writeString(@NonNull String);
-  }
-
-  public final class StatsLog {
-    method public static void write(@NonNull android.util.StatsEvent);
-    method public static void writeRaw(@NonNull byte[], int);
-  }
-
-}
-
diff --git a/apex/statsd/framework/api/system-removed.txt b/apex/statsd/framework/api/system-removed.txt
deleted file mode 100644
index d802177..0000000
--- a/apex/statsd/framework/api/system-removed.txt
+++ /dev/null
@@ -1 +0,0 @@
-// Signature format: 2.0
diff --git a/apex/statsd/framework/java/android/app/StatsManager.java b/apex/statsd/framework/java/android/app/StatsManager.java
deleted file mode 100644
index 41803cf..0000000
--- a/apex/statsd/framework/java/android/app/StatsManager.java
+++ /dev/null
@@ -1,725 +0,0 @@
-/*
- * Copyright 2017 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 static android.Manifest.permission.DUMP;
-import static android.Manifest.permission.PACKAGE_USAGE_STATS;
-
-import android.annotation.CallbackExecutor;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.RequiresPermission;
-import android.annotation.SystemApi;
-import android.content.Context;
-import android.os.Binder;
-import android.os.IPullAtomCallback;
-import android.os.IPullAtomResultReceiver;
-import android.os.IStatsManagerService;
-import android.os.RemoteException;
-import android.os.StatsFrameworkInitializer;
-import android.util.AndroidException;
-import android.util.Log;
-import android.util.StatsEvent;
-import android.util.StatsEventParcel;
-
-import com.android.internal.annotations.GuardedBy;
-import com.android.internal.annotations.VisibleForTesting;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.Executor;
-
-/**
- * API for statsd clients to send configurations and retrieve data.
- *
- * @hide
- */
-@SystemApi
-public final class StatsManager {
-    private static final String TAG = "StatsManager";
-    private static final boolean DEBUG = false;
-
-    private static final Object sLock = new Object();
-    private final Context mContext;
-
-    @GuardedBy("sLock")
-    private IStatsManagerService mStatsManagerService;
-
-    /**
-     * Long extra of uid that added the relevant stats config.
-     */
-    public static final String EXTRA_STATS_CONFIG_UID = "android.app.extra.STATS_CONFIG_UID";
-    /**
-     * Long extra of the relevant stats config's configKey.
-     */
-    public static final String EXTRA_STATS_CONFIG_KEY = "android.app.extra.STATS_CONFIG_KEY";
-    /**
-     * Long extra of the relevant statsd_config.proto's Subscription.id.
-     */
-    public static final String EXTRA_STATS_SUBSCRIPTION_ID =
-            "android.app.extra.STATS_SUBSCRIPTION_ID";
-    /**
-     * Long extra of the relevant statsd_config.proto's Subscription.rule_id.
-     */
-    public static final String EXTRA_STATS_SUBSCRIPTION_RULE_ID =
-            "android.app.extra.STATS_SUBSCRIPTION_RULE_ID";
-    /**
-     *   List<String> of the relevant statsd_config.proto's BroadcastSubscriberDetails.cookie.
-     *   Obtain using {@link android.content.Intent#getStringArrayListExtra(String)}.
-     */
-    public static final String EXTRA_STATS_BROADCAST_SUBSCRIBER_COOKIES =
-            "android.app.extra.STATS_BROADCAST_SUBSCRIBER_COOKIES";
-    /**
-     * Extra of a {@link android.os.StatsDimensionsValue} representing sliced dimension value
-     * information.
-     */
-    public static final String EXTRA_STATS_DIMENSIONS_VALUE =
-            "android.app.extra.STATS_DIMENSIONS_VALUE";
-    /**
-     * Long array extra of the active configs for the uid that added those configs.
-     */
-    public static final String EXTRA_STATS_ACTIVE_CONFIG_KEYS =
-            "android.app.extra.STATS_ACTIVE_CONFIG_KEYS";
-
-    /**
-     * Broadcast Action: Statsd has started.
-     * Configurations and PendingIntents can now be sent to it.
-     */
-    public static final String ACTION_STATSD_STARTED = "android.app.action.STATSD_STARTED";
-
-    // Pull atom callback return codes.
-    /**
-     * Value indicating that this pull was successful and that the result should be used.
-     *
-     **/
-    public static final int PULL_SUCCESS = 0;
-
-    /**
-     * Value indicating that this pull was unsuccessful and that the result should not be used.
-     **/
-    public static final int PULL_SKIP = 1;
-
-    /**
-     * @hide
-     **/
-    @VisibleForTesting public static final long DEFAULT_COOL_DOWN_MILLIS = 1_000L; // 1 second.
-
-    /**
-     * @hide
-     **/
-    @VisibleForTesting public static final long DEFAULT_TIMEOUT_MILLIS = 2_000L; // 2 seconds.
-
-    /**
-     * Constructor for StatsManagerClient.
-     *
-     * @hide
-     */
-    public StatsManager(Context context) {
-        mContext = context;
-    }
-
-    /**
-     * Adds the given configuration and associates it with the given configKey. If a config with the
-     * given configKey already exists for the caller's uid, it is replaced with the new one.
-     *
-     * @param configKey An arbitrary integer that allows clients to track the configuration.
-     * @param config    Wire-encoded StatsdConfig proto that specifies metrics (and all
-     *                  dependencies eg, conditions and matchers).
-     * @throws StatsUnavailableException if unsuccessful due to failing to connect to stats service
-     * @throws IllegalArgumentException if config is not a wire-encoded StatsdConfig proto
-     */
-    @RequiresPermission(allOf = { DUMP, PACKAGE_USAGE_STATS })
-    public void addConfig(long configKey, byte[] config) throws StatsUnavailableException {
-        synchronized (sLock) {
-            try {
-                IStatsManagerService service = getIStatsManagerServiceLocked();
-                // can throw IllegalArgumentException
-                service.addConfiguration(configKey, config, mContext.getOpPackageName());
-            } catch (RemoteException e) {
-                Log.e(TAG, "Failed to connect to statsmanager when adding configuration");
-                throw new StatsUnavailableException("could not connect", e);
-            } catch (SecurityException e) {
-                throw new StatsUnavailableException(e.getMessage(), e);
-            } catch (IllegalStateException e) {
-                Log.e(TAG, "Failed to addConfig in statsmanager");
-                throw new StatsUnavailableException(e.getMessage(), e);
-            }
-        }
-    }
-
-    // TODO: Temporary for backwards compatibility. Remove.
-    /**
-     * @deprecated Use {@link #addConfig(long, byte[])}
-     */
-    @Deprecated
-    @RequiresPermission(allOf = { DUMP, PACKAGE_USAGE_STATS })
-    public boolean addConfiguration(long configKey, byte[] config) {
-        try {
-            addConfig(configKey, config);
-            return true;
-        } catch (StatsUnavailableException | IllegalArgumentException e) {
-            return false;
-        }
-    }
-
-    /**
-     * Remove a configuration from logging.
-     *
-     * @param configKey Configuration key to remove.
-     * @throws StatsUnavailableException if unsuccessful due to failing to connect to stats service
-     */
-    @RequiresPermission(allOf = { DUMP, PACKAGE_USAGE_STATS })
-    public void removeConfig(long configKey) throws StatsUnavailableException {
-        synchronized (sLock) {
-            try {
-                IStatsManagerService service = getIStatsManagerServiceLocked();
-                service.removeConfiguration(configKey, mContext.getOpPackageName());
-            } catch (RemoteException e) {
-                Log.e(TAG, "Failed to connect to statsmanager when removing configuration");
-                throw new StatsUnavailableException("could not connect", e);
-            } catch (SecurityException e) {
-                throw new StatsUnavailableException(e.getMessage(), e);
-            } catch (IllegalStateException e) {
-                Log.e(TAG, "Failed to removeConfig in statsmanager");
-                throw new StatsUnavailableException(e.getMessage(), e);
-            }
-        }
-    }
-
-    // TODO: Temporary for backwards compatibility. Remove.
-    /**
-     * @deprecated Use {@link #removeConfig(long)}
-     */
-    @Deprecated
-    @RequiresPermission(allOf = { DUMP, PACKAGE_USAGE_STATS })
-    public boolean removeConfiguration(long configKey) {
-        try {
-            removeConfig(configKey);
-            return true;
-        } catch (StatsUnavailableException e) {
-            return false;
-        }
-    }
-
-    /**
-     * Set the PendingIntent to be used when broadcasting subscriber information to the given
-     * subscriberId within the given config.
-     * <p>
-     * Suppose that the calling uid has added a config with key configKey, and that in this config
-     * it is specified that when a particular anomaly is detected, a broadcast should be sent to
-     * a BroadcastSubscriber with id subscriberId. This function links the given pendingIntent with
-     * that subscriberId (for that config), so that this pendingIntent is used to send the broadcast
-     * when the anomaly is detected.
-     * <p>
-     * When statsd sends the broadcast, the PendingIntent will used to send an intent with
-     * information of
-     * {@link #EXTRA_STATS_CONFIG_UID},
-     * {@link #EXTRA_STATS_CONFIG_KEY},
-     * {@link #EXTRA_STATS_SUBSCRIPTION_ID},
-     * {@link #EXTRA_STATS_SUBSCRIPTION_RULE_ID},
-     * {@link #EXTRA_STATS_BROADCAST_SUBSCRIBER_COOKIES}, and
-     * {@link #EXTRA_STATS_DIMENSIONS_VALUE}.
-     * <p>
-     * This function can only be called by the owner (uid) of the config. It must be called each
-     * time statsd starts. The config must have been added first (via {@link #addConfig}).
-     *
-     * @param pendingIntent the PendingIntent to use when broadcasting info to the subscriber
-     *                      associated with the given subscriberId. May be null, in which case
-     *                      it undoes any previous setting of this subscriberId.
-     * @param configKey     The integer naming the config to which this subscriber is attached.
-     * @param subscriberId  ID of the subscriber, as used in the config.
-     * @throws StatsUnavailableException if unsuccessful due to failing to connect to stats service
-     */
-    @RequiresPermission(allOf = { DUMP, PACKAGE_USAGE_STATS })
-    public void setBroadcastSubscriber(
-            PendingIntent pendingIntent, long configKey, long subscriberId)
-            throws StatsUnavailableException {
-        synchronized (sLock) {
-            try {
-                IStatsManagerService service = getIStatsManagerServiceLocked();
-                if (pendingIntent != null) {
-                    service.setBroadcastSubscriber(configKey, subscriberId, pendingIntent,
-                            mContext.getOpPackageName());
-                } else {
-                    service.unsetBroadcastSubscriber(configKey, subscriberId,
-                            mContext.getOpPackageName());
-                }
-            } catch (RemoteException e) {
-                Log.e(TAG, "Failed to connect to statsmanager when adding broadcast subscriber",
-                        e);
-                throw new StatsUnavailableException("could not connect", e);
-            } catch (SecurityException e) {
-                throw new StatsUnavailableException(e.getMessage(), e);
-            }
-        }
-    }
-
-    // TODO: Temporary for backwards compatibility. Remove.
-    /**
-     * @deprecated Use {@link #setBroadcastSubscriber(PendingIntent, long, long)}
-     */
-    @Deprecated
-    @RequiresPermission(allOf = { DUMP, PACKAGE_USAGE_STATS })
-    public boolean setBroadcastSubscriber(
-            long configKey, long subscriberId, PendingIntent pendingIntent) {
-        try {
-            setBroadcastSubscriber(pendingIntent, configKey, subscriberId);
-            return true;
-        } catch (StatsUnavailableException e) {
-            return false;
-        }
-    }
-
-    /**
-     * Registers the operation that is called to retrieve the metrics data. This must be called
-     * each time statsd starts. The config must have been added first (via {@link #addConfig},
-     * although addConfig could have been called on a previous boot). This operation allows
-     * statsd to send metrics data whenever statsd determines that the metrics in memory are
-     * approaching the memory limits. The fetch operation should call {@link #getReports} to fetch
-     * the data, which also deletes the retrieved metrics from statsd's memory.
-     *
-     * @param pendingIntent the PendingIntent to use when broadcasting info to the subscriber
-     *                      associated with the given subscriberId. May be null, in which case
-     *                      it removes any associated pending intent with this configKey.
-     * @param configKey     The integer naming the config to which this operation is attached.
-     * @throws StatsUnavailableException if unsuccessful due to failing to connect to stats service
-     */
-    @RequiresPermission(allOf = { DUMP, PACKAGE_USAGE_STATS })
-    public void setFetchReportsOperation(PendingIntent pendingIntent, long configKey)
-            throws StatsUnavailableException {
-        synchronized (sLock) {
-            try {
-                IStatsManagerService service = getIStatsManagerServiceLocked();
-                if (pendingIntent == null) {
-                    service.removeDataFetchOperation(configKey, mContext.getOpPackageName());
-                } else {
-                    service.setDataFetchOperation(configKey, pendingIntent,
-                            mContext.getOpPackageName());
-                }
-
-            } catch (RemoteException e) {
-                Log.e(TAG, "Failed to connect to statsmanager when registering data listener.");
-                throw new StatsUnavailableException("could not connect", e);
-            } catch (SecurityException e) {
-                throw new StatsUnavailableException(e.getMessage(), e);
-            }
-        }
-    }
-
-    /**
-     * Registers the operation that is called whenever there is a change in which configs are
-     * active. This must be called each time statsd starts. This operation allows
-     * statsd to inform clients that they should pull data of the configs that are currently
-     * active. The activeConfigsChangedOperation should set periodic alarms to pull data of configs
-     * that are active and stop pulling data of configs that are no longer active.
-     *
-     * @param pendingIntent the PendingIntent to use when broadcasting info to the subscriber
-     *                      associated with the given subscriberId. May be null, in which case
-     *                      it removes any associated pending intent for this client.
-     * @return A list of configs that are currently active for this client. If the pendingIntent is
-     *         null, this will be an empty list.
-     * @throws StatsUnavailableException if unsuccessful due to failing to connect to stats service
-     */
-    @RequiresPermission(allOf = { DUMP, PACKAGE_USAGE_STATS })
-    public @NonNull long[] setActiveConfigsChangedOperation(@Nullable PendingIntent pendingIntent)
-            throws StatsUnavailableException {
-        synchronized (sLock) {
-            try {
-                IStatsManagerService service = getIStatsManagerServiceLocked();
-                if (pendingIntent == null) {
-                    service.removeActiveConfigsChangedOperation(mContext.getOpPackageName());
-                    return new long[0];
-                } else {
-                    return service.setActiveConfigsChangedOperation(pendingIntent,
-                            mContext.getOpPackageName());
-                }
-
-            } catch (RemoteException e) {
-                Log.e(TAG, "Failed to connect to statsmanager "
-                        + "when registering active configs listener.");
-                throw new StatsUnavailableException("could not connect", e);
-            } catch (SecurityException e) {
-                throw new StatsUnavailableException(e.getMessage(), e);
-            }
-        }
-    }
-
-    // TODO: Temporary for backwards compatibility. Remove.
-    /**
-     * @deprecated Use {@link #setFetchReportsOperation(PendingIntent, long)}
-     */
-    @Deprecated
-    @RequiresPermission(allOf = { DUMP, PACKAGE_USAGE_STATS })
-    public boolean setDataFetchOperation(long configKey, PendingIntent pendingIntent) {
-        try {
-            setFetchReportsOperation(pendingIntent, configKey);
-            return true;
-        } catch (StatsUnavailableException e) {
-            return false;
-        }
-    }
-
-    /**
-     * Request the data collected for the given configKey.
-     * This getter is destructive - it also clears the retrieved metrics from statsd's memory.
-     *
-     * @param configKey Configuration key to retrieve data from.
-     * @return Serialized ConfigMetricsReportList proto.
-     * @throws StatsUnavailableException if unsuccessful due to failing to connect to stats service
-     */
-    @RequiresPermission(allOf = { DUMP, PACKAGE_USAGE_STATS })
-    public byte[] getReports(long configKey) throws StatsUnavailableException {
-        synchronized (sLock) {
-            try {
-                IStatsManagerService service = getIStatsManagerServiceLocked();
-                return service.getData(configKey, mContext.getOpPackageName());
-            } catch (RemoteException e) {
-                Log.e(TAG, "Failed to connect to statsmanager when getting data");
-                throw new StatsUnavailableException("could not connect", e);
-            } catch (SecurityException e) {
-                throw new StatsUnavailableException(e.getMessage(), e);
-            } catch (IllegalStateException e) {
-                Log.e(TAG, "Failed to getReports in statsmanager");
-                throw new StatsUnavailableException(e.getMessage(), e);
-            }
-        }
-    }
-
-    // TODO: Temporary for backwards compatibility. Remove.
-    /**
-     * @deprecated Use {@link #getReports(long)}
-     */
-    @Deprecated
-    @RequiresPermission(allOf = { DUMP, PACKAGE_USAGE_STATS })
-    public @Nullable byte[] getData(long configKey) {
-        try {
-            return getReports(configKey);
-        } catch (StatsUnavailableException e) {
-            return null;
-        }
-    }
-
-    /**
-     * Clients can request metadata for statsd. Will contain stats across all configurations but not
-     * the actual metrics themselves (metrics must be collected via {@link #getReports(long)}.
-     * This getter is not destructive and will not reset any metrics/counters.
-     *
-     * @return Serialized StatsdStatsReport proto.
-     * @throws StatsUnavailableException if unsuccessful due to failing to connect to stats service
-     */
-    @RequiresPermission(allOf = { DUMP, PACKAGE_USAGE_STATS })
-    public byte[] getStatsMetadata() throws StatsUnavailableException {
-        synchronized (sLock) {
-            try {
-                IStatsManagerService service = getIStatsManagerServiceLocked();
-                return service.getMetadata(mContext.getOpPackageName());
-            } catch (RemoteException e) {
-                Log.e(TAG, "Failed to connect to statsmanager when getting metadata");
-                throw new StatsUnavailableException("could not connect", e);
-            } catch (SecurityException e) {
-                throw new StatsUnavailableException(e.getMessage(), e);
-            } catch (IllegalStateException e) {
-                Log.e(TAG, "Failed to getStatsMetadata in statsmanager");
-                throw new StatsUnavailableException(e.getMessage(), e);
-            }
-        }
-    }
-
-    // TODO: Temporary for backwards compatibility. Remove.
-    /**
-     * @deprecated Use {@link #getStatsMetadata()}
-     */
-    @Deprecated
-    @RequiresPermission(allOf = { DUMP, PACKAGE_USAGE_STATS })
-    public @Nullable byte[] getMetadata() {
-        try {
-            return getStatsMetadata();
-        } catch (StatsUnavailableException e) {
-            return null;
-        }
-    }
-
-    /**
-     * Returns the experiments IDs registered with statsd, or an empty array if there aren't any.
-     *
-     * @throws StatsUnavailableException if unsuccessful due to failing to connect to stats service
-     */
-    @RequiresPermission(allOf = {DUMP, PACKAGE_USAGE_STATS})
-    public long[] getRegisteredExperimentIds()
-            throws StatsUnavailableException {
-        synchronized (sLock) {
-            try {
-                IStatsManagerService service = getIStatsManagerServiceLocked();
-                return service.getRegisteredExperimentIds();
-            } catch (RemoteException e) {
-                if (DEBUG) {
-                    Log.d(TAG,
-                            "Failed to connect to StatsManagerService when getting "
-                                    + "registered experiment IDs");
-                }
-                throw new StatsUnavailableException("could not connect", e);
-            } catch (IllegalStateException e) {
-                Log.e(TAG, "Failed to getRegisteredExperimentIds in statsmanager");
-                throw new StatsUnavailableException(e.getMessage(), e);
-            }
-        }
-    }
-
-    /**
-     * Sets a callback for an atom when that atom is to be pulled. The stats service will
-     * invoke pullData in the callback when the stats service determines that this atom needs to be
-     * pulled. This method should not be called by third-party apps.
-     *
-     * @param atomTag           The tag of the atom for this puller callback.
-     * @param metadata          Optional metadata specifying the timeout, cool down time, and
-     *                          additive fields for mapping isolated to host uids.
-     * @param executor          The executor in which to run the callback.
-     * @param callback          The callback to be invoked when the stats service pulls the atom.
-     *
-     */
-    @RequiresPermission(android.Manifest.permission.REGISTER_STATS_PULL_ATOM)
-    public void setPullAtomCallback(int atomTag, @Nullable PullAtomMetadata metadata,
-            @NonNull @CallbackExecutor Executor executor,
-            @NonNull StatsPullAtomCallback callback) {
-        long coolDownMillis =
-                metadata == null ? DEFAULT_COOL_DOWN_MILLIS : metadata.mCoolDownMillis;
-        long timeoutMillis = metadata == null ? DEFAULT_TIMEOUT_MILLIS : metadata.mTimeoutMillis;
-        int[] additiveFields = metadata == null ? new int[0] : metadata.mAdditiveFields;
-        if (additiveFields == null) {
-            additiveFields = new int[0];
-        }
-
-        synchronized (sLock) {
-            try {
-                IStatsManagerService service = getIStatsManagerServiceLocked();
-                PullAtomCallbackInternal rec =
-                    new PullAtomCallbackInternal(atomTag, callback, executor);
-                service.registerPullAtomCallback(
-                        atomTag, coolDownMillis, timeoutMillis, additiveFields, rec);
-            } catch (RemoteException e) {
-                throw new RuntimeException("Unable to register pull callback", e);
-            }
-        }
-    }
-
-    /**
-     * Clears a callback for an atom when that atom is to be pulled. Note that any ongoing
-     * pulls will still occur. This method should not be called by third-party apps.
-     *
-     * @param atomTag           The tag of the atom of which to unregister
-     *
-     */
-    @RequiresPermission(android.Manifest.permission.REGISTER_STATS_PULL_ATOM)
-    public void clearPullAtomCallback(int atomTag) {
-        synchronized (sLock) {
-            try {
-                IStatsManagerService service = getIStatsManagerServiceLocked();
-                service.unregisterPullAtomCallback(atomTag);
-            } catch (RemoteException e) {
-                throw new RuntimeException("Unable to unregister pull atom callback");
-            }
-        }
-    }
-
-    private static class PullAtomCallbackInternal extends IPullAtomCallback.Stub {
-        public final int mAtomId;
-        public final StatsPullAtomCallback mCallback;
-        public final Executor mExecutor;
-
-        PullAtomCallbackInternal(int atomId, StatsPullAtomCallback callback, Executor executor) {
-            mAtomId = atomId;
-            mCallback = callback;
-            mExecutor = executor;
-        }
-
-        @Override
-        public void onPullAtom(int atomTag, IPullAtomResultReceiver resultReceiver) {
-            final long token = Binder.clearCallingIdentity();
-            try {
-                mExecutor.execute(() -> {
-                    List<StatsEvent> data = new ArrayList<>();
-                    int successInt = mCallback.onPullAtom(atomTag, data);
-                    boolean success = successInt == PULL_SUCCESS;
-                    StatsEventParcel[] parcels = new StatsEventParcel[data.size()];
-                    for (int i = 0; i < data.size(); i++) {
-                        parcels[i] = new StatsEventParcel();
-                        parcels[i].buffer = data.get(i).getBytes();
-                    }
-                    try {
-                        resultReceiver.pullFinished(atomTag, success, parcels);
-                    } catch (RemoteException e) {
-                        Log.w(TAG, "StatsPullResultReceiver failed for tag " + mAtomId
-                                + " due to TransactionTooLarge. Calling pullFinish with no data");
-                        StatsEventParcel[] emptyData = new StatsEventParcel[0];
-                        try {
-                            resultReceiver.pullFinished(atomTag, /*success=*/false, emptyData);
-                        } catch (RemoteException nestedException) {
-                            Log.w(TAG, "StatsPullResultReceiver failed for tag " + mAtomId
-                                    + " with empty payload");
-                        }
-                    }
-                });
-            } finally {
-                Binder.restoreCallingIdentity(token);
-            }
-        }
-    }
-
-    /**
-     * Metadata required for registering a StatsPullAtomCallback.
-     * All fields are optional, and defaults will be used for fields that are unspecified.
-     *
-     */
-    public static class PullAtomMetadata {
-        private final long mCoolDownMillis;
-        private final long mTimeoutMillis;
-        private final int[] mAdditiveFields;
-
-        // Private Constructor for builder
-        private PullAtomMetadata(long coolDownMillis, long timeoutMillis, int[] additiveFields) {
-            mCoolDownMillis = coolDownMillis;
-            mTimeoutMillis = timeoutMillis;
-            mAdditiveFields = additiveFields;
-        }
-
-        /**
-         *  Builder for PullAtomMetadata.
-         */
-        public static class Builder {
-            private long mCoolDownMillis;
-            private long mTimeoutMillis;
-            private int[] mAdditiveFields;
-
-            /**
-             * Returns a new PullAtomMetadata.Builder object for constructing PullAtomMetadata for
-             * StatsManager#registerPullAtomCallback
-             */
-            public Builder() {
-                mCoolDownMillis = DEFAULT_COOL_DOWN_MILLIS;
-                mTimeoutMillis = DEFAULT_TIMEOUT_MILLIS;
-                mAdditiveFields = null;
-            }
-
-            /**
-             * Set the cool down time of the pull in milliseconds. If two successive pulls are
-             * issued within the cool down, a cached version of the first pull will be used for the
-             * second pull. The minimum allowed cool down is 1 second.
-             */
-            @NonNull
-            public Builder setCoolDownMillis(long coolDownMillis) {
-                mCoolDownMillis = coolDownMillis;
-                return this;
-            }
-
-            /**
-             * Set the maximum time the pull can take in milliseconds. The maximum allowed timeout
-             * is 10 seconds.
-             */
-            @NonNull
-            public Builder setTimeoutMillis(long timeoutMillis) {
-                mTimeoutMillis = timeoutMillis;
-                return this;
-            }
-
-            /**
-             * Set the additive fields of this pulled atom.
-             *
-             * This is only applicable for atoms which have a uid field. When tasks are run in
-             * isolated processes, the data will be attributed to the host uid. Additive fields
-             * will be combined when the non-additive fields are the same.
-             */
-            @NonNull
-            public Builder setAdditiveFields(@NonNull int[] additiveFields) {
-                mAdditiveFields = additiveFields;
-                return this;
-            }
-
-            /**
-             * Builds and returns a PullAtomMetadata object with the values set in the builder and
-             * defaults for unset fields.
-             */
-            @NonNull
-            public PullAtomMetadata build() {
-                return new PullAtomMetadata(mCoolDownMillis, mTimeoutMillis, mAdditiveFields);
-            }
-        }
-
-        /**
-         * Return the cool down time of this pull in milliseconds.
-         */
-        public long getCoolDownMillis() {
-            return mCoolDownMillis;
-        }
-
-        /**
-         * Return the maximum amount of time this pull can take in milliseconds.
-         */
-        public long getTimeoutMillis() {
-            return mTimeoutMillis;
-        }
-
-        /**
-         * Return the additive fields of this pulled atom.
-         *
-         * This is only applicable for atoms that have a uid field. When tasks are run in
-         * isolated processes, the data will be attributed to the host uid. Additive fields
-         * will be combined when the non-additive fields are the same.
-         */
-        @Nullable
-        public int[] getAdditiveFields() {
-            return mAdditiveFields;
-        }
-    }
-
-    /**
-     * Callback interface for pulling atoms requested by the stats service.
-     *
-     */
-    public interface StatsPullAtomCallback {
-        /**
-         * Pull data for the specified atom tag, filling in the provided list of StatsEvent data.
-         * @return {@link #PULL_SUCCESS} if the pull was successful, or {@link #PULL_SKIP} if not.
-         */
-        int onPullAtom(int atomTag, @NonNull List<StatsEvent> data);
-    }
-
-    @GuardedBy("sLock")
-    private IStatsManagerService getIStatsManagerServiceLocked() {
-        if (mStatsManagerService != null) {
-            return mStatsManagerService;
-        }
-        mStatsManagerService = IStatsManagerService.Stub.asInterface(
-                StatsFrameworkInitializer
-                .getStatsServiceManager()
-                .getStatsManagerServiceRegisterer()
-                .get());
-        return mStatsManagerService;
-    }
-
-    /**
-     * Exception thrown when communication with the stats service fails (eg if it is not available).
-     * This might be thrown early during boot before the stats service has started or if it crashed.
-     */
-    public static class StatsUnavailableException extends AndroidException {
-        public StatsUnavailableException(String reason) {
-            super("Failed to connect to statsd: " + reason);
-        }
-
-        public StatsUnavailableException(String reason, Throwable e) {
-            super("Failed to connect to statsd: " + reason, e);
-        }
-    }
-}
diff --git a/apex/statsd/framework/java/android/os/StatsDimensionsValue.java b/apex/statsd/framework/java/android/os/StatsDimensionsValue.java
deleted file mode 100644
index 7d9349c..0000000
--- a/apex/statsd/framework/java/android/os/StatsDimensionsValue.java
+++ /dev/null
@@ -1,317 +0,0 @@
-/*
- * Copyright 2018 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.annotation.SystemApi;
-import android.util.Log;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Container for statsd dimension value information, corresponding to a
- * stats_log.proto's DimensionValue.
- *
- * This consists of a field (an int representing a statsd atom field)
- * and a value (which may be one of a number of types).
- *
- * <p>
- * Only a single value is held, and it is necessarily one of the following types:
- * {@link String}, int, long, boolean, float,
- * or tuple (i.e. {@link List} of {@code StatsDimensionsValue}).
- *
- * The type of value held can be retrieved using {@link #getValueType()}, which returns one of the
- * following ints, depending on the type of value:
- * <ul>
- *  <li>{@link #STRING_VALUE_TYPE}</li>
- *  <li>{@link #INT_VALUE_TYPE}</li>
- *  <li>{@link #LONG_VALUE_TYPE}</li>
- *  <li>{@link #BOOLEAN_VALUE_TYPE}</li>
- *  <li>{@link #FLOAT_VALUE_TYPE}</li>
- *  <li>{@link #TUPLE_VALUE_TYPE}</li>
- * </ul>
- * Alternatively, this can be determined using {@link #isValueType(int)} with one of these constants
- * as a parameter.
- * The value itself can be retrieved using the correct get...Value() function for its type.
- *
- * <p>
- * The field is always an int, and always exists; it can be obtained using {@link #getField()}.
- *
- *
- * @hide
- */
-@SystemApi
-public final class StatsDimensionsValue implements Parcelable {
-    private static final String TAG = "StatsDimensionsValue";
-
-    // Values of the value type correspond to stats_log.proto's DimensionValue fields.
-    // Keep constants in sync with frameworks/base/cmds/statsd/src/HashableDimensionKey.cpp.
-    /** Indicates that this holds a String. */
-    public static final int STRING_VALUE_TYPE = 2;
-    /** Indicates that this holds an int. */
-    public static final int INT_VALUE_TYPE = 3;
-    /** Indicates that this holds a long. */
-    public static final int LONG_VALUE_TYPE = 4;
-    /** Indicates that this holds a boolean. */
-    public static final int BOOLEAN_VALUE_TYPE = 5;
-    /** Indicates that this holds a float. */
-    public static final int FLOAT_VALUE_TYPE = 6;
-    /** Indicates that this holds a List of StatsDimensionsValues. */
-    public static final int TUPLE_VALUE_TYPE = 7;
-
-    private final StatsDimensionsValueParcel mInner;
-
-    /**
-     * Creates a {@code StatsDimensionValue} from a parcel.
-     *
-     * @hide
-     */
-    public StatsDimensionsValue(Parcel in) {
-        mInner = StatsDimensionsValueParcel.CREATOR.createFromParcel(in);
-    }
-
-    /**
-     * Creates a {@code StatsDimensionsValue} from a StatsDimensionsValueParcel
-     *
-     * @hide
-     */
-    public StatsDimensionsValue(StatsDimensionsValueParcel parcel) {
-        mInner = parcel;
-    }
-
-    /**
-     * Return the field, i.e. the tag of a statsd atom.
-     *
-     * @return the field
-     */
-    public int getField() {
-        return mInner.field;
-    }
-
-    /**
-     * Retrieve the String held, if any.
-     *
-     * @return the {@link String} held if {@link #getValueType()} == {@link #STRING_VALUE_TYPE},
-     *         null otherwise
-     */
-    public String getStringValue() {
-        if (mInner.valueType == STRING_VALUE_TYPE) {
-            return mInner.stringValue;
-        } else {
-            Log.w(TAG, "Value type is " + getValueTypeAsString() + ", not string.");
-            return null;
-        }
-    }
-
-    /**
-     * Retrieve the int held, if any.
-     *
-     * @return the int held if {@link #getValueType()} == {@link #INT_VALUE_TYPE}, 0 otherwise
-     */
-    public int getIntValue() {
-        if (mInner.valueType == INT_VALUE_TYPE) {
-            return mInner.intValue;
-        } else {
-            Log.w(TAG, "Value type is " + getValueTypeAsString() + ", not int.");
-            return 0;
-        }
-    }
-
-    /**
-     * Retrieve the long held, if any.
-     *
-     * @return the long held if {@link #getValueType()} == {@link #LONG_VALUE_TYPE}, 0 otherwise
-     */
-    public long getLongValue() {
-        if (mInner.valueType == LONG_VALUE_TYPE) {
-            return mInner.longValue;
-        } else {
-            Log.w(TAG, "Value type is " + getValueTypeAsString() + ", not long.");
-            return 0;
-        }
-    }
-
-    /**
-     * Retrieve the boolean held, if any.
-     *
-     * @return the boolean held if {@link #getValueType()} == {@link #BOOLEAN_VALUE_TYPE},
-     *         false otherwise
-     */
-    public boolean getBooleanValue() {
-        if (mInner.valueType == BOOLEAN_VALUE_TYPE) {
-            return mInner.boolValue;
-        } else {
-            Log.w(TAG, "Value type is " + getValueTypeAsString() + ", not boolean.");
-            return false;
-        }
-    }
-
-    /**
-     * Retrieve the float held, if any.
-     *
-     * @return the float held if {@link #getValueType()} == {@link #FLOAT_VALUE_TYPE}, 0 otherwise
-     */
-    public float getFloatValue() {
-        if (mInner.valueType == FLOAT_VALUE_TYPE) {
-            return mInner.floatValue;
-        } else {
-            Log.w(TAG, "Value type is " + getValueTypeAsString() + ", not float.");
-            return 0;
-        }
-    }
-
-    /**
-     * Retrieve the tuple, in the form of a {@link List} of {@link StatsDimensionsValue}, held,
-     * if any.
-     *
-     * @return the {@link List} of {@link StatsDimensionsValue} held
-     *         if {@link #getValueType()} == {@link #TUPLE_VALUE_TYPE},
-     *         null otherwise
-     */
-    public List<StatsDimensionsValue> getTupleValueList() {
-        if (mInner.valueType == TUPLE_VALUE_TYPE) {
-            int length = (mInner.tupleValue == null) ? 0 : mInner.tupleValue.length;
-            List<StatsDimensionsValue> tupleValues = new ArrayList<>(length);
-            for (int i = 0; i < length; i++) {
-                tupleValues.add(new StatsDimensionsValue(mInner.tupleValue[i]));
-            }
-            return tupleValues;
-        } else {
-            Log.w(TAG, "Value type is " + getValueTypeAsString() + ", not tuple.");
-            return null;
-        }
-    }
-
-    /**
-     * Returns the constant representing the type of value stored, namely one of
-     * <ul>
-     *   <li>{@link #STRING_VALUE_TYPE}</li>
-     *   <li>{@link #INT_VALUE_TYPE}</li>
-     *   <li>{@link #LONG_VALUE_TYPE}</li>
-     *   <li>{@link #BOOLEAN_VALUE_TYPE}</li>
-     *   <li>{@link #FLOAT_VALUE_TYPE}</li>
-     *   <li>{@link #TUPLE_VALUE_TYPE}</li>
-     * </ul>
-     *
-     * @return the constant representing the type of value stored
-     */
-    public int getValueType() {
-        return mInner.valueType;
-    }
-
-    /**
-     * Returns whether the type of value stored is equal to the given type.
-     *
-     * @param valueType int representing the type of value stored, as used in {@link #getValueType}
-     * @return true if {@link #getValueType()} is equal to {@code valueType}.
-     */
-    public boolean isValueType(int valueType) {
-        return mInner.valueType == valueType;
-    }
-
-    /**
-     * Returns a String representing the information in this StatsDimensionValue.
-     * No guarantees are made about the format of this String.
-     *
-     * @return String representation
-     *
-     * @hide
-     */
-    // Follows the format of statsd's dimension.h toString.
-    public String toString() {
-        StringBuilder sb = new StringBuilder();
-        sb.append(mInner.field);
-        sb.append(":");
-        switch (mInner.valueType) {
-            case STRING_VALUE_TYPE:
-                sb.append(mInner.stringValue);
-                break;
-            case INT_VALUE_TYPE:
-                sb.append(String.valueOf(mInner.intValue));
-                break;
-            case LONG_VALUE_TYPE:
-                sb.append(String.valueOf(mInner.longValue));
-                break;
-            case BOOLEAN_VALUE_TYPE:
-                sb.append(String.valueOf(mInner.boolValue));
-                break;
-            case FLOAT_VALUE_TYPE:
-                sb.append(String.valueOf(mInner.floatValue));
-                break;
-            case TUPLE_VALUE_TYPE:
-                sb.append("{");
-                int length = (mInner.tupleValue == null) ? 0 : mInner.tupleValue.length;
-                for (int i = 0; i < length; i++) {
-                    StatsDimensionsValue child = new StatsDimensionsValue(mInner.tupleValue[i]);
-                    sb.append(child.toString());
-                    sb.append("|");
-                }
-                sb.append("}");
-                break;
-            default:
-                Log.w(TAG, "Incorrect value type");
-                break;
-        }
-        return sb.toString();
-    }
-
-    /**
-     * Parcelable Creator for StatsDimensionsValue.
-     */
-    public static final @android.annotation.NonNull
-            Parcelable.Creator<StatsDimensionsValue> CREATOR = new
-            Parcelable.Creator<StatsDimensionsValue>() {
-                public StatsDimensionsValue createFromParcel(Parcel in) {
-                    return new StatsDimensionsValue(in);
-                }
-
-                public StatsDimensionsValue[] newArray(int size) {
-                    return new StatsDimensionsValue[size];
-                }
-            };
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(Parcel out, int flags) {
-        mInner.writeToParcel(out, flags);
-    }
-
-    /**
-     * Returns a string representation of the type of value stored.
-     */
-    private String getValueTypeAsString() {
-        switch (mInner.valueType) {
-            case STRING_VALUE_TYPE:
-                return "string";
-            case INT_VALUE_TYPE:
-                return "int";
-            case LONG_VALUE_TYPE:
-                return "long";
-            case BOOLEAN_VALUE_TYPE:
-                return "boolean";
-            case FLOAT_VALUE_TYPE:
-                return "float";
-            case TUPLE_VALUE_TYPE:
-                return "tuple";
-            default:
-                return "unknown";
-        }
-    }
-}
diff --git a/apex/statsd/framework/java/android/os/StatsFrameworkInitializer.java b/apex/statsd/framework/java/android/os/StatsFrameworkInitializer.java
deleted file mode 100644
index 8dc9123..0000000
--- a/apex/statsd/framework/java/android/os/StatsFrameworkInitializer.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.os;
-
-import android.annotation.NonNull;
-import android.annotation.SystemApi;
-import android.annotation.SystemApi.Client;
-import android.app.StatsManager;
-import android.app.SystemServiceRegistry;
-import android.content.Context;
-
-/**
- * Class for performing registration for all stats services
- *
- * @hide
- */
-@SystemApi(client = Client.MODULE_LIBRARIES)
-public class StatsFrameworkInitializer {
-    private StatsFrameworkInitializer() {
-    }
-
-    private static volatile StatsServiceManager sStatsServiceManager;
-
-    /**
-     * Sets an instance of {@link StatsServiceManager} that allows
-     * the statsd mainline module to register/obtain stats binder services. This is called
-     * by the platform during the system initialization.
-     *
-     * @param statsServiceManager instance of {@link StatsServiceManager} that allows
-     * the statsd mainline module to register/obtain statsd binder services.
-     */
-    public static void setStatsServiceManager(
-            @NonNull StatsServiceManager statsServiceManager) {
-        if (sStatsServiceManager != null) {
-            throw new IllegalStateException("setStatsServiceManager called twice!");
-        }
-
-        if (statsServiceManager == null) {
-            throw new NullPointerException("statsServiceManager is null");
-        }
-
-        sStatsServiceManager = statsServiceManager;
-    }
-
-    /** @hide */
-    public static StatsServiceManager getStatsServiceManager() {
-        return sStatsServiceManager;
-    }
-
-    /**
-     * Called by {@link SystemServiceRegistry}'s static initializer and registers all statsd
-     * services to {@link Context}, so that {@link Context#getSystemService} can return them.
-     *
-     * @throws IllegalStateException if this is called from anywhere besides
-     * {@link SystemServiceRegistry}
-     */
-    public static void registerServiceWrappers() {
-        SystemServiceRegistry.registerContextAwareService(
-                Context.STATS_MANAGER,
-                StatsManager.class,
-                context -> new StatsManager(context)
-        );
-    }
-}
diff --git a/apex/statsd/framework/java/android/util/StatsEvent.java b/apex/statsd/framework/java/android/util/StatsEvent.java
deleted file mode 100644
index 8be5c63..0000000
--- a/apex/statsd/framework/java/android/util/StatsEvent.java
+++ /dev/null
@@ -1,879 +0,0 @@
-/*
- * Copyright (C) 2019 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.util;
-
-import static java.nio.charset.StandardCharsets.UTF_8;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.SystemApi;
-import android.os.SystemClock;
-
-import com.android.internal.annotations.GuardedBy;
-import com.android.internal.annotations.VisibleForTesting;
-
-import java.util.Arrays;
-
-/**
- * StatsEvent builds and stores the buffer sent over the statsd socket.
- * This class defines and encapsulates the socket protocol.
- *
- * <p>Usage:</p>
- * <pre>
- *      // Pushed event
- *      StatsEvent statsEvent = StatsEvent.newBuilder()
- *          .setAtomId(atomId)
- *          .writeBoolean(false)
- *          .writeString("annotated String field")
- *          .addBooleanAnnotation(annotationId, true)
- *          .usePooledBuffer()
- *          .build();
- *      StatsLog.write(statsEvent);
- *
- *      // Pulled event
- *      StatsEvent statsEvent = StatsEvent.newBuilder()
- *          .setAtomId(atomId)
- *          .writeBoolean(false)
- *          .writeString("annotated String field")
- *          .addBooleanAnnotation(annotationId, true)
- *          .build();
- * </pre>
- * @hide
- **/
-@SystemApi
-public final class StatsEvent {
-    // Type Ids.
-    /**
-     * @hide
-     **/
-    @VisibleForTesting
-    public static final byte TYPE_INT = 0x00;
-
-    /**
-     * @hide
-     **/
-    @VisibleForTesting
-    public static final byte TYPE_LONG = 0x01;
-
-    /**
-     * @hide
-     **/
-    @VisibleForTesting
-    public static final byte TYPE_STRING = 0x02;
-
-    /**
-     * @hide
-     **/
-    @VisibleForTesting
-    public static final byte TYPE_LIST = 0x03;
-
-    /**
-     * @hide
-     **/
-    @VisibleForTesting
-    public static final byte TYPE_FLOAT = 0x04;
-
-    /**
-     * @hide
-     **/
-    @VisibleForTesting
-    public static final byte TYPE_BOOLEAN = 0x05;
-
-    /**
-     * @hide
-     **/
-    @VisibleForTesting
-    public static final byte TYPE_BYTE_ARRAY = 0x06;
-
-    /**
-     * @hide
-     **/
-    @VisibleForTesting
-    public static final byte TYPE_OBJECT = 0x07;
-
-    /**
-     * @hide
-     **/
-    @VisibleForTesting
-    public static final byte TYPE_KEY_VALUE_PAIRS = 0x08;
-
-    /**
-     * @hide
-     **/
-    @VisibleForTesting
-    public static final byte TYPE_ATTRIBUTION_CHAIN = 0x09;
-
-    /**
-     * @hide
-     **/
-    @VisibleForTesting
-    public static final byte TYPE_ERRORS = 0x0F;
-
-    // Error flags.
-    /**
-     * @hide
-     **/
-    @VisibleForTesting
-    public static final int ERROR_NO_TIMESTAMP = 0x1;
-
-    /**
-     * @hide
-     **/
-    @VisibleForTesting
-    public static final int ERROR_NO_ATOM_ID = 0x2;
-
-    /**
-     * @hide
-     **/
-    @VisibleForTesting
-    public static final int ERROR_OVERFLOW = 0x4;
-
-    /**
-     * @hide
-     **/
-    @VisibleForTesting
-    public static final int ERROR_ATTRIBUTION_CHAIN_TOO_LONG = 0x8;
-
-    /**
-     * @hide
-     **/
-    @VisibleForTesting
-    public static final int ERROR_TOO_MANY_KEY_VALUE_PAIRS = 0x10;
-
-    /**
-     * @hide
-     **/
-    @VisibleForTesting
-    public static final int ERROR_ANNOTATION_DOES_NOT_FOLLOW_FIELD = 0x20;
-
-    /**
-     * @hide
-     **/
-    @VisibleForTesting
-    public static final int ERROR_INVALID_ANNOTATION_ID = 0x40;
-
-    /**
-     * @hide
-     **/
-    @VisibleForTesting
-    public static final int ERROR_ANNOTATION_ID_TOO_LARGE = 0x80;
-
-    /**
-     * @hide
-     **/
-    @VisibleForTesting
-    public static final int ERROR_TOO_MANY_ANNOTATIONS = 0x100;
-
-    /**
-     * @hide
-     **/
-    @VisibleForTesting
-    public static final int ERROR_TOO_MANY_FIELDS = 0x200;
-
-    /**
-     * @hide
-     **/
-    @VisibleForTesting
-    public static final int ERROR_ATTRIBUTION_UIDS_TAGS_SIZES_NOT_EQUAL = 0x1000;
-
-    /**
-     * @hide
-     **/
-    @VisibleForTesting
-    public static final int ERROR_ATOM_ID_INVALID_POSITION = 0x2000;
-
-    // Size limits.
-
-    /**
-     * @hide
-     **/
-    @VisibleForTesting
-    public static final int MAX_ANNOTATION_COUNT = 15;
-
-    /**
-     * @hide
-     **/
-    @VisibleForTesting
-    public static final int MAX_ATTRIBUTION_NODES = 127;
-
-    /**
-     * @hide
-     **/
-    @VisibleForTesting
-    public static final int MAX_NUM_ELEMENTS = 127;
-
-    /**
-     * @hide
-     **/
-    @VisibleForTesting
-    public static final int MAX_KEY_VALUE_PAIRS = 127;
-
-    private static final int LOGGER_ENTRY_MAX_PAYLOAD = 4068;
-
-    // Max payload size is 4 bytes less as 4 bytes are reserved for statsEventTag.
-    // See android_util_StatsLog.cpp.
-    private static final int MAX_PUSH_PAYLOAD_SIZE = LOGGER_ENTRY_MAX_PAYLOAD - 4;
-
-    private static final int MAX_PULL_PAYLOAD_SIZE = 50 * 1024; // 50 KB
-
-    private final int mAtomId;
-    private final byte[] mPayload;
-    private Buffer mBuffer;
-    private final int mNumBytes;
-
-    private StatsEvent(final int atomId, @Nullable final Buffer buffer,
-            @NonNull final byte[] payload, final int numBytes) {
-        mAtomId = atomId;
-        mBuffer = buffer;
-        mPayload = payload;
-        mNumBytes = numBytes;
-    }
-
-    /**
-     * Returns a new StatsEvent.Builder for building StatsEvent object.
-     **/
-    @NonNull
-    public static StatsEvent.Builder newBuilder() {
-        return new StatsEvent.Builder(Buffer.obtain());
-    }
-
-    /**
-     * Get the atom Id of the atom encoded in this StatsEvent object.
-     *
-     * @hide
-     **/
-    public int getAtomId() {
-        return mAtomId;
-    }
-
-    /**
-     * Get the byte array that contains the encoded payload that can be sent to statsd.
-     *
-     * @hide
-     **/
-    @NonNull
-    public byte[] getBytes() {
-        return mPayload;
-    }
-
-    /**
-     * Get the number of bytes used to encode the StatsEvent payload.
-     *
-     * @hide
-     **/
-    public int getNumBytes() {
-        return mNumBytes;
-    }
-
-    /**
-     * Recycle resources used by this StatsEvent object.
-     * No actions should be taken on this StatsEvent after release() is called.
-     *
-     * @hide
-     **/
-    public void release() {
-        if (mBuffer != null) {
-            mBuffer.release();
-            mBuffer = null;
-        }
-    }
-
-    /**
-     * Builder for constructing a StatsEvent object.
-     *
-     * <p>This class defines and encapsulates the socket encoding for the buffer.
-     * The write methods must be called in the same order as the order of fields in the
-     * atom definition.</p>
-     *
-     * <p>setAtomId() can be called anytime before build().</p>
-     *
-     * <p>Example:</p>
-     * <pre>
-     *     // Atom definition.
-     *     message MyAtom {
-     *         optional int32 field1 = 1;
-     *         optional int64 field2 = 2;
-     *         optional string field3 = 3 [(annotation1) = true];
-     *     }
-     *
-     *     // StatsEvent construction for pushed event.
-     *     StatsEvent.newBuilder()
-     *     StatsEvent statsEvent = StatsEvent.newBuilder()
-     *         .setAtomId(atomId)
-     *         .writeInt(3) // field1
-     *         .writeLong(8L) // field2
-     *         .writeString("foo") // field 3
-     *         .addBooleanAnnotation(annotation1Id, true)
-     *         .usePooledBuffer()
-     *         .build();
-     *
-     *     // StatsEvent construction for pulled event.
-     *     StatsEvent.newBuilder()
-     *     StatsEvent statsEvent = StatsEvent.newBuilder()
-     *         .setAtomId(atomId)
-     *         .writeInt(3) // field1
-     *         .writeLong(8L) // field2
-     *         .writeString("foo") // field 3
-     *         .addBooleanAnnotation(annotation1Id, true)
-     *         .build();
-     * </pre>
-     **/
-    public static final class Builder {
-        // Fixed positions.
-        private static final int POS_NUM_ELEMENTS = 1;
-        private static final int POS_TIMESTAMP_NS = POS_NUM_ELEMENTS + Byte.BYTES;
-        private static final int POS_ATOM_ID = POS_TIMESTAMP_NS + Byte.BYTES + Long.BYTES;
-
-        private final Buffer mBuffer;
-        private long mTimestampNs;
-        private int mAtomId;
-        private byte mCurrentAnnotationCount;
-        private int mPos;
-        private int mPosLastField;
-        private byte mLastType;
-        private int mNumElements;
-        private int mErrorMask;
-        private boolean mUsePooledBuffer = false;
-
-        private Builder(final Buffer buffer) {
-            mBuffer = buffer;
-            mCurrentAnnotationCount = 0;
-            mAtomId = 0;
-            mTimestampNs = SystemClock.elapsedRealtimeNanos();
-            mNumElements = 0;
-
-            // Set mPos to 0 for writing TYPE_OBJECT at 0th position.
-            mPos = 0;
-            writeTypeId(TYPE_OBJECT);
-
-            // Write timestamp.
-            mPos = POS_TIMESTAMP_NS;
-            writeLong(mTimestampNs);
-        }
-
-        /**
-         * Sets the atom id for this StatsEvent.
-         *
-         * This should be called immediately after StatsEvent.newBuilder()
-         * and should only be called once.
-         * Not calling setAtomId will result in ERROR_NO_ATOM_ID.
-         * Calling setAtomId out of order will result in ERROR_ATOM_ID_INVALID_POSITION.
-         **/
-        @NonNull
-        public Builder setAtomId(final int atomId) {
-            if (0 == mAtomId) {
-                mAtomId = atomId;
-
-                if (1 == mNumElements) { // Only timestamp is written so far.
-                    writeInt(atomId);
-                } else {
-                    // setAtomId called out of order.
-                    mErrorMask |= ERROR_ATOM_ID_INVALID_POSITION;
-                }
-            }
-
-            return this;
-        }
-
-        /**
-         * Write a boolean field to this StatsEvent.
-         **/
-        @NonNull
-        public Builder writeBoolean(final boolean value) {
-            // Write boolean typeId byte followed by boolean byte representation.
-            writeTypeId(TYPE_BOOLEAN);
-            mPos += mBuffer.putBoolean(mPos, value);
-            mNumElements++;
-            return this;
-        }
-
-        /**
-         * Write an integer field to this StatsEvent.
-         **/
-        @NonNull
-        public Builder writeInt(final int value) {
-            // Write integer typeId byte followed by 4-byte representation of value.
-            writeTypeId(TYPE_INT);
-            mPos += mBuffer.putInt(mPos, value);
-            mNumElements++;
-            return this;
-        }
-
-        /**
-         * Write a long field to this StatsEvent.
-         **/
-        @NonNull
-        public Builder writeLong(final long value) {
-            // Write long typeId byte followed by 8-byte representation of value.
-            writeTypeId(TYPE_LONG);
-            mPos += mBuffer.putLong(mPos, value);
-            mNumElements++;
-            return this;
-        }
-
-        /**
-         * Write a float field to this StatsEvent.
-         **/
-        @NonNull
-        public Builder writeFloat(final float value) {
-            // Write float typeId byte followed by 4-byte representation of value.
-            writeTypeId(TYPE_FLOAT);
-            mPos += mBuffer.putFloat(mPos, value);
-            mNumElements++;
-            return this;
-        }
-
-        /**
-         * Write a String field to this StatsEvent.
-         **/
-        @NonNull
-        public Builder writeString(@NonNull final String value) {
-            // Write String typeId byte, followed by 4-byte representation of number of bytes
-            // in the UTF-8 encoding, followed by the actual UTF-8 byte encoding of value.
-            final byte[] valueBytes = stringToBytes(value);
-            writeByteArray(valueBytes, TYPE_STRING);
-            return this;
-        }
-
-        /**
-         * Write a byte array field to this StatsEvent.
-         **/
-        @NonNull
-        public Builder writeByteArray(@NonNull final byte[] value) {
-            // Write byte array typeId byte, followed by 4-byte representation of number of bytes
-            // in value, followed by the actual byte array.
-            writeByteArray(value, TYPE_BYTE_ARRAY);
-            return this;
-        }
-
-        private void writeByteArray(@NonNull final byte[] value, final byte typeId) {
-            writeTypeId(typeId);
-            final int numBytes = value.length;
-            mPos += mBuffer.putInt(mPos, numBytes);
-            mPos += mBuffer.putByteArray(mPos, value);
-            mNumElements++;
-        }
-
-        /**
-         * Write an attribution chain field to this StatsEvent.
-         *
-         * The sizes of uids and tags must be equal. The AttributionNode at position i is
-         * made up of uids[i] and tags[i].
-         *
-         * @param uids array of uids in the attribution nodes.
-         * @param tags array of tags in the attribution nodes.
-         **/
-        @NonNull
-        public Builder writeAttributionChain(
-                @NonNull final int[] uids, @NonNull final String[] tags) {
-            final byte numUids = (byte) uids.length;
-            final byte numTags = (byte) tags.length;
-
-            if (numUids != numTags) {
-                mErrorMask |= ERROR_ATTRIBUTION_UIDS_TAGS_SIZES_NOT_EQUAL;
-            } else if (numUids > MAX_ATTRIBUTION_NODES) {
-                mErrorMask |= ERROR_ATTRIBUTION_CHAIN_TOO_LONG;
-            } else {
-                // Write attribution chain typeId byte, followed by 1-byte representation of
-                // number of attribution nodes, followed by encoding of each attribution node.
-                writeTypeId(TYPE_ATTRIBUTION_CHAIN);
-                mPos += mBuffer.putByte(mPos, numUids);
-                for (int i = 0; i < numUids; i++) {
-                    // Each uid is encoded as 4-byte representation of its int value.
-                    mPos += mBuffer.putInt(mPos, uids[i]);
-
-                    // Each tag is encoded as 4-byte representation of number of bytes in its
-                    // UTF-8 encoding, followed by the actual UTF-8 bytes.
-                    final byte[] tagBytes = stringToBytes(tags[i]);
-                    mPos += mBuffer.putInt(mPos, tagBytes.length);
-                    mPos += mBuffer.putByteArray(mPos, tagBytes);
-                }
-                mNumElements++;
-            }
-            return this;
-        }
-
-        /**
-         * Write KeyValuePairsAtom entries to this StatsEvent.
-         *
-         * @param intMap Integer key-value pairs.
-         * @param longMap Long key-value pairs.
-         * @param stringMap String key-value pairs.
-         * @param floatMap Float key-value pairs.
-         **/
-        @NonNull
-        public Builder writeKeyValuePairs(
-                @Nullable final SparseIntArray intMap,
-                @Nullable final SparseLongArray longMap,
-                @Nullable final SparseArray<String> stringMap,
-                @Nullable final SparseArray<Float> floatMap) {
-            final int intMapSize = null == intMap ? 0 : intMap.size();
-            final int longMapSize = null == longMap ? 0 : longMap.size();
-            final int stringMapSize = null == stringMap ? 0 : stringMap.size();
-            final int floatMapSize = null == floatMap ? 0 : floatMap.size();
-            final int totalCount = intMapSize + longMapSize + stringMapSize + floatMapSize;
-
-            if (totalCount > MAX_KEY_VALUE_PAIRS) {
-                mErrorMask |= ERROR_TOO_MANY_KEY_VALUE_PAIRS;
-            } else {
-                writeTypeId(TYPE_KEY_VALUE_PAIRS);
-                mPos += mBuffer.putByte(mPos, (byte) totalCount);
-
-                for (int i = 0; i < intMapSize; i++) {
-                    final int key = intMap.keyAt(i);
-                    final int value = intMap.valueAt(i);
-                    mPos += mBuffer.putInt(mPos, key);
-                    writeTypeId(TYPE_INT);
-                    mPos += mBuffer.putInt(mPos, value);
-                }
-
-                for (int i = 0; i < longMapSize; i++) {
-                    final int key = longMap.keyAt(i);
-                    final long value = longMap.valueAt(i);
-                    mPos += mBuffer.putInt(mPos, key);
-                    writeTypeId(TYPE_LONG);
-                    mPos += mBuffer.putLong(mPos, value);
-                }
-
-                for (int i = 0; i < stringMapSize; i++) {
-                    final int key = stringMap.keyAt(i);
-                    final String value = stringMap.valueAt(i);
-                    mPos += mBuffer.putInt(mPos, key);
-                    writeTypeId(TYPE_STRING);
-                    final byte[] valueBytes = stringToBytes(value);
-                    mPos += mBuffer.putInt(mPos, valueBytes.length);
-                    mPos += mBuffer.putByteArray(mPos, valueBytes);
-                }
-
-                for (int i = 0; i < floatMapSize; i++) {
-                    final int key = floatMap.keyAt(i);
-                    final float value = floatMap.valueAt(i);
-                    mPos += mBuffer.putInt(mPos, key);
-                    writeTypeId(TYPE_FLOAT);
-                    mPos += mBuffer.putFloat(mPos, value);
-                }
-
-                mNumElements++;
-            }
-
-            return this;
-        }
-
-        /**
-         * Write a boolean annotation for the last field written.
-         **/
-        @NonNull
-        public Builder addBooleanAnnotation(
-                final byte annotationId, final boolean value) {
-            // Ensure there's a field written to annotate.
-            if (mNumElements < 2) {
-                mErrorMask |= ERROR_ANNOTATION_DOES_NOT_FOLLOW_FIELD;
-            } else if (mCurrentAnnotationCount >= MAX_ANNOTATION_COUNT) {
-                mErrorMask |= ERROR_TOO_MANY_ANNOTATIONS;
-            } else {
-                mPos += mBuffer.putByte(mPos, annotationId);
-                mPos += mBuffer.putByte(mPos, TYPE_BOOLEAN);
-                mPos += mBuffer.putBoolean(mPos, value);
-                mCurrentAnnotationCount++;
-                writeAnnotationCount();
-            }
-
-            return this;
-        }
-
-        /**
-         * Write an integer annotation for the last field written.
-         **/
-        @NonNull
-        public Builder addIntAnnotation(final byte annotationId, final int value) {
-            if (mNumElements < 2) {
-                mErrorMask |= ERROR_ANNOTATION_DOES_NOT_FOLLOW_FIELD;
-            } else if (mCurrentAnnotationCount >= MAX_ANNOTATION_COUNT) {
-                mErrorMask |= ERROR_TOO_MANY_ANNOTATIONS;
-            } else {
-                mPos += mBuffer.putByte(mPos, annotationId);
-                mPos += mBuffer.putByte(mPos, TYPE_INT);
-                mPos += mBuffer.putInt(mPos, value);
-                mCurrentAnnotationCount++;
-                writeAnnotationCount();
-            }
-
-            return this;
-        }
-
-        /**
-         * Indicates to reuse Buffer's byte array as the underlying payload in StatsEvent.
-         * This should be called for pushed events to reduce memory allocations and garbage
-         * collections.
-         **/
-        @NonNull
-        public Builder usePooledBuffer() {
-            mUsePooledBuffer = true;
-            mBuffer.setMaxSize(MAX_PUSH_PAYLOAD_SIZE, mPos);
-            return this;
-        }
-
-        /**
-         * Builds a StatsEvent object with values entered in this Builder.
-         **/
-        @NonNull
-        public StatsEvent build() {
-            if (0L == mTimestampNs) {
-                mErrorMask |= ERROR_NO_TIMESTAMP;
-            }
-            if (0 == mAtomId) {
-                mErrorMask |= ERROR_NO_ATOM_ID;
-            }
-            if (mBuffer.hasOverflowed()) {
-                mErrorMask |= ERROR_OVERFLOW;
-            }
-            if (mNumElements > MAX_NUM_ELEMENTS) {
-                mErrorMask |= ERROR_TOO_MANY_FIELDS;
-            }
-
-            if (0 == mErrorMask) {
-                mBuffer.putByte(POS_NUM_ELEMENTS, (byte) mNumElements);
-            } else {
-                // Write atom id and error mask. Overwrite any annotations for atom Id.
-                mPos = POS_ATOM_ID;
-                mPos += mBuffer.putByte(mPos, TYPE_INT);
-                mPos += mBuffer.putInt(mPos, mAtomId);
-                mPos += mBuffer.putByte(mPos, TYPE_ERRORS);
-                mPos += mBuffer.putInt(mPos, mErrorMask);
-                mBuffer.putByte(POS_NUM_ELEMENTS, (byte) 3);
-            }
-
-            final int size = mPos;
-
-            if (mUsePooledBuffer) {
-                return new StatsEvent(mAtomId, mBuffer, mBuffer.getBytes(), size);
-            } else {
-                // Create a copy of the buffer with the required number of bytes.
-                final byte[] payload = new byte[size];
-                System.arraycopy(mBuffer.getBytes(), 0, payload, 0, size);
-
-                // Return Buffer instance to the pool.
-                mBuffer.release();
-
-                return new StatsEvent(mAtomId, null, payload, size);
-            }
-        }
-
-        private void writeTypeId(final byte typeId) {
-            mPosLastField = mPos;
-            mLastType = typeId;
-            mCurrentAnnotationCount = 0;
-            final byte encodedId = (byte) (typeId & 0x0F);
-            mPos += mBuffer.putByte(mPos, encodedId);
-        }
-
-        private void writeAnnotationCount() {
-            // Use first 4 bits for annotation count and last 4 bits for typeId.
-            final byte encodedId = (byte) ((mCurrentAnnotationCount << 4) | (mLastType & 0x0F));
-            mBuffer.putByte(mPosLastField, encodedId);
-        }
-
-        @NonNull
-        private static byte[] stringToBytes(@Nullable final String value) {
-            return (null == value ? "" : value).getBytes(UTF_8);
-        }
-    }
-
-    private static final class Buffer {
-        private static Object sLock = new Object();
-
-        @GuardedBy("sLock")
-        private static Buffer sPool;
-
-        private byte[] mBytes = new byte[MAX_PUSH_PAYLOAD_SIZE];
-        private boolean mOverflow = false;
-        private int mMaxSize = MAX_PULL_PAYLOAD_SIZE;
-
-        @NonNull
-        private static Buffer obtain() {
-            final Buffer buffer;
-            synchronized (sLock) {
-                buffer = null == sPool ? new Buffer() : sPool;
-                sPool = null;
-            }
-            buffer.reset();
-            return buffer;
-        }
-
-        private Buffer() {
-        }
-
-        @NonNull
-        private byte[] getBytes() {
-            return mBytes;
-        }
-
-        private void release() {
-            // Recycle this Buffer if its size is MAX_PUSH_PAYLOAD_SIZE or under.
-            if (mBytes.length <= MAX_PUSH_PAYLOAD_SIZE) {
-                synchronized (sLock) {
-                    if (null == sPool) {
-                        sPool = this;
-                    }
-                }
-            }
-        }
-
-        private void reset() {
-            mOverflow = false;
-            mMaxSize = MAX_PULL_PAYLOAD_SIZE;
-        }
-
-        private void setMaxSize(final int maxSize, final int numBytesWritten) {
-            mMaxSize = maxSize;
-            if (numBytesWritten > maxSize) {
-                mOverflow = true;
-            }
-        }
-
-        private boolean hasOverflowed() {
-            return mOverflow;
-        }
-
-        /**
-         * Checks for available space in the byte array.
-         *
-         * @param index starting position in the buffer to start the check.
-         * @param numBytes number of bytes to check from index.
-         * @return true if space is available, false otherwise.
-         **/
-        private boolean hasEnoughSpace(final int index, final int numBytes) {
-            final int totalBytesNeeded = index + numBytes;
-
-            if (totalBytesNeeded > mMaxSize) {
-                mOverflow = true;
-                return false;
-            }
-
-            // Expand buffer if needed.
-            if (mBytes.length < mMaxSize && totalBytesNeeded > mBytes.length) {
-                int newSize = mBytes.length;
-                do {
-                    newSize *= 2;
-                } while (newSize <= totalBytesNeeded);
-
-                if (newSize > mMaxSize) {
-                    newSize = mMaxSize;
-                }
-
-                mBytes = Arrays.copyOf(mBytes, newSize);
-            }
-
-            return true;
-        }
-
-        /**
-         * Writes a byte into the buffer.
-         *
-         * @param index position in the buffer where the byte is written.
-         * @param value the byte to write.
-         * @return number of bytes written to buffer from this write operation.
-         **/
-        private int putByte(final int index, final byte value) {
-            if (hasEnoughSpace(index, Byte.BYTES)) {
-                mBytes[index] = (byte) (value);
-                return Byte.BYTES;
-            }
-            return 0;
-        }
-
-        /**
-         * Writes a boolean into the buffer.
-         *
-         * @param index position in the buffer where the boolean is written.
-         * @param value the boolean to write.
-         * @return number of bytes written to buffer from this write operation.
-         **/
-        private int putBoolean(final int index, final boolean value) {
-            return putByte(index, (byte) (value ? 1 : 0));
-        }
-
-        /**
-         * Writes an integer into the buffer.
-         *
-         * @param index position in the buffer where the integer is written.
-         * @param value the integer to write.
-         * @return number of bytes written to buffer from this write operation.
-         **/
-        private int putInt(final int index, final int value) {
-            if (hasEnoughSpace(index, Integer.BYTES)) {
-                // Use little endian byte order.
-                mBytes[index] = (byte) (value);
-                mBytes[index + 1] = (byte) (value >> 8);
-                mBytes[index + 2] = (byte) (value >> 16);
-                mBytes[index + 3] = (byte) (value >> 24);
-                return Integer.BYTES;
-            }
-            return 0;
-        }
-
-        /**
-         * Writes a long into the buffer.
-         *
-         * @param index position in the buffer where the long is written.
-         * @param value the long to write.
-         * @return number of bytes written to buffer from this write operation.
-         **/
-        private int putLong(final int index, final long value) {
-            if (hasEnoughSpace(index, Long.BYTES)) {
-                // Use little endian byte order.
-                mBytes[index] = (byte) (value);
-                mBytes[index + 1] = (byte) (value >> 8);
-                mBytes[index + 2] = (byte) (value >> 16);
-                mBytes[index + 3] = (byte) (value >> 24);
-                mBytes[index + 4] = (byte) (value >> 32);
-                mBytes[index + 5] = (byte) (value >> 40);
-                mBytes[index + 6] = (byte) (value >> 48);
-                mBytes[index + 7] = (byte) (value >> 56);
-                return Long.BYTES;
-            }
-            return 0;
-        }
-
-        /**
-         * Writes a float into the buffer.
-         *
-         * @param index position in the buffer where the float is written.
-         * @param value the float to write.
-         * @return number of bytes written to buffer from this write operation.
-         **/
-        private int putFloat(final int index, final float value) {
-            return putInt(index, Float.floatToIntBits(value));
-        }
-
-        /**
-         * Copies a byte array into the buffer.
-         *
-         * @param index position in the buffer where the byte array is copied.
-         * @param value the byte array to copy.
-         * @return number of bytes written to buffer from this write operation.
-         **/
-        private int putByteArray(final int index, @NonNull final byte[] value) {
-            final int numBytes = value.length;
-            if (hasEnoughSpace(index, numBytes)) {
-                System.arraycopy(value, 0, mBytes, index, numBytes);
-                return numBytes;
-            }
-            return 0;
-        }
-    }
-}
diff --git a/apex/statsd/framework/java/android/util/StatsLog.java b/apex/statsd/framework/java/android/util/StatsLog.java
deleted file mode 100644
index 0a9f4eb..0000000
--- a/apex/statsd/framework/java/android/util/StatsLog.java
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- * Copyright (C) 2017 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.util;
-
-import static android.Manifest.permission.DUMP;
-import static android.Manifest.permission.PACKAGE_USAGE_STATS;
-
-import android.Manifest;
-import android.annotation.NonNull;
-import android.annotation.RequiresPermission;
-import android.annotation.SystemApi;
-import android.content.Context;
-import android.os.IStatsd;
-import android.os.Process;
-import android.util.proto.ProtoOutputStream;
-
-import com.android.internal.statsd.StatsdStatsLog;
-
-/**
- * StatsLog provides an API for developers to send events to statsd. The events can be used to
- * define custom metrics inside statsd.
- */
-public final class StatsLog {
-
-    // Load JNI library
-    static {
-        System.loadLibrary("stats_jni");
-    }
-    private static final String TAG = "StatsLog";
-    private static final boolean DEBUG = false;
-    private static final int EXPERIMENT_IDS_FIELD_ID = 1;
-
-    private StatsLog() {
-    }
-
-    /**
-     * Logs a start event.
-     *
-     * @param label developer-chosen label.
-     * @return True if the log request was sent to statsd.
-     */
-    public static boolean logStart(int label) {
-        int callingUid = Process.myUid();
-        StatsdStatsLog.write(
-                StatsdStatsLog.APP_BREADCRUMB_REPORTED,
-                callingUid,
-                label,
-                StatsdStatsLog.APP_BREADCRUMB_REPORTED__STATE__START);
-        return true;
-    }
-
-    /**
-     * Logs a stop event.
-     *
-     * @param label developer-chosen label.
-     * @return True if the log request was sent to statsd.
-     */
-    public static boolean logStop(int label) {
-        int callingUid = Process.myUid();
-        StatsdStatsLog.write(
-                StatsdStatsLog.APP_BREADCRUMB_REPORTED,
-                callingUid,
-                label,
-                StatsdStatsLog.APP_BREADCRUMB_REPORTED__STATE__STOP);
-        return true;
-    }
-
-    /**
-     * Logs an event that does not represent a start or stop boundary.
-     *
-     * @param label developer-chosen label.
-     * @return True if the log request was sent to statsd.
-     */
-    public static boolean logEvent(int label) {
-        int callingUid = Process.myUid();
-        StatsdStatsLog.write(
-                StatsdStatsLog.APP_BREADCRUMB_REPORTED,
-                callingUid,
-                label,
-                StatsdStatsLog.APP_BREADCRUMB_REPORTED__STATE__UNSPECIFIED);
-        return true;
-    }
-
-    /**
-     * Logs an event for binary push for module updates.
-     *
-     * @param trainName        name of install train.
-     * @param trainVersionCode version code of the train.
-     * @param options          optional flags about this install.
-     *                         The last 3 bits indicate options:
-     *                             0x01: FLAG_REQUIRE_STAGING
-     *                             0x02: FLAG_ROLLBACK_ENABLED
-     *                             0x04: FLAG_REQUIRE_LOW_LATENCY_MONITOR
-     * @param state            current install state. Defined as State enums in
-     *                         BinaryPushStateChanged atom in
-     *                         frameworks/base/cmds/statsd/src/atoms.proto
-     * @param experimentIds    experiment ids.
-     * @return True if the log request was sent to statsd.
-     */
-    @RequiresPermission(allOf = {DUMP, PACKAGE_USAGE_STATS})
-    public static boolean logBinaryPushStateChanged(@NonNull String trainName,
-            long trainVersionCode, int options, int state,
-            @NonNull long[] experimentIds) {
-        ProtoOutputStream proto = new ProtoOutputStream();
-        for (long id : experimentIds) {
-            proto.write(
-                    ProtoOutputStream.FIELD_TYPE_INT64
-                    | ProtoOutputStream.FIELD_COUNT_REPEATED
-                    | EXPERIMENT_IDS_FIELD_ID,
-                    id);
-        }
-        StatsdStatsLog.write(StatsdStatsLog.BINARY_PUSH_STATE_CHANGED,
-                trainName,
-                trainVersionCode,
-                (options & IStatsd.FLAG_REQUIRE_STAGING) > 0,
-                (options & IStatsd.FLAG_ROLLBACK_ENABLED) > 0,
-                (options & IStatsd.FLAG_REQUIRE_LOW_LATENCY_MONITOR) > 0,
-                state,
-                proto.getBytes(),
-                0,
-                0,
-                false);
-        return true;
-    }
-
-    /**
-     * Write an event to stats log using the raw format.
-     *
-     * @param buffer    The encoded buffer of data to write.
-     * @param size      The number of bytes from the buffer to write.
-     * @hide
-     */
-    // TODO(b/144935988): Mark deprecated.
-    @SystemApi
-    public static void writeRaw(@NonNull byte[] buffer, int size) {
-        // TODO(b/144935988): make this no-op once clients have migrated to StatsEvent.
-        writeImpl(buffer, size, 0);
-    }
-
-    /**
-     * Write an event to stats log using the raw format.
-     *
-     * @param buffer    The encoded buffer of data to write.
-     * @param size      The number of bytes from the buffer to write.
-     * @param atomId    The id of the atom to which the event belongs.
-     */
-    private static native void writeImpl(@NonNull byte[] buffer, int size, int atomId);
-
-    /**
-     * Write an event to stats log using the raw format encapsulated in StatsEvent.
-     * After writing to stats log, release() is called on the StatsEvent object.
-     * No further action should be taken on the StatsEvent object following this call.
-     *
-     * @param statsEvent    The StatsEvent object containing the encoded buffer of data to write.
-     * @hide
-     */
-    @SystemApi
-    public static void write(@NonNull final StatsEvent statsEvent) {
-        writeImpl(statsEvent.getBytes(), statsEvent.getNumBytes(), statsEvent.getAtomId());
-        statsEvent.release();
-    }
-
-    private static void enforceDumpCallingPermission(Context context) {
-        context.enforceCallingPermission(android.Manifest.permission.DUMP, "Need DUMP permission.");
-    }
-
-    private static void enforcesageStatsCallingPermission(Context context) {
-        context.enforceCallingPermission(Manifest.permission.PACKAGE_USAGE_STATS,
-                "Need PACKAGE_USAGE_STATS permission.");
-    }
-}
diff --git a/apex/statsd/framework/test/Android.bp b/apex/statsd/framework/test/Android.bp
deleted file mode 100644
index 5cc5647..0000000
--- a/apex/statsd/framework/test/Android.bp
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright (C) 2020 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-android_test {
-    name: "FrameworkStatsdTest",
-    sdk_version: "module_current",
-    srcs: [ "**/*.java" ],
-    manifest: "AndroidManifest.xml",
-    static_libs: [
-        "androidx.test.rules",
-        "truth-prebuilt",
-    ],
-    libs: [
-        "android.test.runner.stubs",
-        "android.test.base.stubs",
-        "framework-statsd.impl",
-    ],
-    test_suites: [
-        "device-tests",
-        "mts",
-    ],
-}
diff --git a/apex/statsd/framework/test/AndroidManifest.xml b/apex/statsd/framework/test/AndroidManifest.xml
deleted file mode 100644
index 8f89d23..0000000
--- a/apex/statsd/framework/test/AndroidManifest.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2020 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-        package="com.android.os.statsd.framework.test"
-        >
-
-    <instrumentation
-            android:name="androidx.test.runner.AndroidJUnitRunner"
-            android:targetPackage="com.android.os.statsd.framework.test"
-            android:label="Framework Statsd Tests" />
-
-</manifest>
diff --git a/apex/statsd/framework/test/AndroidTest.xml b/apex/statsd/framework/test/AndroidTest.xml
deleted file mode 100644
index fb51915..0000000
--- a/apex/statsd/framework/test/AndroidTest.xml
+++ /dev/null
@@ -1,34 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2020 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<configuration description="Runs Tests for Statsd.">
-    <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
-        <option name="test-file-name" value="FrameworkStatsdTest.apk" />
-        <option name="install-arg" value="-g" />
-    </target_preparer>
-
-    <option name="test-suite-tag" value="apct" />
-    <option name="test-suite-tag" value="mts" />
-    <option name="test-tag" value="FrameworkStatsdTest" />
-    <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
-        <option name="package" value="com.android.os.statsd.framework.test" />
-        <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
-        <option name="hidden-api-checks" value="false"/>
-    </test>
-
-    <object type="module_controller" class="com.android.tradefed.testtype.suite.module.MainlineTestModuleController">
-        <option name="mainline-module-package-name" value="com.google.android.os.statsd" />
-    </object>
-</configuration>
\ No newline at end of file
diff --git a/apex/statsd/framework/test/src/android/app/PullAtomMetadataTest.java b/apex/statsd/framework/test/src/android/app/PullAtomMetadataTest.java
deleted file mode 100644
index fd386bd..0000000
--- a/apex/statsd/framework/test/src/android/app/PullAtomMetadataTest.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (C) 2019 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 static com.google.common.truth.Truth.assertThat;
-
-import android.app.StatsManager.PullAtomMetadata;
-
-import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-@SmallTest
-@RunWith(AndroidJUnit4.class)
-public final class PullAtomMetadataTest {
-
-    @Test
-    public void testEmpty() {
-        PullAtomMetadata metadata = new PullAtomMetadata.Builder().build();
-        assertThat(metadata.getTimeoutMillis()).isEqualTo(StatsManager.DEFAULT_TIMEOUT_MILLIS);
-        assertThat(metadata.getCoolDownMillis()).isEqualTo(StatsManager.DEFAULT_COOL_DOWN_MILLIS);
-        assertThat(metadata.getAdditiveFields()).isNull();
-    }
-
-    @Test
-    public void testSetTimeoutMillis() {
-        long timeoutMillis = 500L;
-        PullAtomMetadata metadata =
-                new PullAtomMetadata.Builder().setTimeoutMillis(timeoutMillis).build();
-        assertThat(metadata.getTimeoutMillis()).isEqualTo(timeoutMillis);
-        assertThat(metadata.getCoolDownMillis()).isEqualTo(StatsManager.DEFAULT_COOL_DOWN_MILLIS);
-        assertThat(metadata.getAdditiveFields()).isNull();
-    }
-
-    @Test
-    public void testSetCoolDownMillis() {
-        long coolDownMillis = 10_000L;
-        PullAtomMetadata metadata =
-                new PullAtomMetadata.Builder().setCoolDownMillis(coolDownMillis).build();
-        assertThat(metadata.getTimeoutMillis()).isEqualTo(StatsManager.DEFAULT_TIMEOUT_MILLIS);
-        assertThat(metadata.getCoolDownMillis()).isEqualTo(coolDownMillis);
-        assertThat(metadata.getAdditiveFields()).isNull();
-    }
-
-    @Test
-    public void testSetAdditiveFields() {
-        int[] fields = {2, 4, 6};
-        PullAtomMetadata metadata =
-                new PullAtomMetadata.Builder().setAdditiveFields(fields).build();
-        assertThat(metadata.getTimeoutMillis()).isEqualTo(StatsManager.DEFAULT_TIMEOUT_MILLIS);
-        assertThat(metadata.getCoolDownMillis()).isEqualTo(StatsManager.DEFAULT_COOL_DOWN_MILLIS);
-        assertThat(metadata.getAdditiveFields()).isEqualTo(fields);
-    }
-
-    @Test
-    public void testSetAllElements() {
-        long timeoutMillis = 300L;
-        long coolDownMillis = 9572L;
-        int[] fields = {3, 2};
-        PullAtomMetadata metadata = new PullAtomMetadata.Builder()
-                .setTimeoutMillis(timeoutMillis)
-                .setCoolDownMillis(coolDownMillis)
-                .setAdditiveFields(fields)
-                .build();
-        assertThat(metadata.getTimeoutMillis()).isEqualTo(timeoutMillis);
-        assertThat(metadata.getCoolDownMillis()).isEqualTo(coolDownMillis);
-        assertThat(metadata.getAdditiveFields()).isEqualTo(fields);
-    }
-}
diff --git a/apex/statsd/framework/test/src/android/os/StatsDimensionsValueTest.java b/apex/statsd/framework/test/src/android/os/StatsDimensionsValueTest.java
deleted file mode 100644
index db25911..0000000
--- a/apex/statsd/framework/test/src/android/os/StatsDimensionsValueTest.java
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.os;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-
-import java.util.List;
-
-@RunWith(JUnit4.class)
-public final class StatsDimensionsValueTest {
-
-    @Test
-    public void testConversionFromStructuredParcel() {
-        int tupleField = 100; // atom id
-        String stringValue = "Hello";
-        int intValue = 123;
-        long longValue = 123456789L;
-        float floatValue = 1.1f;
-        boolean boolValue = true;
-
-        // Construct structured parcel
-        StatsDimensionsValueParcel sdvp = new StatsDimensionsValueParcel();
-        sdvp.field = tupleField;
-        sdvp.valueType = StatsDimensionsValue.TUPLE_VALUE_TYPE;
-        sdvp.tupleValue = new StatsDimensionsValueParcel[5];
-
-        for (int i = 0; i < 5; i++) {
-            sdvp.tupleValue[i] = new StatsDimensionsValueParcel();
-            sdvp.tupleValue[i].field = i + 1;
-        }
-
-        sdvp.tupleValue[0].valueType = StatsDimensionsValue.STRING_VALUE_TYPE;
-        sdvp.tupleValue[1].valueType = StatsDimensionsValue.INT_VALUE_TYPE;
-        sdvp.tupleValue[2].valueType = StatsDimensionsValue.LONG_VALUE_TYPE;
-        sdvp.tupleValue[3].valueType = StatsDimensionsValue.FLOAT_VALUE_TYPE;
-        sdvp.tupleValue[4].valueType = StatsDimensionsValue.BOOLEAN_VALUE_TYPE;
-
-        sdvp.tupleValue[0].stringValue = stringValue;
-        sdvp.tupleValue[1].intValue = intValue;
-        sdvp.tupleValue[2].longValue = longValue;
-        sdvp.tupleValue[3].floatValue = floatValue;
-        sdvp.tupleValue[4].boolValue = boolValue;
-
-        // Convert to StatsDimensionsValue and check result
-        StatsDimensionsValue sdv = new StatsDimensionsValue(sdvp);
-
-        assertThat(sdv.getField()).isEqualTo(tupleField);
-        assertThat(sdv.getValueType()).isEqualTo(StatsDimensionsValue.TUPLE_VALUE_TYPE);
-        List<StatsDimensionsValue> sdvChildren = sdv.getTupleValueList();
-        assertThat(sdvChildren.size()).isEqualTo(5);
-
-        for (int i = 0; i < 5; i++) {
-            assertThat(sdvChildren.get(i).getField()).isEqualTo(i + 1);
-        }
-
-        assertThat(sdvChildren.get(0).getValueType())
-              .isEqualTo(StatsDimensionsValue.STRING_VALUE_TYPE);
-        assertThat(sdvChildren.get(1).getValueType())
-              .isEqualTo(StatsDimensionsValue.INT_VALUE_TYPE);
-        assertThat(sdvChildren.get(2).getValueType())
-              .isEqualTo(StatsDimensionsValue.LONG_VALUE_TYPE);
-        assertThat(sdvChildren.get(3).getValueType())
-              .isEqualTo(StatsDimensionsValue.FLOAT_VALUE_TYPE);
-        assertThat(sdvChildren.get(4).getValueType())
-              .isEqualTo(StatsDimensionsValue.BOOLEAN_VALUE_TYPE);
-
-        assertThat(sdvChildren.get(0).getStringValue()).isEqualTo(stringValue);
-        assertThat(sdvChildren.get(1).getIntValue()).isEqualTo(intValue);
-        assertThat(sdvChildren.get(2).getLongValue()).isEqualTo(longValue);
-        assertThat(sdvChildren.get(3).getFloatValue()).isEqualTo(floatValue);
-        assertThat(sdvChildren.get(4).getBooleanValue()).isEqualTo(boolValue);
-
-        // Ensure that StatsDimensionsValue and StatsDimensionsValueParcel are
-        // parceled equivalently
-        Parcel sdvpParcel = Parcel.obtain();
-        Parcel sdvParcel = Parcel.obtain();
-        sdvp.writeToParcel(sdvpParcel, 0);
-        sdv.writeToParcel(sdvParcel, 0);
-        assertThat(sdvpParcel.dataSize()).isEqualTo(sdvParcel.dataSize());
-    }
-
-    @Test
-    public void testNullTupleArray() {
-        int tupleField = 100; // atom id
-
-        StatsDimensionsValueParcel parcel = new StatsDimensionsValueParcel();
-        parcel.field = tupleField;
-        parcel.valueType = StatsDimensionsValue.TUPLE_VALUE_TYPE;
-        parcel.tupleValue = null;
-
-        StatsDimensionsValue sdv = new StatsDimensionsValue(parcel);
-        assertThat(sdv.getField()).isEqualTo(tupleField);
-        assertThat(sdv.getValueType()).isEqualTo(StatsDimensionsValue.TUPLE_VALUE_TYPE);
-        List<StatsDimensionsValue> sdvChildren = sdv.getTupleValueList();
-        assertThat(sdvChildren.size()).isEqualTo(0);
-    }
-}
diff --git a/apex/statsd/framework/test/src/android/util/StatsEventTest.java b/apex/statsd/framework/test/src/android/util/StatsEventTest.java
deleted file mode 100644
index 8d26369..0000000
--- a/apex/statsd/framework/test/src/android/util/StatsEventTest.java
+++ /dev/null
@@ -1,818 +0,0 @@
-/*
- * Copyright (C) 2019 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.util;
-
-import static com.google.common.truth.Truth.assertThat;
-import static com.google.common.truth.Truth.assertWithMessage;
-
-import static java.nio.charset.StandardCharsets.UTF_8;
-
-import android.os.SystemClock;
-
-import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
-
-import com.google.common.collect.Range;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.util.Random;
-
-/**
- * Internal tests for {@link StatsEvent}.
- */
-@SmallTest
-@RunWith(AndroidJUnit4.class)
-public class StatsEventTest {
-
-    @Test
-    public void testNoFields() {
-        final long minTimestamp = SystemClock.elapsedRealtimeNanos();
-        final StatsEvent statsEvent = StatsEvent.newBuilder().usePooledBuffer().build();
-        final long maxTimestamp = SystemClock.elapsedRealtimeNanos();
-
-        final int expectedAtomId = 0;
-        assertThat(statsEvent.getAtomId()).isEqualTo(expectedAtomId);
-
-        final ByteBuffer buffer =
-                ByteBuffer.wrap(statsEvent.getBytes()).order(ByteOrder.LITTLE_ENDIAN);
-
-        assertWithMessage("Root element in buffer is not TYPE_OBJECT")
-                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_OBJECT);
-
-        assertWithMessage("Incorrect number of elements in root object")
-                .that(buffer.get()).isEqualTo(3);
-
-        assertWithMessage("First element is not timestamp")
-                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_LONG);
-
-        assertWithMessage("Incorrect timestamp")
-                .that(buffer.getLong()).isIn(Range.closed(minTimestamp, maxTimestamp));
-
-        assertWithMessage("Second element is not atom id")
-                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_INT);
-
-        assertWithMessage("Incorrect atom id")
-                .that(buffer.getInt()).isEqualTo(expectedAtomId);
-
-        assertWithMessage("Third element is not errors type")
-                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_ERRORS);
-
-        final int errorMask = buffer.getInt();
-
-        assertWithMessage("ERROR_NO_ATOM_ID should be the only error in the error mask")
-                .that(errorMask).isEqualTo(StatsEvent.ERROR_NO_ATOM_ID);
-
-        assertThat(statsEvent.getNumBytes()).isEqualTo(buffer.position());
-
-        statsEvent.release();
-    }
-
-    @Test
-    public void testOnlyAtomId() {
-        final int expectedAtomId = 109;
-
-        final long minTimestamp = SystemClock.elapsedRealtimeNanos();
-        final StatsEvent statsEvent = StatsEvent.newBuilder()
-                .setAtomId(expectedAtomId)
-                .usePooledBuffer()
-                .build();
-        final long maxTimestamp = SystemClock.elapsedRealtimeNanos();
-
-        assertThat(statsEvent.getAtomId()).isEqualTo(expectedAtomId);
-
-        final ByteBuffer buffer =
-                ByteBuffer.wrap(statsEvent.getBytes()).order(ByteOrder.LITTLE_ENDIAN);
-
-        assertWithMessage("Root element in buffer is not TYPE_OBJECT")
-                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_OBJECT);
-
-        assertWithMessage("Incorrect number of elements in root object")
-                .that(buffer.get()).isEqualTo(2);
-
-        assertWithMessage("First element is not timestamp")
-                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_LONG);
-
-        assertWithMessage("Incorrect timestamp")
-                .that(buffer.getLong()).isIn(Range.closed(minTimestamp, maxTimestamp));
-
-        assertWithMessage("Second element is not atom id")
-                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_INT);
-
-        assertWithMessage("Incorrect atom id")
-                .that(buffer.getInt()).isEqualTo(expectedAtomId);
-
-        assertThat(statsEvent.getNumBytes()).isEqualTo(buffer.position());
-
-        statsEvent.release();
-    }
-
-    @Test
-    public void testIntBooleanIntInt() {
-        final int expectedAtomId = 109;
-        final int field1 = 1;
-        final boolean field2 = true;
-        final int field3 = 3;
-        final int field4 = 4;
-
-        final long minTimestamp = SystemClock.elapsedRealtimeNanos();
-        final StatsEvent statsEvent = StatsEvent.newBuilder()
-                .setAtomId(expectedAtomId)
-                .writeInt(field1)
-                .writeBoolean(field2)
-                .writeInt(field3)
-                .writeInt(field4)
-                .usePooledBuffer()
-                .build();
-        final long maxTimestamp = SystemClock.elapsedRealtimeNanos();
-
-        assertThat(statsEvent.getAtomId()).isEqualTo(expectedAtomId);
-
-        final ByteBuffer buffer =
-                ByteBuffer.wrap(statsEvent.getBytes()).order(ByteOrder.LITTLE_ENDIAN);
-
-        assertWithMessage("Root element in buffer is not TYPE_OBJECT")
-                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_OBJECT);
-
-        assertWithMessage("Incorrect number of elements in root object")
-                .that(buffer.get()).isEqualTo(6);
-
-        assertWithMessage("First element is not timestamp")
-                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_LONG);
-
-        assertWithMessage("Incorrect timestamp")
-                .that(buffer.getLong()).isIn(Range.closed(minTimestamp, maxTimestamp));
-
-        assertWithMessage("Second element is not atom id")
-                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_INT);
-
-        assertWithMessage("Incorrect atom id")
-                .that(buffer.getInt()).isEqualTo(expectedAtomId);
-
-        assertWithMessage("First field is not Int")
-                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_INT);
-
-        assertWithMessage("Incorrect field 1")
-                .that(buffer.getInt()).isEqualTo(field1);
-
-        assertWithMessage("Second field is not Boolean")
-                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_BOOLEAN);
-
-        assertWithMessage("Incorrect field 2")
-                .that(buffer.get()).isEqualTo(1);
-
-        assertWithMessage("Third field is not Int")
-                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_INT);
-
-        assertWithMessage("Incorrect field 3")
-                .that(buffer.getInt()).isEqualTo(field3);
-
-        assertWithMessage("Fourth field is not Int")
-                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_INT);
-
-        assertWithMessage("Incorrect field 4")
-                .that(buffer.getInt()).isEqualTo(field4);
-
-        assertThat(statsEvent.getNumBytes()).isEqualTo(buffer.position());
-
-        statsEvent.release();
-    }
-
-    @Test
-    public void testStringFloatByteArray() {
-        final int expectedAtomId = 109;
-        final String field1 = "Str 1";
-        final float field2 = 9.334f;
-        final byte[] field3 = new byte[] { 56, 23, 89, -120 };
-
-        final long minTimestamp = SystemClock.elapsedRealtimeNanos();
-        final StatsEvent statsEvent = StatsEvent.newBuilder()
-                .setAtomId(expectedAtomId)
-                .writeString(field1)
-                .writeFloat(field2)
-                .writeByteArray(field3)
-                .usePooledBuffer()
-                .build();
-        final long maxTimestamp = SystemClock.elapsedRealtimeNanos();
-
-        assertThat(statsEvent.getAtomId()).isEqualTo(expectedAtomId);
-
-        final ByteBuffer buffer =
-                ByteBuffer.wrap(statsEvent.getBytes()).order(ByteOrder.LITTLE_ENDIAN);
-
-        assertWithMessage("Root element in buffer is not TYPE_OBJECT")
-                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_OBJECT);
-
-        assertWithMessage("Incorrect number of elements in root object")
-                .that(buffer.get()).isEqualTo(5);
-
-        assertWithMessage("First element is not timestamp")
-                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_LONG);
-
-        assertWithMessage("Incorrect timestamp")
-                .that(buffer.getLong()).isIn(Range.closed(minTimestamp, maxTimestamp));
-
-        assertWithMessage("Second element is not atom id")
-                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_INT);
-
-        assertWithMessage("Incorrect atom id")
-                .that(buffer.getInt()).isEqualTo(expectedAtomId);
-
-        assertWithMessage("First field is not String")
-                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_STRING);
-
-        final String field1Actual = getStringFromByteBuffer(buffer);
-        assertWithMessage("Incorrect field 1")
-                .that(field1Actual).isEqualTo(field1);
-
-        assertWithMessage("Second field is not Float")
-                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_FLOAT);
-
-        assertWithMessage("Incorrect field 2")
-                .that(buffer.getFloat()).isEqualTo(field2);
-
-        assertWithMessage("Third field is not byte array")
-                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_BYTE_ARRAY);
-
-        final byte[] field3Actual = getByteArrayFromByteBuffer(buffer);
-        assertWithMessage("Incorrect field 3")
-                .that(field3Actual).isEqualTo(field3);
-
-        assertThat(statsEvent.getNumBytes()).isEqualTo(buffer.position());
-
-        statsEvent.release();
-    }
-
-    @Test
-    public void testAttributionChainLong() {
-        final int expectedAtomId = 109;
-        final int[] uids = new int[] { 1, 2, 3, 4, 5 };
-        final String[] tags = new String[] { "1", "2", "3", "4", "5" };
-        final long field2 = -230909823L;
-
-        final long minTimestamp = SystemClock.elapsedRealtimeNanos();
-        final StatsEvent statsEvent = StatsEvent.newBuilder()
-                .setAtomId(expectedAtomId)
-                .writeAttributionChain(uids, tags)
-                .writeLong(field2)
-                .usePooledBuffer()
-                .build();
-        final long maxTimestamp = SystemClock.elapsedRealtimeNanos();
-
-        assertThat(statsEvent.getAtomId()).isEqualTo(expectedAtomId);
-
-        final ByteBuffer buffer =
-                ByteBuffer.wrap(statsEvent.getBytes()).order(ByteOrder.LITTLE_ENDIAN);
-
-        assertWithMessage("Root element in buffer is not TYPE_OBJECT")
-                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_OBJECT);
-
-        assertWithMessage("Incorrect number of elements in root object")
-                .that(buffer.get()).isEqualTo(4);
-
-        assertWithMessage("First element is not timestamp")
-                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_LONG);
-
-        assertWithMessage("Incorrect timestamp")
-                .that(buffer.getLong()).isIn(Range.closed(minTimestamp, maxTimestamp));
-
-        assertWithMessage("Second element is not atom id")
-                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_INT);
-
-        assertWithMessage("Incorrect atom id")
-                .that(buffer.getInt()).isEqualTo(expectedAtomId);
-
-        assertWithMessage("First field is not Attribution Chain")
-                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_ATTRIBUTION_CHAIN);
-
-        assertWithMessage("Incorrect number of attribution nodes")
-                .that(buffer.get()).isEqualTo((byte) uids.length);
-
-        for (int i = 0; i < tags.length; i++) {
-            assertWithMessage("Incorrect uid in Attribution Chain")
-                    .that(buffer.getInt()).isEqualTo(uids[i]);
-
-            final String tag = getStringFromByteBuffer(buffer);
-            assertWithMessage("Incorrect tag in Attribution Chain")
-                    .that(tag).isEqualTo(tags[i]);
-        }
-
-        assertWithMessage("Second field is not Long")
-                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_LONG);
-
-        assertWithMessage("Incorrect field 2")
-                .that(buffer.getLong()).isEqualTo(field2);
-
-        assertThat(statsEvent.getNumBytes()).isEqualTo(buffer.position());
-
-        statsEvent.release();
-    }
-
-    @Test
-    public void testKeyValuePairs() {
-        final int expectedAtomId = 109;
-        final SparseIntArray intMap = new SparseIntArray();
-        final SparseLongArray longMap = new SparseLongArray();
-        final SparseArray<String> stringMap = new SparseArray<>();
-        final SparseArray<Float> floatMap = new SparseArray<>();
-        intMap.put(1, -1);
-        intMap.put(2, -2);
-        stringMap.put(3, "abc");
-        stringMap.put(4, "2h");
-        floatMap.put(9, -234.344f);
-
-        final long minTimestamp = SystemClock.elapsedRealtimeNanos();
-        final StatsEvent statsEvent = StatsEvent.newBuilder()
-                .setAtomId(expectedAtomId)
-                .writeKeyValuePairs(intMap, longMap, stringMap, floatMap)
-                .usePooledBuffer()
-                .build();
-        final long maxTimestamp = SystemClock.elapsedRealtimeNanos();
-
-        assertThat(statsEvent.getAtomId()).isEqualTo(expectedAtomId);
-
-        final ByteBuffer buffer =
-                ByteBuffer.wrap(statsEvent.getBytes()).order(ByteOrder.LITTLE_ENDIAN);
-
-        assertWithMessage("Root element in buffer is not TYPE_OBJECT")
-                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_OBJECT);
-
-        assertWithMessage("Incorrect number of elements in root object")
-                .that(buffer.get()).isEqualTo(3);
-
-        assertWithMessage("First element is not timestamp")
-                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_LONG);
-
-        assertWithMessage("Incorrect timestamp")
-                .that(buffer.getLong()).isIn(Range.closed(minTimestamp, maxTimestamp));
-
-        assertWithMessage("Second element is not atom id")
-                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_INT);
-
-        assertWithMessage("Incorrect atom id")
-                .that(buffer.getInt()).isEqualTo(expectedAtomId);
-
-        assertWithMessage("First field is not KeyValuePairs")
-                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_KEY_VALUE_PAIRS);
-
-        assertWithMessage("Incorrect number of key value pairs")
-                .that(buffer.get()).isEqualTo(
-                        (byte) (intMap.size() + longMap.size() + stringMap.size()
-                                + floatMap.size()));
-
-        for (int i = 0; i < intMap.size(); i++) {
-            assertWithMessage("Incorrect key in intMap")
-                    .that(buffer.getInt()).isEqualTo(intMap.keyAt(i));
-            assertWithMessage("The type id of the value should be TYPE_INT in intMap")
-                    .that(buffer.get()).isEqualTo(StatsEvent.TYPE_INT);
-            assertWithMessage("Incorrect value in intMap")
-                    .that(buffer.getInt()).isEqualTo(intMap.valueAt(i));
-        }
-
-        for (int i = 0; i < longMap.size(); i++) {
-            assertWithMessage("Incorrect key in longMap")
-                    .that(buffer.getInt()).isEqualTo(longMap.keyAt(i));
-            assertWithMessage("The type id of the value should be TYPE_LONG in longMap")
-                    .that(buffer.get()).isEqualTo(StatsEvent.TYPE_LONG);
-            assertWithMessage("Incorrect value in longMap")
-                    .that(buffer.getLong()).isEqualTo(longMap.valueAt(i));
-        }
-
-        for (int i = 0; i < stringMap.size(); i++) {
-            assertWithMessage("Incorrect key in stringMap")
-                    .that(buffer.getInt()).isEqualTo(stringMap.keyAt(i));
-            assertWithMessage("The type id of the value should be TYPE_STRING in stringMap")
-                    .that(buffer.get()).isEqualTo(StatsEvent.TYPE_STRING);
-            final String value = getStringFromByteBuffer(buffer);
-            assertWithMessage("Incorrect value in stringMap")
-                    .that(value).isEqualTo(stringMap.valueAt(i));
-        }
-
-        for (int i = 0; i < floatMap.size(); i++) {
-            assertWithMessage("Incorrect key in floatMap")
-                    .that(buffer.getInt()).isEqualTo(floatMap.keyAt(i));
-            assertWithMessage("The type id of the value should be TYPE_FLOAT in floatMap")
-                    .that(buffer.get()).isEqualTo(StatsEvent.TYPE_FLOAT);
-            assertWithMessage("Incorrect value in floatMap")
-                    .that(buffer.getFloat()).isEqualTo(floatMap.valueAt(i));
-        }
-
-        assertThat(statsEvent.getNumBytes()).isEqualTo(buffer.position());
-
-        statsEvent.release();
-    }
-
-    @Test
-    public void testSingleAnnotations() {
-        final int expectedAtomId = 109;
-        final int field1 = 1;
-        final byte field1AnnotationId = 45;
-        final boolean field1AnnotationValue = false;
-        final boolean field2 = true;
-        final byte field2AnnotationId = 1;
-        final int field2AnnotationValue = 23;
-
-        final long minTimestamp = SystemClock.elapsedRealtimeNanos();
-        final StatsEvent statsEvent = StatsEvent.newBuilder()
-                .setAtomId(expectedAtomId)
-                .writeInt(field1)
-                .addBooleanAnnotation(field1AnnotationId, field1AnnotationValue)
-                .writeBoolean(field2)
-                .addIntAnnotation(field2AnnotationId, field2AnnotationValue)
-                .usePooledBuffer()
-                .build();
-        final long maxTimestamp = SystemClock.elapsedRealtimeNanos();
-
-        assertThat(statsEvent.getAtomId()).isEqualTo(expectedAtomId);
-
-        final ByteBuffer buffer =
-                ByteBuffer.wrap(statsEvent.getBytes()).order(ByteOrder.LITTLE_ENDIAN);
-
-        assertWithMessage("Root element in buffer is not TYPE_OBJECT")
-                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_OBJECT);
-
-        assertWithMessage("Incorrect number of elements in root object")
-                .that(buffer.get()).isEqualTo(4);
-
-        assertWithMessage("First element is not timestamp")
-                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_LONG);
-
-        assertWithMessage("Incorrect timestamp")
-                .that(buffer.getLong()).isIn(Range.closed(minTimestamp, maxTimestamp));
-
-        assertWithMessage("Second element is not atom id")
-                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_INT);
-
-        assertWithMessage("Incorrect atom id")
-                .that(buffer.getInt()).isEqualTo(expectedAtomId);
-
-        final byte field1Header = buffer.get();
-        final int field1AnnotationValueCount = field1Header >> 4;
-        final byte field1Type = (byte) (field1Header & 0x0F);
-        assertWithMessage("First field is not Int")
-                .that(field1Type).isEqualTo(StatsEvent.TYPE_INT);
-        assertWithMessage("First field annotation count is wrong")
-                .that(field1AnnotationValueCount).isEqualTo(1);
-        assertWithMessage("Incorrect field 1")
-                .that(buffer.getInt()).isEqualTo(field1);
-        assertWithMessage("First field's annotation id is wrong")
-                .that(buffer.get()).isEqualTo(field1AnnotationId);
-        assertWithMessage("First field's annotation type is wrong")
-                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_BOOLEAN);
-        assertWithMessage("First field's annotation value is wrong")
-                .that(buffer.get()).isEqualTo(field1AnnotationValue ? 1 : 0);
-
-        final byte field2Header = buffer.get();
-        final int field2AnnotationValueCount = field2Header >> 4;
-        final byte field2Type = (byte) (field2Header & 0x0F);
-        assertWithMessage("Second field is not boolean")
-                .that(field2Type).isEqualTo(StatsEvent.TYPE_BOOLEAN);
-        assertWithMessage("Second field annotation count is wrong")
-                .that(field2AnnotationValueCount).isEqualTo(1);
-        assertWithMessage("Incorrect field 2")
-                .that(buffer.get()).isEqualTo(field2 ? 1 : 0);
-        assertWithMessage("Second field's annotation id is wrong")
-                .that(buffer.get()).isEqualTo(field2AnnotationId);
-        assertWithMessage("Second field's annotation type is wrong")
-                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_INT);
-        assertWithMessage("Second field's annotation value is wrong")
-                .that(buffer.getInt()).isEqualTo(field2AnnotationValue);
-
-        assertThat(statsEvent.getNumBytes()).isEqualTo(buffer.position());
-
-        statsEvent.release();
-    }
-
-    @Test
-    public void testAtomIdAnnotations() {
-        final int expectedAtomId = 109;
-        final byte atomAnnotationId = 84;
-        final int atomAnnotationValue = 9;
-        final int field1 = 1;
-        final byte field1AnnotationId = 45;
-        final boolean field1AnnotationValue = false;
-        final boolean field2 = true;
-        final byte field2AnnotationId = 1;
-        final int field2AnnotationValue = 23;
-
-        final long minTimestamp = SystemClock.elapsedRealtimeNanos();
-        final StatsEvent statsEvent = StatsEvent.newBuilder()
-                .setAtomId(expectedAtomId)
-                .addIntAnnotation(atomAnnotationId, atomAnnotationValue)
-                .writeInt(field1)
-                .addBooleanAnnotation(field1AnnotationId, field1AnnotationValue)
-                .writeBoolean(field2)
-                .addIntAnnotation(field2AnnotationId, field2AnnotationValue)
-                .usePooledBuffer()
-                .build();
-        final long maxTimestamp = SystemClock.elapsedRealtimeNanos();
-
-        assertThat(statsEvent.getAtomId()).isEqualTo(expectedAtomId);
-
-        final ByteBuffer buffer =
-                ByteBuffer.wrap(statsEvent.getBytes()).order(ByteOrder.LITTLE_ENDIAN);
-
-        assertWithMessage("Root element in buffer is not TYPE_OBJECT")
-                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_OBJECT);
-
-        assertWithMessage("Incorrect number of elements in root object")
-                .that(buffer.get()).isEqualTo(4);
-
-        assertWithMessage("First element is not timestamp")
-                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_LONG);
-
-        assertWithMessage("Incorrect timestamp")
-                .that(buffer.getLong()).isIn(Range.closed(minTimestamp, maxTimestamp));
-
-        final byte atomIdHeader = buffer.get();
-        final int atomIdAnnotationValueCount = atomIdHeader >> 4;
-        final byte atomIdValueType = (byte) (atomIdHeader & 0x0F);
-        assertWithMessage("Second element is not atom id")
-                .that(atomIdValueType).isEqualTo(StatsEvent.TYPE_INT);
-        assertWithMessage("Atom id annotation count is wrong")
-                .that(atomIdAnnotationValueCount).isEqualTo(1);
-        assertWithMessage("Incorrect atom id")
-                .that(buffer.getInt()).isEqualTo(expectedAtomId);
-        assertWithMessage("Atom id's annotation id is wrong")
-                .that(buffer.get()).isEqualTo(atomAnnotationId);
-        assertWithMessage("Atom id's annotation type is wrong")
-                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_INT);
-        assertWithMessage("Atom id's annotation value is wrong")
-                .that(buffer.getInt()).isEqualTo(atomAnnotationValue);
-
-        final byte field1Header = buffer.get();
-        final int field1AnnotationValueCount = field1Header >> 4;
-        final byte field1Type = (byte) (field1Header & 0x0F);
-        assertWithMessage("First field is not Int")
-                .that(field1Type).isEqualTo(StatsEvent.TYPE_INT);
-        assertWithMessage("First field annotation count is wrong")
-                .that(field1AnnotationValueCount).isEqualTo(1);
-        assertWithMessage("Incorrect field 1")
-                .that(buffer.getInt()).isEqualTo(field1);
-        assertWithMessage("First field's annotation id is wrong")
-                .that(buffer.get()).isEqualTo(field1AnnotationId);
-        assertWithMessage("First field's annotation type is wrong")
-                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_BOOLEAN);
-        assertWithMessage("First field's annotation value is wrong")
-                .that(buffer.get()).isEqualTo(field1AnnotationValue ? 1 : 0);
-
-        final byte field2Header = buffer.get();
-        final int field2AnnotationValueCount = field2Header >> 4;
-        final byte field2Type = (byte) (field2Header & 0x0F);
-        assertWithMessage("Second field is not boolean")
-                .that(field2Type).isEqualTo(StatsEvent.TYPE_BOOLEAN);
-        assertWithMessage("Second field annotation count is wrong")
-                .that(field2AnnotationValueCount).isEqualTo(1);
-        assertWithMessage("Incorrect field 2")
-                .that(buffer.get()).isEqualTo(field2 ? 1 : 0);
-        assertWithMessage("Second field's annotation id is wrong")
-                .that(buffer.get()).isEqualTo(field2AnnotationId);
-        assertWithMessage("Second field's annotation type is wrong")
-                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_INT);
-        assertWithMessage("Second field's annotation value is wrong")
-                .that(buffer.getInt()).isEqualTo(field2AnnotationValue);
-
-        assertThat(statsEvent.getNumBytes()).isEqualTo(buffer.position());
-
-        statsEvent.release();
-    }
-
-    @Test
-    public void testSetAtomIdNotCalledImmediately() {
-        final int expectedAtomId = 109;
-        final int field1 = 25;
-        final boolean field2 = true;
-
-        final long minTimestamp = SystemClock.elapsedRealtimeNanos();
-        final StatsEvent statsEvent = StatsEvent.newBuilder()
-                .writeInt(field1)
-                .setAtomId(expectedAtomId)
-                .writeBoolean(field2)
-                .usePooledBuffer()
-                .build();
-        final long maxTimestamp = SystemClock.elapsedRealtimeNanos();
-
-        assertThat(statsEvent.getAtomId()).isEqualTo(expectedAtomId);
-
-        final ByteBuffer buffer =
-                ByteBuffer.wrap(statsEvent.getBytes()).order(ByteOrder.LITTLE_ENDIAN);
-
-        assertWithMessage("Root element in buffer is not TYPE_OBJECT")
-                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_OBJECT);
-
-        assertWithMessage("Incorrect number of elements in root object")
-                .that(buffer.get()).isEqualTo(3);
-
-        assertWithMessage("First element is not timestamp")
-                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_LONG);
-
-        assertWithMessage("Incorrect timestamp")
-                .that(buffer.getLong()).isIn(Range.closed(minTimestamp, maxTimestamp));
-
-        assertWithMessage("Second element is not atom id")
-                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_INT);
-
-        assertWithMessage("Incorrect atom id")
-                .that(buffer.getInt()).isEqualTo(expectedAtomId);
-
-        assertWithMessage("Third element is not errors type")
-                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_ERRORS);
-
-        final int errorMask = buffer.getInt();
-
-        assertWithMessage("ERROR_ATOM_ID_INVALID_POSITION should be the only error in the mask")
-                .that(errorMask).isEqualTo(StatsEvent.ERROR_ATOM_ID_INVALID_POSITION);
-
-        assertThat(statsEvent.getNumBytes()).isEqualTo(buffer.position());
-
-        statsEvent.release();
-    }
-
-    @Test
-    public void testLargePulledEvent() {
-        final int expectedAtomId = 10_020;
-        byte[] field1 = new byte[10 * 1024];
-        new Random().nextBytes(field1);
-
-        final long minTimestamp = SystemClock.elapsedRealtimeNanos();
-        final StatsEvent statsEvent =
-                StatsEvent.newBuilder().setAtomId(expectedAtomId).writeByteArray(field1).build();
-        final long maxTimestamp = SystemClock.elapsedRealtimeNanos();
-
-        assertThat(statsEvent.getAtomId()).isEqualTo(expectedAtomId);
-
-        final ByteBuffer buffer =
-                ByteBuffer.wrap(statsEvent.getBytes()).order(ByteOrder.LITTLE_ENDIAN);
-
-        assertWithMessage("Root element in buffer is not TYPE_OBJECT")
-                .that(buffer.get())
-                .isEqualTo(StatsEvent.TYPE_OBJECT);
-
-        assertWithMessage("Incorrect number of elements in root object")
-                .that(buffer.get())
-                .isEqualTo(3);
-
-        assertWithMessage("First element is not timestamp")
-                .that(buffer.get())
-                .isEqualTo(StatsEvent.TYPE_LONG);
-
-        assertWithMessage("Incorrect timestamp")
-                .that(buffer.getLong())
-                .isIn(Range.closed(minTimestamp, maxTimestamp));
-
-        assertWithMessage("Second element is not atom id")
-                .that(buffer.get())
-                .isEqualTo(StatsEvent.TYPE_INT);
-
-        assertWithMessage("Incorrect atom id").that(buffer.getInt()).isEqualTo(expectedAtomId);
-
-        assertWithMessage("Third element is not byte array")
-                .that(buffer.get())
-                .isEqualTo(StatsEvent.TYPE_BYTE_ARRAY);
-
-        final byte[] field1Actual = getByteArrayFromByteBuffer(buffer);
-        assertWithMessage("Incorrect field 1").that(field1Actual).isEqualTo(field1);
-
-        assertThat(statsEvent.getNumBytes()).isEqualTo(buffer.position());
-
-        statsEvent.release();
-    }
-
-    @Test
-    public void testPulledEventOverflow() {
-        final int expectedAtomId = 10_020;
-        byte[] field1 = new byte[50 * 1024];
-        new Random().nextBytes(field1);
-
-        final long minTimestamp = SystemClock.elapsedRealtimeNanos();
-        final StatsEvent statsEvent =
-                StatsEvent.newBuilder().setAtomId(expectedAtomId).writeByteArray(field1).build();
-        final long maxTimestamp = SystemClock.elapsedRealtimeNanos();
-
-        assertThat(statsEvent.getAtomId()).isEqualTo(expectedAtomId);
-
-        final ByteBuffer buffer =
-                ByteBuffer.wrap(statsEvent.getBytes()).order(ByteOrder.LITTLE_ENDIAN);
-
-        assertWithMessage("Root element in buffer is not TYPE_OBJECT")
-                .that(buffer.get())
-                .isEqualTo(StatsEvent.TYPE_OBJECT);
-
-        assertWithMessage("Incorrect number of elements in root object")
-                .that(buffer.get())
-                .isEqualTo(3);
-
-        assertWithMessage("First element is not timestamp")
-                .that(buffer.get())
-                .isEqualTo(StatsEvent.TYPE_LONG);
-
-        assertWithMessage("Incorrect timestamp")
-                .that(buffer.getLong())
-                .isIn(Range.closed(minTimestamp, maxTimestamp));
-
-        assertWithMessage("Second element is not atom id")
-                .that(buffer.get())
-                .isEqualTo(StatsEvent.TYPE_INT);
-
-        assertWithMessage("Incorrect atom id").that(buffer.getInt()).isEqualTo(expectedAtomId);
-
-        assertWithMessage("Third element is not errors type")
-                .that(buffer.get())
-                .isEqualTo(StatsEvent.TYPE_ERRORS);
-
-        final int errorMask = buffer.getInt();
-
-        assertWithMessage("ERROR_OVERFLOW should be the only error in the error mask")
-                .that(errorMask)
-                .isEqualTo(StatsEvent.ERROR_OVERFLOW);
-
-        assertThat(statsEvent.getNumBytes()).isEqualTo(buffer.position());
-
-        statsEvent.release();
-    }
-
-    @Test
-    public void testPushedEventOverflow() {
-        final int expectedAtomId = 10_020;
-        byte[] field1 = new byte[10 * 1024];
-        new Random().nextBytes(field1);
-
-        final long minTimestamp = SystemClock.elapsedRealtimeNanos();
-        final StatsEvent statsEvent = StatsEvent.newBuilder()
-                                              .setAtomId(expectedAtomId)
-                                              .writeByteArray(field1)
-                                              .usePooledBuffer()
-                                              .build();
-        final long maxTimestamp = SystemClock.elapsedRealtimeNanos();
-
-        assertThat(statsEvent.getAtomId()).isEqualTo(expectedAtomId);
-
-        final ByteBuffer buffer =
-                ByteBuffer.wrap(statsEvent.getBytes()).order(ByteOrder.LITTLE_ENDIAN);
-
-        assertWithMessage("Root element in buffer is not TYPE_OBJECT")
-                .that(buffer.get())
-                .isEqualTo(StatsEvent.TYPE_OBJECT);
-
-        assertWithMessage("Incorrect number of elements in root object")
-                .that(buffer.get())
-                .isEqualTo(3);
-
-        assertWithMessage("First element is not timestamp")
-                .that(buffer.get())
-                .isEqualTo(StatsEvent.TYPE_LONG);
-
-        assertWithMessage("Incorrect timestamp")
-                .that(buffer.getLong())
-                .isIn(Range.closed(minTimestamp, maxTimestamp));
-
-        assertWithMessage("Second element is not atom id")
-                .that(buffer.get())
-                .isEqualTo(StatsEvent.TYPE_INT);
-
-        assertWithMessage("Incorrect atom id").that(buffer.getInt()).isEqualTo(expectedAtomId);
-
-        assertWithMessage("Third element is not errors type")
-                .that(buffer.get())
-                .isEqualTo(StatsEvent.TYPE_ERRORS);
-
-        final int errorMask = buffer.getInt();
-
-        assertWithMessage("ERROR_OVERFLOW should be the only error in the error mask")
-                .that(errorMask)
-                .isEqualTo(StatsEvent.ERROR_OVERFLOW);
-
-        assertThat(statsEvent.getNumBytes()).isEqualTo(buffer.position());
-
-        statsEvent.release();
-    }
-
-    private static byte[] getByteArrayFromByteBuffer(final ByteBuffer buffer) {
-        final int numBytes = buffer.getInt();
-        byte[] bytes = new byte[numBytes];
-        buffer.get(bytes);
-        return bytes;
-    }
-
-    private static String getStringFromByteBuffer(final ByteBuffer buffer) {
-        final byte[] bytes = getByteArrayFromByteBuffer(buffer);
-        return new String(bytes, UTF_8);
-    }
-}
diff --git a/apex/statsd/jni/android_util_StatsLog.cpp b/apex/statsd/jni/android_util_StatsLog.cpp
deleted file mode 100644
index 71ce949..0000000
--- a/apex/statsd/jni/android_util_StatsLog.cpp
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (C) 2019 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.
- */
-
-#define LOG_NAMESPACE "StatsLog.tag."
-#define LOG_TAG "StatsLog_println"
-
-#include <jni.h>
-#include <log/log.h>
-#include <nativehelper/scoped_local_ref.h>
-#include "stats_buffer_writer.h"
-
-namespace android {
-
-static void android_util_StatsLog_write(JNIEnv* env, jobject clazz, jbyteArray buf, jint size,
-        jint atomId) {
-    if (buf == NULL) {
-        return;
-    }
-    jint actualSize = env->GetArrayLength(buf);
-    if (actualSize < size) {
-        return;
-    }
-
-    jbyte* bufferArray = env->GetByteArrayElements(buf, NULL);
-    if (bufferArray == NULL) {
-        return;
-    }
-
-    write_buffer_to_statsd((void*) bufferArray, size, atomId);
-
-    env->ReleaseByteArrayElements(buf, bufferArray, 0);
-}
-
-/*
- * JNI registration.
- */
-static const JNINativeMethod gMethods[] = {
-    /* name, signature, funcPtr */
-    { "writeImpl", "([BII)V", (void*) android_util_StatsLog_write },
-};
-
-int register_android_util_StatsLog(JNIEnv* env)
-{
-    static const char* kStatsLogClass = "android/util/StatsLog";
-
-    ScopedLocalRef<jclass> cls(env, env->FindClass(kStatsLogClass));
-    if (cls.get() == nullptr) {
-        ALOGE("jni statsd registration failure, class not found '%s'", kStatsLogClass);
-        return JNI_ERR;
-    }
-
-    const jint count = sizeof(gMethods) / sizeof(gMethods[0]);
-    int status = env->RegisterNatives(cls.get(), gMethods, count);
-    if (status < 0) {
-        ALOGE("jni statsd registration failure, status: %d", status);
-        return JNI_ERR;
-    }
-    return JNI_VERSION_1_4;
-}
-
-}; // namespace android
-
-/*
- * JNI Initialization
- */
-jint JNI_OnLoad(JavaVM* jvm, void* reserved) {
-    JNIEnv* e;
-
-    ALOGV("statsd : loading JNI\n");
-    // Check JNI version
-    if (jvm->GetEnv((void**)&e, JNI_VERSION_1_4)) {
-        ALOGE("JNI version mismatch error");
-        return JNI_ERR;
-    }
-
-    return android::register_android_util_StatsLog(e);
-}
diff --git a/apex/statsd/service/Android.bp b/apex/statsd/service/Android.bp
deleted file mode 100644
index df0ccfc..0000000
--- a/apex/statsd/service/Android.bp
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright (C) 2020 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-filegroup {
-    name: "service-statsd-sources",
-    srcs: [
-        "java/**/*.java",
-    ],
-}
-
-java_library {
-    name: "service-statsd",
-    srcs: [ ":service-statsd-sources" ],
-    sdk_version: "system_server_current",
-    libs: [
-        "framework-annotations-lib",
-        "framework-statsd",
-    ],
-    plugins: ["java_api_finder"],
-    apex_available: [
-        "com.android.os.statsd",
-        "test_com.android.os.statsd",
-    ],
-}
diff --git a/apex/statsd/service/java/com/android/server/stats/StatsCompanion.java b/apex/statsd/service/java/com/android/server/stats/StatsCompanion.java
deleted file mode 100644
index dc477a5..0000000
--- a/apex/statsd/service/java/com/android/server/stats/StatsCompanion.java
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- * Copyright (C) 2019 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.stats;
-
-import android.app.PendingIntent;
-import android.app.StatsManager;
-import android.content.Context;
-import android.content.Intent;
-import android.os.Binder;
-import android.os.IPendingIntentRef;
-import android.os.Process;
-import android.os.StatsDimensionsValue;
-import android.os.StatsDimensionsValueParcel;
-import android.util.Log;
-
-import com.android.server.SystemService;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-
-/**
- * @hide
- */
-public class StatsCompanion {
-    private static final String TAG = "StatsCompanion";
-    private static final boolean DEBUG = false;
-
-    private static final int AID_STATSD = 1066;
-
-    private static final String STATS_COMPANION_SERVICE = "statscompanion";
-    private static final String STATS_MANAGER_SERVICE = "statsmanager";
-
-    static void enforceStatsdCallingUid() {
-        if (Binder.getCallingPid() == Process.myPid()) {
-            return;
-        }
-        if (Binder.getCallingUid() != AID_STATSD) {
-            throw new SecurityException("Not allowed to access StatsCompanion");
-        }
-    }
-
-    /**
-     * Lifecycle class for both {@link StatsCompanionService} and {@link StatsManagerService}.
-     */
-    public static final class Lifecycle extends SystemService {
-        private StatsCompanionService mStatsCompanionService;
-        private StatsManagerService mStatsManagerService;
-
-        public Lifecycle(Context context) {
-            super(context);
-        }
-
-        @Override
-        public void onStart() {
-            mStatsCompanionService = new StatsCompanionService(getContext());
-            mStatsManagerService = new StatsManagerService(getContext());
-            mStatsCompanionService.setStatsManagerService(mStatsManagerService);
-            mStatsManagerService.setStatsCompanionService(mStatsCompanionService);
-
-            try {
-                publishBinderService(STATS_COMPANION_SERVICE, mStatsCompanionService);
-                if (DEBUG) Log.d(TAG, "Published " + STATS_COMPANION_SERVICE);
-                publishBinderService(STATS_MANAGER_SERVICE, mStatsManagerService);
-                if (DEBUG) Log.d(TAG, "Published " + STATS_MANAGER_SERVICE);
-            } catch (Exception e) {
-                Log.e(TAG, "Failed to publishBinderService", e);
-            }
-        }
-
-        @Override
-        public void onBootPhase(int phase) {
-            super.onBootPhase(phase);
-            if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) {
-                mStatsCompanionService.systemReady();
-            }
-            if (phase == PHASE_BOOT_COMPLETED) {
-                mStatsCompanionService.bootCompleted();
-            }
-        }
-    }
-
-    /**
-     * Wrapper for {@link PendingIntent}. Allows Statsd to send PendingIntents.
-     */
-    public static class PendingIntentRef extends IPendingIntentRef.Stub {
-
-        private static final String TAG = "PendingIntentRef";
-
-        /**
-         * The last report time is provided with each intent registered to
-         * StatsManager#setFetchReportsOperation. This allows easy de-duping in the receiver if
-         * statsd is requesting the client to retrieve the same statsd data. The last report time
-         * corresponds to the last_report_elapsed_nanos that will provided in the current
-         * ConfigMetricsReport, and this timestamp also corresponds to the
-         * current_report_elapsed_nanos of the most recently obtained ConfigMetricsReport.
-         */
-        private static final String EXTRA_LAST_REPORT_TIME = "android.app.extra.LAST_REPORT_TIME";
-        private static final int CODE_DATA_BROADCAST = 1;
-        private static final int CODE_ACTIVE_CONFIGS_BROADCAST = 1;
-        private static final int CODE_SUBSCRIBER_BROADCAST = 1;
-
-        private final PendingIntent mPendingIntent;
-        private final Context mContext;
-
-        public PendingIntentRef(PendingIntent pendingIntent, Context context) {
-            mPendingIntent = pendingIntent;
-            mContext = context;
-        }
-
-        @Override
-        public void sendDataBroadcast(long lastReportTimeNs) {
-            enforceStatsdCallingUid();
-            Intent intent = new Intent();
-            intent.putExtra(EXTRA_LAST_REPORT_TIME, lastReportTimeNs);
-            try {
-                mPendingIntent.send(mContext, CODE_DATA_BROADCAST, intent, null, null);
-            } catch (PendingIntent.CanceledException e) {
-                Log.w(TAG, "Unable to send PendingIntent");
-            }
-        }
-
-        @Override
-        public void sendActiveConfigsChangedBroadcast(long[] configIds) {
-            enforceStatsdCallingUid();
-            Intent intent = new Intent();
-            intent.putExtra(StatsManager.EXTRA_STATS_ACTIVE_CONFIG_KEYS, configIds);
-            try {
-                mPendingIntent.send(mContext, CODE_ACTIVE_CONFIGS_BROADCAST, intent, null, null);
-                if (DEBUG) {
-                    Log.d(TAG, "Sent broadcast with config ids " + Arrays.toString(configIds));
-                }
-            } catch (PendingIntent.CanceledException e) {
-                Log.w(TAG, "Unable to send active configs changed broadcast using PendingIntent");
-            }
-        }
-
-        @Override
-        public void sendSubscriberBroadcast(long configUid, long configId, long subscriptionId,
-                long subscriptionRuleId, String[] cookies,
-                StatsDimensionsValueParcel dimensionsValueParcel) {
-            enforceStatsdCallingUid();
-            StatsDimensionsValue dimensionsValue = new StatsDimensionsValue(dimensionsValueParcel);
-            Intent intent =
-                    new Intent()
-                            .putExtra(StatsManager.EXTRA_STATS_CONFIG_UID, configUid)
-                            .putExtra(StatsManager.EXTRA_STATS_CONFIG_KEY, configId)
-                            .putExtra(StatsManager.EXTRA_STATS_SUBSCRIPTION_ID, subscriptionId)
-                            .putExtra(StatsManager.EXTRA_STATS_SUBSCRIPTION_RULE_ID,
-                                    subscriptionRuleId)
-                            .putExtra(StatsManager.EXTRA_STATS_DIMENSIONS_VALUE, dimensionsValue);
-
-            ArrayList<String> cookieList = new ArrayList<>(cookies.length);
-            cookieList.addAll(Arrays.asList(cookies));
-            intent.putStringArrayListExtra(
-                    StatsManager.EXTRA_STATS_BROADCAST_SUBSCRIBER_COOKIES, cookieList);
-
-            if (DEBUG) {
-                Log.d(TAG,
-                        String.format(
-                                "Statsd sendSubscriberBroadcast with params {%d %d %d %d %s %s}",
-                                configUid, configId, subscriptionId, subscriptionRuleId,
-                                Arrays.toString(cookies),
-                                dimensionsValue));
-            }
-            try {
-                mPendingIntent.send(mContext, CODE_SUBSCRIBER_BROADCAST, intent, null, null);
-            } catch (PendingIntent.CanceledException e) {
-                Log.w(TAG,
-                        "Unable to send using PendingIntent from uid " + configUid
-                                + "; presumably it had been cancelled.");
-            }
-        }
-    }
-}
diff --git a/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java b/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java
deleted file mode 100644
index fbda86f..0000000
--- a/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java
+++ /dev/null
@@ -1,770 +0,0 @@
-/*
- * Copyright (C) 2017 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.stats;
-
-import static android.os.Process.THREAD_PRIORITY_BACKGROUND;
-
-import android.app.AlarmManager;
-import android.app.AlarmManager.OnAlarmListener;
-import android.app.StatsManager;
-import android.content.BroadcastReceiver;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.os.Binder;
-import android.os.Bundle;
-import android.os.FileUtils;
-import android.os.Handler;
-import android.os.HandlerThread;
-import android.os.IBinder;
-import android.os.IStatsCompanionService;
-import android.os.IStatsd;
-import android.os.Looper;
-import android.os.ParcelFileDescriptor;
-import android.os.PowerManager;
-import android.os.RemoteException;
-import android.os.StatsFrameworkInitializer;
-import android.os.SystemClock;
-import android.os.UserHandle;
-import android.os.UserManager;
-import android.util.Log;
-import android.util.proto.ProtoOutputStream;
-
-import com.android.internal.annotations.GuardedBy;
-
-import java.io.File;
-import java.io.FileDescriptor;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-/**
- * Helper service for statsd (the native stats management service in cmds/statsd/).
- * Used for registering and receiving alarms on behalf of statsd.
- *
- * @hide
- */
-public class StatsCompanionService extends IStatsCompanionService.Stub {
-
-    private static final long MILLIS_IN_A_DAY = TimeUnit.DAYS.toMillis(1);
-
-    public static final String RESULT_RECEIVER_CONTROLLER_KEY = "controller_activity";
-    public static final String CONFIG_DIR = "/data/misc/stats-service";
-
-    static final String TAG = "StatsCompanionService";
-    static final boolean DEBUG = false;
-    /**
-     * Hard coded field ids of frameworks/base/cmds/statsd/src/uid_data.proto
-     * to be used in ProtoOutputStream.
-     */
-    private static final int APPLICATION_INFO_FIELD_ID = 1;
-    private static final int UID_FIELD_ID = 1;
-    private static final int VERSION_FIELD_ID = 2;
-    private static final int VERSION_STRING_FIELD_ID = 3;
-    private static final int PACKAGE_NAME_FIELD_ID = 4;
-    private static final int INSTALLER_FIELD_ID = 5;
-
-    public static final int DEATH_THRESHOLD = 10;
-
-    static final class CompanionHandler extends Handler {
-        CompanionHandler(Looper looper) {
-            super(looper);
-        }
-    }
-
-    private final Context mContext;
-    private final AlarmManager mAlarmManager;
-    @GuardedBy("sStatsdLock")
-    private static IStatsd sStatsd;
-    private static final Object sStatsdLock = new Object();
-
-    private final OnAlarmListener mPullingAlarmListener;
-    private final OnAlarmListener mPeriodicAlarmListener;
-
-    private StatsManagerService mStatsManagerService;
-
-    @GuardedBy("sStatsdLock")
-    private final HashSet<Long> mDeathTimeMillis = new HashSet<>();
-    @GuardedBy("sStatsdLock")
-    private final HashMap<Long, String> mDeletedFiles = new HashMap<>();
-    private final CompanionHandler mHandler;
-
-    // Flag that is set when PHASE_BOOT_COMPLETED is triggered in the StatsCompanion lifecycle.
-    private AtomicBoolean mBootCompleted = new AtomicBoolean(false);
-
-    public StatsCompanionService(Context context) {
-        super();
-        mContext = context;
-        mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
-        if (DEBUG) Log.d(TAG, "Registered receiver for ACTION_PACKAGE_REPLACED and ADDED.");
-        HandlerThread handlerThread = new HandlerThread(TAG);
-        handlerThread.start();
-        mHandler = new CompanionHandler(handlerThread.getLooper());
-
-        mPullingAlarmListener = new PullingAlarmListener(context);
-        mPeriodicAlarmListener = new PeriodicAlarmListener(context);
-    }
-
-    private final static int[] toIntArray(List<Integer> list) {
-        int[] ret = new int[list.size()];
-        for (int i = 0; i < ret.length; i++) {
-            ret[i] = list.get(i);
-        }
-        return ret;
-    }
-
-    private final static long[] toLongArray(List<Long> list) {
-        long[] ret = new long[list.size()];
-        for (int i = 0; i < ret.length; i++) {
-            ret[i] = list.get(i);
-        }
-        return ret;
-    }
-
-    /**
-     * Non-blocking call to retrieve a reference to statsd
-     *
-     * @return IStatsd object if statsd is ready, null otherwise.
-     */
-    private static IStatsd getStatsdNonblocking() {
-        synchronized (sStatsdLock) {
-            return sStatsd;
-        }
-    }
-
-    private static void informAllUids(Context context) {
-        ParcelFileDescriptor[] fds;
-        try {
-            fds = ParcelFileDescriptor.createPipe();
-        } catch (IOException e) {
-            Log.e(TAG, "Failed to create a pipe to send uid map data.", e);
-            return;
-        }
-        HandlerThread backgroundThread = new HandlerThread(
-                "statsCompanionService.bg", THREAD_PRIORITY_BACKGROUND);
-        backgroundThread.start();
-        Handler handler = new Handler(backgroundThread.getLooper());
-        handler.post(() -> {
-            UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE);
-            PackageManager pm = context.getPackageManager();
-            final List<UserHandle> users = um.getUserHandles(true);
-            if (DEBUG) {
-                Log.d(TAG, "Iterating over " + users.size() + " userHandles.");
-            }
-            IStatsd statsd = getStatsdNonblocking();
-            if (statsd == null) {
-                return;
-            }
-            try {
-                statsd.informAllUidData(fds[0]);
-            } catch (RemoteException e) {
-                Log.e(TAG, "Failed to send uid map to statsd");
-            }
-            try {
-                fds[0].close();
-            } catch (IOException e) {
-                Log.e(TAG, "Failed to close the read side of the pipe.", e);
-            }
-            final ParcelFileDescriptor writeFd = fds[1];
-            FileOutputStream fout = new ParcelFileDescriptor.AutoCloseOutputStream(writeFd);
-            try {
-                ProtoOutputStream output = new ProtoOutputStream(fout);
-                int numRecords = 0;
-                // Add in all the apps for every user/profile.
-                for (UserHandle userHandle : users) {
-                    List<PackageInfo> packagesPlusApex = getAllPackagesWithApex(pm, userHandle);
-                    for (int j = 0; j < packagesPlusApex.size(); j++) {
-                        if (packagesPlusApex.get(j).applicationInfo != null) {
-                            String installer;
-                            try {
-                                installer = pm.getInstallerPackageName(
-                                        packagesPlusApex.get(j).packageName);
-                            } catch (IllegalArgumentException e) {
-                                installer = "";
-                            }
-                            long applicationInfoToken =
-                                    output.start(ProtoOutputStream.FIELD_TYPE_MESSAGE
-                                            | ProtoOutputStream.FIELD_COUNT_REPEATED
-                                            | APPLICATION_INFO_FIELD_ID);
-                            output.write(ProtoOutputStream.FIELD_TYPE_INT32
-                                            | ProtoOutputStream.FIELD_COUNT_SINGLE | UID_FIELD_ID,
-                                    packagesPlusApex.get(j).applicationInfo.uid);
-                            output.write(ProtoOutputStream.FIELD_TYPE_INT64
-                                            | ProtoOutputStream.FIELD_COUNT_SINGLE
-                                            | VERSION_FIELD_ID,
-                                    packagesPlusApex.get(j).getLongVersionCode());
-                            output.write(ProtoOutputStream.FIELD_TYPE_STRING
-                                            | ProtoOutputStream.FIELD_COUNT_SINGLE
-                                            | VERSION_STRING_FIELD_ID,
-                                    packagesPlusApex.get(j).versionName);
-                            output.write(ProtoOutputStream.FIELD_TYPE_STRING
-                                    | ProtoOutputStream.FIELD_COUNT_SINGLE
-                                    | PACKAGE_NAME_FIELD_ID, packagesPlusApex.get(j).packageName);
-                            output.write(ProtoOutputStream.FIELD_TYPE_STRING
-                                            | ProtoOutputStream.FIELD_COUNT_SINGLE
-                                            | INSTALLER_FIELD_ID,
-                                    installer == null ? "" : installer);
-                            numRecords++;
-                            output.end(applicationInfoToken);
-                        }
-                    }
-                }
-                output.flush();
-                if (DEBUG) {
-                    Log.d(TAG, "Sent data for " + numRecords + " apps");
-                }
-            } finally {
-                FileUtils.closeQuietly(fout);
-                backgroundThread.quit();
-                backgroundThread.interrupt();
-            }
-        });
-    }
-
-    private static List<PackageInfo> getAllPackagesWithApex(PackageManager pm,
-            UserHandle userHandle) {
-        // We want all the uninstalled packages because uninstalled package uids can still be logged
-        // to statsd.
-        List<PackageInfo> allPackages = new ArrayList<>(
-                pm.getInstalledPackagesAsUser(PackageManager.MATCH_UNINSTALLED_PACKAGES
-                                | PackageManager.MATCH_ANY_USER,
-                        userHandle.getIdentifier()));
-        // We make a second query to package manager for the apex modules because package manager
-        // returns both installed and uninstalled apexes with
-        // PackageManager.MATCH_UNINSTALLED_PACKAGES flag. We only want active apexes because
-        // inactive apexes can conflict with active ones.
-        for (PackageInfo packageInfo : pm.getInstalledPackages(PackageManager.MATCH_APEX)) {
-            if (packageInfo.isApex) {
-                allPackages.add(packageInfo);
-            }
-        }
-        return allPackages;
-    }
-
-    private static class WakelockThread extends Thread {
-        private final PowerManager.WakeLock mWl;
-        private final Runnable mRunnable;
-
-        WakelockThread(Context context, String wakelockName, Runnable runnable) {
-            PowerManager powerManager = (PowerManager)
-                    context.getSystemService(Context.POWER_SERVICE);
-            mWl = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, wakelockName);
-            mRunnable = runnable;
-        }
-        @Override
-        public void run() {
-            try {
-                mRunnable.run();
-            } finally {
-                mWl.release();
-            }
-        }
-        @Override
-        public void start() {
-            mWl.acquire();
-            super.start();
-        }
-    }
-
-    private final static class AppUpdateReceiver extends BroadcastReceiver {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            /**
-             * App updates actually consist of REMOVE, ADD, and then REPLACE broadcasts. To avoid
-             * waste, we ignore the REMOVE and ADD broadcasts that contain the replacing flag.
-             * If we can't find the value for EXTRA_REPLACING, we default to false.
-             */
-            if (!intent.getAction().equals(Intent.ACTION_PACKAGE_REPLACED)
-                    && intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
-                return; // Keep only replacing or normal add and remove.
-            }
-            if (DEBUG) Log.d(TAG, "StatsCompanionService noticed an app was updated.");
-            synchronized (sStatsdLock) {
-                if (sStatsd == null) {
-                    Log.w(TAG, "Could not access statsd to inform it of an app update");
-                    return;
-                }
-                try {
-                    if (intent.getAction().equals(Intent.ACTION_PACKAGE_REMOVED)) {
-                        Bundle b = intent.getExtras();
-                        int uid = b.getInt(Intent.EXTRA_UID);
-                        boolean replacing = intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);
-                        if (!replacing) {
-                            // Don't bother sending an update if we're right about to get another
-                            // intent for the new version that's added.
-                            String app = intent.getData().getSchemeSpecificPart();
-                            sStatsd.informOnePackageRemoved(app, uid);
-                        }
-                    } else {
-                        PackageManager pm = context.getPackageManager();
-                        Bundle b = intent.getExtras();
-                        int uid = b.getInt(Intent.EXTRA_UID);
-                        String app = intent.getData().getSchemeSpecificPart();
-                        PackageInfo pi = pm.getPackageInfo(app, PackageManager.MATCH_ANY_USER);
-                        String installer;
-                        try {
-                            installer = pm.getInstallerPackageName(app);
-                        } catch (IllegalArgumentException e) {
-                            installer = "";
-                        }
-                        sStatsd.informOnePackage(
-                                app,
-                                uid,
-                                pi.getLongVersionCode(),
-                                pi.versionName == null ? "" : pi.versionName,
-                                installer == null ? "" : installer);
-                    }
-                } catch (Exception e) {
-                    Log.w(TAG, "Failed to inform statsd of an app update", e);
-                }
-            }
-        }
-    }
-
-    private static final class UserUpdateReceiver extends BroadcastReceiver {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            // Pull the latest state of UID->app name, version mapping.
-            // Needed since the new user basically has a version of every app.
-            informAllUids(context);
-        }
-    }
-
-    public final static class PullingAlarmListener implements OnAlarmListener {
-        private final Context mContext;
-
-        PullingAlarmListener(Context context) {
-            mContext = context;
-        }
-
-        @Override
-        public void onAlarm() {
-            if (DEBUG) {
-                Log.d(TAG, "Time to poll something.");
-            }
-            IStatsd statsd = getStatsdNonblocking();
-            if (statsd == null) {
-                Log.w(TAG, "Could not access statsd to inform it of pulling alarm firing.");
-                return;
-            }
-
-            // Wakelock needs to be retained while calling statsd.
-            Thread thread = new WakelockThread(mContext,
-                    PullingAlarmListener.class.getCanonicalName(), new Runnable() {
-                        @Override
-                        public void run() {
-                            try {
-                                statsd.informPollAlarmFired();
-                            } catch (RemoteException e) {
-                                Log.w(TAG, "Failed to inform statsd of pulling alarm firing.", e);
-                            }
-                        }
-                    });
-            thread.start();
-        }
-    }
-
-    public final static class PeriodicAlarmListener implements OnAlarmListener {
-        private final Context mContext;
-
-        PeriodicAlarmListener(Context context) {
-            mContext = context;
-        }
-
-        @Override
-        public void onAlarm() {
-            if (DEBUG) {
-                Log.d(TAG, "Time to trigger periodic alarm.");
-            }
-            IStatsd statsd = getStatsdNonblocking();
-            if (statsd == null) {
-                Log.w(TAG, "Could not access statsd to inform it of periodic alarm firing.");
-                return;
-            }
-
-            // Wakelock needs to be retained while calling statsd.
-            Thread thread = new WakelockThread(mContext,
-                    PeriodicAlarmListener.class.getCanonicalName(), new Runnable() {
-                        @Override
-                        public void run() {
-                            try {
-                                statsd.informAlarmForSubscriberTriggeringFired();
-                            } catch (RemoteException e) {
-                                Log.w(TAG, "Failed to inform statsd of periodic alarm firing.", e);
-                            }
-                        }
-                    });
-            thread.start();
-        }
-    }
-
-    public final static class ShutdownEventReceiver extends BroadcastReceiver {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            /**
-             * Skip immediately if intent is not relevant to device shutdown.
-             */
-            if (!intent.getAction().equals(Intent.ACTION_REBOOT)
-                    && !(intent.getAction().equals(Intent.ACTION_SHUTDOWN)
-                    && (intent.getFlags() & Intent.FLAG_RECEIVER_FOREGROUND) != 0)) {
-                return;
-            }
-
-            if (DEBUG) {
-                Log.i(TAG, "StatsCompanionService noticed a shutdown.");
-            }
-            IStatsd statsd = getStatsdNonblocking();
-            if (statsd == null) {
-                Log.w(TAG, "Could not access statsd to inform it of a shutdown event.");
-                return;
-            }
-            try {
-                // two way binder call
-                statsd.informDeviceShutdown();
-            } catch (Exception e) {
-                Log.w(TAG, "Failed to inform statsd of a shutdown event.", e);
-            }
-        }
-    }
-
-    @Override // Binder call
-    public void setAlarmForSubscriberTriggering(long timestampMs) {
-        StatsCompanion.enforceStatsdCallingUid();
-        if (DEBUG) {
-            Log.d(TAG,
-                    "Setting periodic alarm in about " + (timestampMs
-                            - SystemClock.elapsedRealtime()));
-        }
-        final long callingToken = Binder.clearCallingIdentity();
-        try {
-            // using ELAPSED_REALTIME, not ELAPSED_REALTIME_WAKEUP, so if device is asleep, will
-            // only fire when it awakens.
-            mAlarmManager.setExact(AlarmManager.ELAPSED_REALTIME, timestampMs, TAG + ".periodic",
-                    mPeriodicAlarmListener, mHandler);
-        } finally {
-            Binder.restoreCallingIdentity(callingToken);
-        }
-    }
-
-    @Override // Binder call
-    public void cancelAlarmForSubscriberTriggering() {
-        StatsCompanion.enforceStatsdCallingUid();
-        if (DEBUG) {
-            Log.d(TAG, "Cancelling periodic alarm");
-        }
-        final long callingToken = Binder.clearCallingIdentity();
-        try {
-            mAlarmManager.cancel(mPeriodicAlarmListener);
-        } finally {
-            Binder.restoreCallingIdentity(callingToken);
-        }
-    }
-
-    @Override // Binder call
-    public void setPullingAlarm(long nextPullTimeMs) {
-        StatsCompanion.enforceStatsdCallingUid();
-        if (DEBUG) {
-            Log.d(TAG, "Setting pulling alarm in about "
-                    + (nextPullTimeMs - SystemClock.elapsedRealtime()));
-        }
-        final long callingToken = Binder.clearCallingIdentity();
-        try {
-            // using ELAPSED_REALTIME, not ELAPSED_REALTIME_WAKEUP, so if device is asleep, will
-            // only fire when it awakens.
-            mAlarmManager.setExact(AlarmManager.ELAPSED_REALTIME, nextPullTimeMs, TAG + ".pull",
-                    mPullingAlarmListener, mHandler);
-        } finally {
-            Binder.restoreCallingIdentity(callingToken);
-        }
-    }
-
-    @Override // Binder call
-    public void cancelPullingAlarm() {
-        StatsCompanion.enforceStatsdCallingUid();
-        if (DEBUG) {
-            Log.d(TAG, "Cancelling pulling alarm");
-        }
-        final long callingToken = Binder.clearCallingIdentity();
-        try {
-            mAlarmManager.cancel(mPullingAlarmListener);
-        } finally {
-            Binder.restoreCallingIdentity(callingToken);
-        }
-    }
-
-    @Override // Binder call
-    public void statsdReady() {
-        StatsCompanion.enforceStatsdCallingUid();
-        if (DEBUG) {
-            Log.d(TAG, "learned that statsdReady");
-        }
-        sayHiToStatsd(); // tell statsd that we're ready too and link to it
-
-        final Intent intent = new Intent(StatsManager.ACTION_STATSD_STARTED);
-        // Retrieve list of broadcast receivers for this broadcast & send them directed broadcasts
-        // to wake them up (if they're in background).
-        List<ResolveInfo> resolveInfos =
-                mContext.getPackageManager().queryBroadcastReceiversAsUser(
-                        intent, 0, UserHandle.SYSTEM);
-        if (resolveInfos == null || resolveInfos.isEmpty()) {
-            return; // No need to send broadcast.
-        }
-
-        for (ResolveInfo resolveInfo : resolveInfos) {
-            Intent intentToSend = new Intent(intent);
-            intentToSend.setComponent(new ComponentName(
-                    resolveInfo.activityInfo.applicationInfo.packageName,
-                    resolveInfo.activityInfo.name));
-            mContext.sendBroadcastAsUser(intentToSend, UserHandle.SYSTEM,
-                    android.Manifest.permission.DUMP);
-        }
-    }
-
-    @Override // Binder call
-    public boolean checkPermission(String permission, int pid, int uid) {
-        StatsCompanion.enforceStatsdCallingUid();
-        return mContext.checkPermission(permission, pid, uid) == PackageManager.PERMISSION_GRANTED;
-    }
-
-    // Statsd related code
-
-    /**
-     * Fetches the statsd IBinder service. This is a blocking call that always refetches statsd
-     * instead of returning the cached sStatsd.
-     * Note: This should only be called from {@link #sayHiToStatsd()}. All other clients should use
-     * the cached sStatsd via {@link #getStatsdNonblocking()}.
-     */
-    private IStatsd fetchStatsdServiceLocked() {
-        sStatsd = IStatsd.Stub.asInterface(StatsFrameworkInitializer
-                .getStatsServiceManager()
-                .getStatsdServiceRegisterer()
-                .get());
-        return sStatsd;
-    }
-
-    private void registerStatsdDeathRecipient(IStatsd statsd, List<BroadcastReceiver> receivers) {
-        StatsdDeathRecipient deathRecipient = new StatsdDeathRecipient(statsd, receivers);
-
-        try {
-            statsd.asBinder().linkToDeath(deathRecipient, /*flags=*/0);
-        } catch (RemoteException e) {
-            Log.e(TAG, "linkToDeath (StatsdDeathRecipient) failed");
-            // Statsd has already died. Unregister receivers ourselves.
-            for (BroadcastReceiver receiver : receivers) {
-                mContext.unregisterReceiver(receiver);
-            }
-            synchronized (sStatsdLock) {
-                if (statsd == sStatsd) {
-                    statsdNotReadyLocked();
-                }
-            }
-        }
-    }
-
-    /**
-     * Now that the android system is ready, StatsCompanion is ready too, so inform statsd.
-     */
-    void systemReady() {
-        if (DEBUG) Log.d(TAG, "Learned that systemReady");
-        sayHiToStatsd();
-    }
-
-    void setStatsManagerService(StatsManagerService statsManagerService) {
-        mStatsManagerService = statsManagerService;
-    }
-
-    /**
-     * Tells statsd that statscompanion is ready. If the binder call returns, link to
-     * statsd.
-     */
-    private void sayHiToStatsd() {
-        IStatsd statsd;
-        synchronized (sStatsdLock) {
-            if (sStatsd != null && sStatsd.asBinder().isBinderAlive()) {
-                Log.e(TAG, "statsd has already been fetched before",
-                        new IllegalStateException("IStatsd object should be null or dead"));
-                return;
-            }
-            statsd = fetchStatsdServiceLocked();
-        }
-
-        if (statsd == null) {
-            Log.i(TAG, "Could not yet find statsd to tell it that StatsCompanion is alive.");
-            return;
-        }
-
-        // Cleann up from previous statsd - cancel any alarms that had been set. Do this here
-        // instead of in binder death because statsd can come back and set different alarms, or not
-        // want to set an alarm when it had been set. This guarantees that when we get a new statsd,
-        // we cancel any alarms before it is able to set them.
-        cancelPullingAlarm();
-        cancelAlarmForSubscriberTriggering();
-
-        if (DEBUG) Log.d(TAG, "Saying hi to statsd");
-        mStatsManagerService.statsdReady(statsd);
-        try {
-            statsd.statsCompanionReady();
-
-            BroadcastReceiver appUpdateReceiver = new AppUpdateReceiver();
-            BroadcastReceiver userUpdateReceiver = new UserUpdateReceiver();
-            BroadcastReceiver shutdownEventReceiver = new ShutdownEventReceiver();
-
-            // Setup broadcast receiver for updates.
-            IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_REPLACED);
-            filter.addAction(Intent.ACTION_PACKAGE_ADDED);
-            filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
-            filter.addDataScheme("package");
-            mContext.registerReceiverForAllUsers(appUpdateReceiver, filter, null, null);
-
-            // Setup receiver for user initialize (which happens once for a new user)
-            // and if a user is removed.
-            filter = new IntentFilter(Intent.ACTION_USER_INITIALIZE);
-            filter.addAction(Intent.ACTION_USER_REMOVED);
-            mContext.registerReceiverForAllUsers(userUpdateReceiver, filter, null, null);
-
-            // Setup receiver for device reboots or shutdowns.
-            filter = new IntentFilter(Intent.ACTION_REBOOT);
-            filter.addAction(Intent.ACTION_SHUTDOWN);
-            mContext.registerReceiverForAllUsers(shutdownEventReceiver, filter, null, null);
-
-            // Register death recipient.
-            List<BroadcastReceiver> broadcastReceivers =
-                    List.of(appUpdateReceiver, userUpdateReceiver, shutdownEventReceiver);
-            registerStatsdDeathRecipient(statsd, broadcastReceivers);
-
-            // Tell statsd that boot has completed. The signal may have already been sent, but since
-            // the signal-receiving function is idempotent, that's ok.
-            if (mBootCompleted.get()) {
-                statsd.bootCompleted();
-            }
-
-            // Pull the latest state of UID->app name, version mapping when statsd starts.
-            informAllUids(mContext);
-
-            Log.i(TAG, "Told statsd that StatsCompanionService is alive.");
-        } catch (RemoteException e) {
-            Log.e(TAG, "Failed to inform statsd that statscompanion is ready", e);
-        }
-    }
-
-    private class StatsdDeathRecipient implements IBinder.DeathRecipient {
-
-        private final IStatsd mStatsd;
-        private final List<BroadcastReceiver> mReceiversToUnregister;
-
-        StatsdDeathRecipient(IStatsd statsd, List<BroadcastReceiver> receivers) {
-            mStatsd = statsd;
-            mReceiversToUnregister = receivers;
-        }
-
-        // It is possible for binderDied to be called after a restarted statsd calls statsdReady,
-        // but that's alright because the code does not assume an ordering of the two calls.
-        @Override
-        public void binderDied() {
-            Log.i(TAG, "Statsd is dead - erase all my knowledge, except pullers");
-            synchronized (sStatsdLock) {
-                long now = SystemClock.elapsedRealtime();
-                for (Long timeMillis : mDeathTimeMillis) {
-                    long ageMillis = now - timeMillis;
-                    if (ageMillis > MILLIS_IN_A_DAY) {
-                        mDeathTimeMillis.remove(timeMillis);
-                    }
-                }
-                for (Long timeMillis : mDeletedFiles.keySet()) {
-                    long ageMillis = now - timeMillis;
-                    if (ageMillis > MILLIS_IN_A_DAY * 7) {
-                        mDeletedFiles.remove(timeMillis);
-                    }
-                }
-                mDeathTimeMillis.add(now);
-                if (mDeathTimeMillis.size() >= DEATH_THRESHOLD) {
-                    mDeathTimeMillis.clear();
-                    File[] configs = new File(CONFIG_DIR).listFiles();
-                    if (configs != null && configs.length > 0) {
-                        String fileName = configs[0].getName();
-                        if (configs[0].delete()) {
-                            mDeletedFiles.put(now, fileName);
-                        }
-                    }
-                }
-
-                // Unregister receivers on death because receivers can only be unregistered once.
-                // Otherwise, an IllegalArgumentException is thrown.
-                for (BroadcastReceiver receiver: mReceiversToUnregister) {
-                    mContext.unregisterReceiver(receiver);
-                }
-
-                // It's possible for statsd to have restarted and called statsdReady, causing a new
-                // sStatsd binder object to be fetched, before the binderDied callback runs. Only
-                // call #statsdNotReadyLocked if that hasn't happened yet.
-                if (mStatsd == sStatsd) {
-                    statsdNotReadyLocked();
-                }
-            }
-        }
-    }
-
-    private void statsdNotReadyLocked() {
-        sStatsd = null;
-        mStatsManagerService.statsdNotReady();
-    }
-
-    void bootCompleted() {
-        mBootCompleted.set(true);
-        IStatsd statsd = getStatsdNonblocking();
-        if (statsd == null) {
-            // Statsd is not yet ready.
-            // Delay the boot completed ping to {@link #sayHiToStatsd()}
-            return;
-        }
-        try {
-            statsd.bootCompleted();
-        } catch (RemoteException e) {
-            Log.e(TAG, "Failed to notify statsd that boot completed");
-        }
-    }
-
-    @Override
-    protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
-        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
-                != PackageManager.PERMISSION_GRANTED) {
-            return;
-        }
-
-        synchronized (sStatsdLock) {
-            writer.println("Number of configuration files deleted: " + mDeletedFiles.size());
-            if (mDeletedFiles.size() > 0) {
-                writer.println("  timestamp, deleted file name");
-            }
-            long lastBootMillis =
-                    SystemClock.currentThreadTimeMillis() - SystemClock.elapsedRealtime();
-            for (Long elapsedMillis : mDeletedFiles.keySet()) {
-                long deletionMillis = lastBootMillis + elapsedMillis;
-                writer.println("  " + deletionMillis + ", " + mDeletedFiles.get(elapsedMillis));
-            }
-        }
-    }
-}
diff --git a/apex/statsd/service/java/com/android/server/stats/StatsManagerService.java b/apex/statsd/service/java/com/android/server/stats/StatsManagerService.java
deleted file mode 100644
index 1e3846b..0000000
--- a/apex/statsd/service/java/com/android/server/stats/StatsManagerService.java
+++ /dev/null
@@ -1,668 +0,0 @@
-/*
- * Copyright (C) 2019 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.stats;
-
-import static com.android.server.stats.StatsCompanion.PendingIntentRef;
-
-import android.Manifest;
-import android.annotation.Nullable;
-import android.app.AppOpsManager;
-import android.app.PendingIntent;
-import android.content.Context;
-import android.os.Binder;
-import android.os.IPullAtomCallback;
-import android.os.IStatsManagerService;
-import android.os.IStatsd;
-import android.os.PowerManager;
-import android.os.Process;
-import android.os.RemoteException;
-import android.util.ArrayMap;
-import android.util.Log;
-
-import com.android.internal.annotations.GuardedBy;
-
-import java.util.Map;
-import java.util.Objects;
-
-/**
- * Service for {@link android.app.StatsManager}.
- *
- * @hide
- */
-public class StatsManagerService extends IStatsManagerService.Stub {
-
-    private static final String TAG = "StatsManagerService";
-    private static final boolean DEBUG = false;
-
-    private static final int STATSD_TIMEOUT_MILLIS = 5000;
-
-    private static final String USAGE_STATS_PERMISSION_OPS = "android:get_usage_stats";
-
-    @GuardedBy("mLock")
-    private IStatsd mStatsd;
-    private final Object mLock = new Object();
-
-    private StatsCompanionService mStatsCompanionService;
-    private Context mContext;
-
-    @GuardedBy("mLock")
-    private ArrayMap<ConfigKey, PendingIntentRef> mDataFetchPirMap = new ArrayMap<>();
-    @GuardedBy("mLock")
-    private ArrayMap<Integer, PendingIntentRef> mActiveConfigsPirMap = new ArrayMap<>();
-    @GuardedBy("mLock")
-    private ArrayMap<ConfigKey, ArrayMap<Long, PendingIntentRef>> mBroadcastSubscriberPirMap =
-            new ArrayMap<>();
-
-    public StatsManagerService(Context context) {
-        super();
-        mContext = context;
-    }
-
-    private static class ConfigKey {
-        private final int mUid;
-        private final long mConfigId;
-
-        ConfigKey(int uid, long configId) {
-            mUid = uid;
-            mConfigId = configId;
-        }
-
-        public int getUid() {
-            return mUid;
-        }
-
-        public long getConfigId() {
-            return mConfigId;
-        }
-
-        @Override
-        public int hashCode() {
-            return Objects.hash(mUid, mConfigId);
-        }
-
-        @Override
-        public boolean equals(Object obj) {
-            if (obj instanceof ConfigKey) {
-                ConfigKey other = (ConfigKey) obj;
-                return this.mUid == other.getUid() && this.mConfigId == other.getConfigId();
-            }
-            return false;
-        }
-    }
-
-    private static class PullerKey {
-        private final int mUid;
-        private final int mAtomTag;
-
-        PullerKey(int uid, int atom) {
-            mUid = uid;
-            mAtomTag = atom;
-        }
-
-        public int getUid() {
-            return mUid;
-        }
-
-        public int getAtom() {
-            return mAtomTag;
-        }
-
-        @Override
-        public int hashCode() {
-            return Objects.hash(mUid, mAtomTag);
-        }
-
-        @Override
-        public boolean equals(Object obj) {
-            if (obj instanceof PullerKey) {
-                PullerKey other = (PullerKey) obj;
-                return this.mUid == other.getUid() && this.mAtomTag == other.getAtom();
-            }
-            return false;
-        }
-    }
-
-    private static class PullerValue {
-        private final long mCoolDownMillis;
-        private final long mTimeoutMillis;
-        private final int[] mAdditiveFields;
-        private final IPullAtomCallback mCallback;
-
-        PullerValue(long coolDownMillis, long timeoutMillis, int[] additiveFields,
-                IPullAtomCallback callback) {
-            mCoolDownMillis = coolDownMillis;
-            mTimeoutMillis = timeoutMillis;
-            mAdditiveFields = additiveFields;
-            mCallback = callback;
-        }
-
-        public long getCoolDownMillis() {
-            return mCoolDownMillis;
-        }
-
-        public long getTimeoutMillis() {
-            return mTimeoutMillis;
-        }
-
-        public int[] getAdditiveFields() {
-            return mAdditiveFields;
-        }
-
-        public IPullAtomCallback getCallback() {
-            return mCallback;
-        }
-    }
-
-    private final ArrayMap<PullerKey, PullerValue> mPullers = new ArrayMap<>();
-
-    @Override
-    public void registerPullAtomCallback(int atomTag, long coolDownMillis, long timeoutMillis,
-            int[] additiveFields, IPullAtomCallback pullerCallback) {
-        enforceRegisterStatsPullAtomPermission();
-        if (pullerCallback == null) {
-            Log.w(TAG, "Puller callback is null for atom " + atomTag);
-            return;
-        }
-        int callingUid = Binder.getCallingUid();
-        PullerKey key = new PullerKey(callingUid, atomTag);
-        PullerValue val =
-                new PullerValue(coolDownMillis, timeoutMillis, additiveFields, pullerCallback);
-
-        // Always cache the puller in StatsManagerService. If statsd is down, we will register the
-        // puller when statsd comes back up.
-        synchronized (mLock) {
-            mPullers.put(key, val);
-        }
-
-        IStatsd statsd = getStatsdNonblocking();
-        if (statsd == null) {
-            return;
-        }
-
-        final long token = Binder.clearCallingIdentity();
-        try {
-            statsd.registerPullAtomCallback(callingUid, atomTag, coolDownMillis, timeoutMillis,
-                    additiveFields, pullerCallback);
-        } catch (RemoteException e) {
-            Log.e(TAG, "Failed to access statsd to register puller for atom " + atomTag);
-        } finally {
-            Binder.restoreCallingIdentity(token);
-        }
-    }
-
-    @Override
-    public void unregisterPullAtomCallback(int atomTag) {
-        enforceRegisterStatsPullAtomPermission();
-        int callingUid = Binder.getCallingUid();
-        PullerKey key = new PullerKey(callingUid, atomTag);
-
-        // Always remove the puller from StatsManagerService even if statsd is down. When statsd
-        // comes back up, we will not re-register the removed puller.
-        synchronized (mLock) {
-            mPullers.remove(key);
-        }
-
-        IStatsd statsd = getStatsdNonblocking();
-        if (statsd == null) {
-            return;
-        }
-
-        final long token = Binder.clearCallingIdentity();
-        try {
-            statsd.unregisterPullAtomCallback(callingUid, atomTag);
-        } catch (RemoteException e) {
-            Log.e(TAG, "Failed to access statsd to unregister puller for atom " + atomTag);
-        } finally {
-            Binder.restoreCallingIdentity(token);
-        }
-    }
-
-    @Override
-    public void setDataFetchOperation(long configId, PendingIntent pendingIntent,
-            String packageName) {
-        enforceDumpAndUsageStatsPermission(packageName);
-        int callingUid = Binder.getCallingUid();
-        final long token = Binder.clearCallingIdentity();
-        PendingIntentRef pir = new PendingIntentRef(pendingIntent, mContext);
-        ConfigKey key = new ConfigKey(callingUid, configId);
-        // We add the PIR to a map so we can reregister if statsd is unavailable.
-        synchronized (mLock) {
-            mDataFetchPirMap.put(key, pir);
-        }
-        try {
-            IStatsd statsd = getStatsdNonblocking();
-            if (statsd != null) {
-                statsd.setDataFetchOperation(configId, pir, callingUid);
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "Failed to setDataFetchOperation with statsd");
-        } finally {
-            Binder.restoreCallingIdentity(token);
-        }
-    }
-
-    @Override
-    public void removeDataFetchOperation(long configId, String packageName) {
-        enforceDumpAndUsageStatsPermission(packageName);
-        int callingUid = Binder.getCallingUid();
-        final long token = Binder.clearCallingIdentity();
-        ConfigKey key = new ConfigKey(callingUid, configId);
-        synchronized (mLock) {
-            mDataFetchPirMap.remove(key);
-        }
-        try {
-            IStatsd statsd = getStatsdNonblocking();
-            if (statsd != null) {
-                statsd.removeDataFetchOperation(configId, callingUid);
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "Failed to removeDataFetchOperation with statsd");
-        } finally {
-            Binder.restoreCallingIdentity(token);
-        }
-    }
-
-    @Override
-    public long[] setActiveConfigsChangedOperation(PendingIntent pendingIntent,
-            String packageName) {
-        enforceDumpAndUsageStatsPermission(packageName);
-        int callingUid = Binder.getCallingUid();
-        final long token = Binder.clearCallingIdentity();
-        PendingIntentRef pir = new PendingIntentRef(pendingIntent, mContext);
-        // We add the PIR to a map so we can reregister if statsd is unavailable.
-        synchronized (mLock) {
-            mActiveConfigsPirMap.put(callingUid, pir);
-        }
-        try {
-            IStatsd statsd = getStatsdNonblocking();
-            if (statsd != null) {
-                return statsd.setActiveConfigsChangedOperation(pir, callingUid);
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "Failed to setActiveConfigsChangedOperation with statsd");
-        } finally {
-            Binder.restoreCallingIdentity(token);
-        }
-        return new long[] {};
-    }
-
-    @Override
-    public void removeActiveConfigsChangedOperation(String packageName) {
-        enforceDumpAndUsageStatsPermission(packageName);
-        int callingUid = Binder.getCallingUid();
-        final long token = Binder.clearCallingIdentity();
-        synchronized (mLock) {
-            mActiveConfigsPirMap.remove(callingUid);
-        }
-        try {
-            IStatsd statsd = getStatsdNonblocking();
-            if (statsd != null) {
-                statsd.removeActiveConfigsChangedOperation(callingUid);
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "Failed to removeActiveConfigsChangedOperation with statsd");
-        } finally {
-            Binder.restoreCallingIdentity(token);
-        }
-    }
-
-    @Override
-    public void setBroadcastSubscriber(long configId, long subscriberId,
-            PendingIntent pendingIntent, String packageName) {
-        enforceDumpAndUsageStatsPermission(packageName);
-        int callingUid = Binder.getCallingUid();
-        final long token = Binder.clearCallingIdentity();
-        PendingIntentRef pir = new PendingIntentRef(pendingIntent, mContext);
-        ConfigKey key = new ConfigKey(callingUid, configId);
-        // We add the PIR to a map so we can reregister if statsd is unavailable.
-        synchronized (mLock) {
-            ArrayMap<Long, PendingIntentRef> innerMap = mBroadcastSubscriberPirMap
-                    .getOrDefault(key, new ArrayMap<>());
-            innerMap.put(subscriberId, pir);
-            mBroadcastSubscriberPirMap.put(key, innerMap);
-        }
-        try {
-            IStatsd statsd = getStatsdNonblocking();
-            if (statsd != null) {
-                statsd.setBroadcastSubscriber(
-                        configId, subscriberId, pir, callingUid);
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "Failed to setBroadcastSubscriber with statsd");
-        } finally {
-            Binder.restoreCallingIdentity(token);
-        }
-    }
-
-    @Override
-    public void unsetBroadcastSubscriber(long configId, long subscriberId, String packageName) {
-        enforceDumpAndUsageStatsPermission(packageName);
-        int callingUid = Binder.getCallingUid();
-        final long token = Binder.clearCallingIdentity();
-        ConfigKey key = new ConfigKey(callingUid, configId);
-        synchronized (mLock) {
-            ArrayMap<Long, PendingIntentRef> innerMap = mBroadcastSubscriberPirMap
-                    .getOrDefault(key, new ArrayMap<>());
-            innerMap.remove(subscriberId);
-            if (innerMap.isEmpty()) {
-                mBroadcastSubscriberPirMap.remove(key);
-            }
-        }
-        try {
-            IStatsd statsd = getStatsdNonblocking();
-            if (statsd != null) {
-                statsd.unsetBroadcastSubscriber(configId, subscriberId, callingUid);
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "Failed to unsetBroadcastSubscriber with statsd");
-        } finally {
-            Binder.restoreCallingIdentity(token);
-        }
-    }
-
-    @Override
-    public long[] getRegisteredExperimentIds() throws IllegalStateException {
-        enforceDumpAndUsageStatsPermission(null);
-        final long token = Binder.clearCallingIdentity();
-        try {
-            IStatsd statsd = waitForStatsd();
-            if (statsd != null) {
-                return statsd.getRegisteredExperimentIds();
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "Failed to getRegisteredExperimentIds with statsd");
-            throw new IllegalStateException(e.getMessage(), e);
-        } finally {
-            Binder.restoreCallingIdentity(token);
-        }
-        throw new IllegalStateException("Failed to connect to statsd to registerExperimentIds");
-    }
-
-    @Override
-    public byte[] getMetadata(String packageName) throws IllegalStateException {
-        enforceDumpAndUsageStatsPermission(packageName);
-        final long token = Binder.clearCallingIdentity();
-        try {
-            IStatsd statsd = waitForStatsd();
-            if (statsd != null) {
-                return statsd.getMetadata();
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "Failed to getMetadata with statsd");
-            throw new IllegalStateException(e.getMessage(), e);
-        } finally {
-            Binder.restoreCallingIdentity(token);
-        }
-        throw new IllegalStateException("Failed to connect to statsd to getMetadata");
-    }
-
-    @Override
-    public byte[] getData(long key, String packageName) throws IllegalStateException {
-        enforceDumpAndUsageStatsPermission(packageName);
-        PowerManager powerManager = (PowerManager)
-                mContext.getSystemService(Context.POWER_SERVICE);
-        PowerManager.WakeLock wl = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
-                /*tag=*/ StatsManagerService.class.getCanonicalName());
-        int callingUid = Binder.getCallingUid();
-        final long token = Binder.clearCallingIdentity();
-        wl.acquire();
-        try {
-            IStatsd statsd = waitForStatsd();
-            if (statsd != null) {
-                return statsd.getData(key, callingUid);
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "Failed to getData with statsd");
-            throw new IllegalStateException(e.getMessage(), e);
-        } finally {
-            wl.release();
-            Binder.restoreCallingIdentity(token);
-        }
-        throw new IllegalStateException("Failed to connect to statsd to getData");
-    }
-
-    @Override
-    public void addConfiguration(long configId, byte[] config, String packageName)
-            throws IllegalStateException {
-        enforceDumpAndUsageStatsPermission(packageName);
-        int callingUid = Binder.getCallingUid();
-        final long token = Binder.clearCallingIdentity();
-        try {
-            IStatsd statsd = waitForStatsd();
-            if (statsd != null) {
-                statsd.addConfiguration(configId, config, callingUid);
-                return;
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "Failed to addConfiguration with statsd");
-            throw new IllegalStateException(e.getMessage(), e);
-        } finally {
-            Binder.restoreCallingIdentity(token);
-        }
-        throw new IllegalStateException("Failed to connect to statsd to addConfig");
-    }
-
-    @Override
-    public void removeConfiguration(long configId, String packageName)
-            throws IllegalStateException {
-        enforceDumpAndUsageStatsPermission(packageName);
-        int callingUid = Binder.getCallingUid();
-        final long token = Binder.clearCallingIdentity();
-        try {
-            IStatsd statsd = waitForStatsd();
-            if (statsd != null) {
-                statsd.removeConfiguration(configId, callingUid);
-                return;
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "Failed to removeConfiguration with statsd");
-            throw new IllegalStateException(e.getMessage(), e);
-        } finally {
-            Binder.restoreCallingIdentity(token);
-        }
-        throw new IllegalStateException("Failed to connect to statsd to removeConfig");
-    }
-
-    void setStatsCompanionService(StatsCompanionService statsCompanionService) {
-        mStatsCompanionService = statsCompanionService;
-    }
-
-    /**
-     * Checks that the caller has both DUMP and PACKAGE_USAGE_STATS permissions. Also checks that
-     * the caller has USAGE_STATS_PERMISSION_OPS for the specified packageName if it is not null.
-     *
-     * @param packageName The packageName to check USAGE_STATS_PERMISSION_OPS.
-     */
-    private void enforceDumpAndUsageStatsPermission(@Nullable String packageName) {
-        int callingUid = Binder.getCallingUid();
-        int callingPid = Binder.getCallingPid();
-
-        if (callingPid == Process.myPid()) {
-            return;
-        }
-
-        mContext.enforceCallingPermission(Manifest.permission.DUMP, null);
-        mContext.enforceCallingPermission(Manifest.permission.PACKAGE_USAGE_STATS, null);
-
-        if (packageName == null) {
-            return;
-        }
-        AppOpsManager appOpsManager = (AppOpsManager) mContext
-                .getSystemService(Context.APP_OPS_SERVICE);
-        switch (appOpsManager.noteOp(USAGE_STATS_PERMISSION_OPS,
-                Binder.getCallingUid(), packageName, null, null)) {
-            case AppOpsManager.MODE_ALLOWED:
-            case AppOpsManager.MODE_DEFAULT:
-                break;
-            default:
-                throw new SecurityException(
-                        String.format("UID %d / PID %d lacks app-op %s",
-                                callingUid, callingPid, USAGE_STATS_PERMISSION_OPS)
-                );
-        }
-    }
-
-    private void enforceRegisterStatsPullAtomPermission() {
-        mContext.enforceCallingOrSelfPermission(
-                android.Manifest.permission.REGISTER_STATS_PULL_ATOM,
-                "Need REGISTER_STATS_PULL_ATOM permission.");
-    }
-
-
-    /**
-     * Clients should call this if blocking until statsd to be ready is desired
-     *
-     * @return IStatsd object if statsd becomes ready within the timeout, null otherwise.
-     */
-    private IStatsd waitForStatsd() {
-        synchronized (mLock) {
-            if (mStatsd == null) {
-                try {
-                    mLock.wait(STATSD_TIMEOUT_MILLIS);
-                } catch (InterruptedException e) {
-                    Log.e(TAG, "wait for statsd interrupted");
-                }
-            }
-            return mStatsd;
-        }
-    }
-
-    /**
-     * Clients should call this to receive a reference to statsd.
-     *
-     * @return IStatsd object if statsd is ready, null otherwise.
-     */
-    private IStatsd getStatsdNonblocking() {
-        synchronized (mLock) {
-            return mStatsd;
-        }
-    }
-
-    /**
-     * Called from {@link StatsCompanionService}.
-     *
-     * Tells StatsManagerService that Statsd is ready and updates
-     * Statsd with the contents of our local cache.
-     */
-    void statsdReady(IStatsd statsd) {
-        synchronized (mLock) {
-            mStatsd = statsd;
-            mLock.notify();
-        }
-        sayHiToStatsd(statsd);
-    }
-
-    /**
-     * Called from {@link StatsCompanionService}.
-     *
-     * Tells StatsManagerService that Statsd is no longer ready
-     * and we should no longer make binder calls with statsd.
-     */
-    void statsdNotReady() {
-        synchronized (mLock) {
-            mStatsd = null;
-        }
-    }
-
-    private void sayHiToStatsd(IStatsd statsd) {
-        if (statsd == null) {
-            return;
-        }
-
-        final long token = Binder.clearCallingIdentity();
-        try {
-            registerAllPullers(statsd);
-            registerAllDataFetchOperations(statsd);
-            registerAllActiveConfigsChangedOperations(statsd);
-            registerAllBroadcastSubscribers(statsd);
-        } catch (RemoteException e) {
-            Log.e(TAG, "StatsManager failed to (re-)register data with statsd");
-        } finally {
-            Binder.restoreCallingIdentity(token);
-        }
-    }
-
-    // Pre-condition: the Binder calling identity has already been cleared
-    private void registerAllPullers(IStatsd statsd) throws RemoteException {
-        // Since we do not want to make an IPC with the lock held, we first create a copy of the
-        // data with the lock held before iterating through the map.
-        ArrayMap<PullerKey, PullerValue> pullersCopy;
-        synchronized (mLock) {
-            pullersCopy = new ArrayMap<>(mPullers);
-        }
-
-        for (Map.Entry<PullerKey, PullerValue> entry : pullersCopy.entrySet()) {
-            PullerKey key = entry.getKey();
-            PullerValue value = entry.getValue();
-            statsd.registerPullAtomCallback(key.getUid(), key.getAtom(), value.getCoolDownMillis(),
-                    value.getTimeoutMillis(), value.getAdditiveFields(), value.getCallback());
-        }
-        statsd.allPullersFromBootRegistered();
-    }
-
-    // Pre-condition: the Binder calling identity has already been cleared
-    private void registerAllDataFetchOperations(IStatsd statsd) throws RemoteException {
-        // Since we do not want to make an IPC with the lock held, we first create a copy of the
-        // data with the lock held before iterating through the map.
-        ArrayMap<ConfigKey, PendingIntentRef> dataFetchCopy;
-        synchronized (mLock) {
-            dataFetchCopy = new ArrayMap<>(mDataFetchPirMap);
-        }
-
-        for (Map.Entry<ConfigKey, PendingIntentRef> entry : dataFetchCopy.entrySet()) {
-            ConfigKey key = entry.getKey();
-            statsd.setDataFetchOperation(key.getConfigId(), entry.getValue(), key.getUid());
-        }
-    }
-
-    // Pre-condition: the Binder calling identity has already been cleared
-    private void registerAllActiveConfigsChangedOperations(IStatsd statsd) throws RemoteException {
-        // Since we do not want to make an IPC with the lock held, we first create a copy of the
-        // data with the lock held before iterating through the map.
-        ArrayMap<Integer, PendingIntentRef> activeConfigsChangedCopy;
-        synchronized (mLock) {
-            activeConfigsChangedCopy = new ArrayMap<>(mActiveConfigsPirMap);
-        }
-
-        for (Map.Entry<Integer, PendingIntentRef> entry : activeConfigsChangedCopy.entrySet()) {
-            statsd.setActiveConfigsChangedOperation(entry.getValue(), entry.getKey());
-        }
-    }
-
-    // Pre-condition: the Binder calling identity has already been cleared
-    private void registerAllBroadcastSubscribers(IStatsd statsd) throws RemoteException {
-        // Since we do not want to make an IPC with the lock held, we first create a deep copy of
-        // the data with the lock held before iterating through the map.
-        ArrayMap<ConfigKey, ArrayMap<Long, PendingIntentRef>> broadcastSubscriberCopy =
-                new ArrayMap<>();
-        synchronized (mLock) {
-            for (Map.Entry<ConfigKey, ArrayMap<Long, PendingIntentRef>> entry :
-                    mBroadcastSubscriberPirMap.entrySet()) {
-                broadcastSubscriberCopy.put(entry.getKey(), new ArrayMap(entry.getValue()));
-            }
-        }
-
-        for (Map.Entry<ConfigKey, ArrayMap<Long, PendingIntentRef>> entry :
-                mBroadcastSubscriberPirMap.entrySet()) {
-            ConfigKey configKey = entry.getKey();
-            for (Map.Entry<Long, PendingIntentRef> subscriberEntry : entry.getValue().entrySet()) {
-                statsd.setBroadcastSubscriber(configKey.getConfigId(), subscriberEntry.getKey(),
-                        subscriberEntry.getValue(), configKey.getUid());
-            }
-        }
-    }
-}
diff --git a/apex/statsd/statsd.rc b/apex/statsd/statsd.rc
deleted file mode 100644
index 605da2a..0000000
--- a/apex/statsd/statsd.rc
+++ /dev/null
@@ -1,20 +0,0 @@
-# Copyright (C) 2017 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.
-
-service statsd /apex/com.android.os.statsd/bin/statsd
-    class main
-    socket statsdw dgram+passcred 0222 statsd statsd
-    user statsd
-    group statsd log
-    writepid /dev/cpuset/system-background/tasks
diff --git a/apex/statsd/testing/Android.bp b/apex/statsd/testing/Android.bp
deleted file mode 100644
index a9cd0cc..0000000
--- a/apex/statsd/testing/Android.bp
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (C) 2019 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.
-
-apex_test {
-    name: "test_com.android.os.statsd",
-    visibility: [
-        "//system/apex/tests",
-    ],
-    defaults: ["com.android.os.statsd-defaults"],
-    manifest: "test_manifest.json",
-    file_contexts: ":com.android.os.statsd-file_contexts",
-    // Test APEX, should never be installed
-    installable: false,
-}
diff --git a/apex/statsd/testing/test_manifest.json b/apex/statsd/testing/test_manifest.json
deleted file mode 100644
index 57343d3e..0000000
--- a/apex/statsd/testing/test_manifest.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
-  "name": "com.android.os.statsd",
-  "version": 2147483647
-}
diff --git a/apex/statsd/tests/libstatspull/Android.bp b/apex/statsd/tests/libstatspull/Android.bp
deleted file mode 100644
index 05b3e04..0000000
--- a/apex/statsd/tests/libstatspull/Android.bp
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright (C) 2019 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.
-
-android_test {
-    name: "LibStatsPullTests",
-    static_libs: [
-        "androidx.test.rules",
-        "platformprotoslite",
-        "statsdprotolite",
-        "truth-prebuilt",
-    ],
-    libs: [
-        "android.test.runner.stubs",
-        "android.test.base.stubs",
-    ],
-    jni_libs: [
-        "libstatspull_testhelper",
-    ],
-    srcs: [
-        "src/**/*.java",
-        "protos/**/*.proto",
-        ],
-    test_suites: [
-        "device-tests",
-        "mts",
-    ],
-    platform_apis: true,
-    privileged: true,
-    certificate: "platform",
-    compile_multilib: "both",
-}
-
-cc_library_shared {
-    name: "libstatspull_testhelper",
-    srcs: ["jni/stats_pull_helper.cpp"],
-    cflags: [
-        "-Wall",
-        "-Werror",
-    ],
-    shared_libs: [
-        "libbinder_ndk",
-        "statsd-aidl-ndk_platform",
-    ],
-    static_libs: [
-        "libstatspull_private",
-        "libstatssocket_private",
-        "libutils",
-        "libcutils",
-    ],
-}
diff --git a/apex/statsd/tests/libstatspull/AndroidManifest.xml b/apex/statsd/tests/libstatspull/AndroidManifest.xml
deleted file mode 100644
index 0c669b0..0000000
--- a/apex/statsd/tests/libstatspull/AndroidManifest.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- -->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-          package="com.android.internal.os.statsd.libstats" >
-
-
-    <uses-permission android:name="android.permission.DUMP" />
-    <uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" />
-    <uses-permission android:name="android.permission.REGISTER_STATS_PULL_ATOM" />
-
-    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
-                     android:targetPackage="com.android.internal.os.statsd.libstats"
-                     android:label="Tests for libstatspull">
-    </instrumentation>
-</manifest>
-
diff --git a/apex/statsd/tests/libstatspull/jni/stats_pull_helper.cpp b/apex/statsd/tests/libstatspull/jni/stats_pull_helper.cpp
deleted file mode 100644
index 166592d..0000000
--- a/apex/statsd/tests/libstatspull/jni/stats_pull_helper.cpp
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2019, 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.
- */
-
-#include <jni.h>
-#include <log/log.h>
-#include <stats_event.h>
-#include <stats_pull_atom_callback.h>
-
-#include <chrono>
-#include <thread>
-
-using std::this_thread::sleep_for;
-
-namespace {
-static int32_t sAtomTag;
-static int32_t sPullReturnVal;
-static int64_t sLatencyMillis;
-static int32_t sAtomsPerPull;
-static int32_t sNumPulls = 0;
-
-static AStatsManager_PullAtomCallbackReturn pullAtomCallback(int32_t atomTag, AStatsEventList* data,
-                                                             void* /*cookie*/) {
-    sNumPulls++;
-    sleep_for(std::chrono::milliseconds(sLatencyMillis));
-    for (int i = 0; i < sAtomsPerPull; i++) {
-        AStatsEvent* event = AStatsEventList_addStatsEvent(data);
-        AStatsEvent_setAtomId(event, atomTag);
-        AStatsEvent_writeInt64(event, (int64_t) sNumPulls);
-        AStatsEvent_build(event);
-    }
-    return sPullReturnVal;
-}
-
-extern "C" JNIEXPORT void JNICALL
-Java_com_android_internal_os_statsd_libstats_LibStatsPullTests_setStatsPuller(
-        JNIEnv* /*env*/, jobject /* this */, jint atomTag, jlong timeoutMillis,
-        jlong coolDownMillis, jint pullRetVal, jlong latencyMillis, int atomsPerPull) {
-    sAtomTag = atomTag;
-    sPullReturnVal = pullRetVal;
-    sLatencyMillis = latencyMillis;
-    sAtomsPerPull = atomsPerPull;
-    sNumPulls = 0;
-    AStatsManager_PullAtomMetadata* metadata = AStatsManager_PullAtomMetadata_obtain();
-    AStatsManager_PullAtomMetadata_setCoolDownMillis(metadata, coolDownMillis);
-    AStatsManager_PullAtomMetadata_setTimeoutMillis(metadata, timeoutMillis);
-
-    AStatsManager_setPullAtomCallback(sAtomTag, metadata, &pullAtomCallback, nullptr);
-    AStatsManager_PullAtomMetadata_release(metadata);
-}
-
-extern "C" JNIEXPORT void JNICALL
-Java_com_android_internal_os_statsd_libstats_LibStatsPullTests_clearStatsPuller(JNIEnv* /*env*/,
-                                                                                jobject /* this */,
-                                                                                jint /*atomTag*/) {
-    AStatsManager_clearPullAtomCallback(sAtomTag);
-}
-} // namespace
diff --git a/apex/statsd/tests/libstatspull/protos/test_atoms.proto b/apex/statsd/tests/libstatspull/protos/test_atoms.proto
deleted file mode 100644
index 56c1b53..0000000
--- a/apex/statsd/tests/libstatspull/protos/test_atoms.proto
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-syntax = "proto2";
-
-package com.android.internal.os.statsd.protos;
-
-option java_package = "com.android.internal.os.statsd.protos";
-option java_outer_classname = "TestAtoms";
-
-message PullCallbackAtomWrapper {
-  optional PullCallbackAtom pull_callback_atom = 150030;
-}
-
-message PullCallbackAtom {
-  optional int64 long_val = 1;
-}
-
-
-
diff --git a/apex/statsd/tests/libstatspull/src/com/android/internal/os/statsd/libstats/LibStatsPullTests.java b/apex/statsd/tests/libstatspull/src/com/android/internal/os/statsd/libstats/LibStatsPullTests.java
deleted file mode 100644
index 6108a32..0000000
--- a/apex/statsd/tests/libstatspull/src/com/android/internal/os/statsd/libstats/LibStatsPullTests.java
+++ /dev/null
@@ -1,287 +0,0 @@
-/*
- * Copyright (C) 2019 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.internal.os.statsd.libstats;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.app.StatsManager;
-import android.content.Context;
-import android.util.Log;
-import android.util.StatsLog;
-
-import androidx.test.InstrumentationRegistry;
-import androidx.test.filters.MediumTest;
-import androidx.test.runner.AndroidJUnit4;
-
-import com.android.internal.os.StatsdConfigProto.AtomMatcher;
-import com.android.internal.os.StatsdConfigProto.FieldFilter;
-import com.android.internal.os.StatsdConfigProto.GaugeMetric;
-import com.android.internal.os.StatsdConfigProto.PullAtomPackages;
-import com.android.internal.os.StatsdConfigProto.SimpleAtomMatcher;
-import com.android.internal.os.StatsdConfigProto.StatsdConfig;
-import com.android.internal.os.StatsdConfigProto.TimeUnit;
-import com.android.internal.os.statsd.protos.TestAtoms;
-import com.android.os.AtomsProto.Atom;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.util.List;
-
-/**
- * Test puller registration.
- */
-@MediumTest
-@RunWith(AndroidJUnit4.class)
-public class LibStatsPullTests {
-    private static final String LOG_TAG = LibStatsPullTests.class.getSimpleName();
-    private static final int SHORT_SLEEP_MILLIS = 250;
-    private static final int LONG_SLEEP_MILLIS = 1_000;
-    private Context mContext;
-    private static final int PULL_ATOM_TAG = 150030;
-    private static final int APP_BREADCRUMB_LABEL = 3;
-    private static int sPullReturnValue;
-    private static long sConfigId;
-    private static long sPullLatencyMillis;
-    private static long sPullTimeoutMillis;
-    private static long sCoolDownMillis;
-    private static int sAtomsPerPull;
-
-    static {
-        System.loadLibrary("statspull_testhelper");
-    }
-
-    /**
-     * Setup the tests. Initialize shared data.
-     */
-    @Before
-    public void setup() {
-        mContext = InstrumentationRegistry.getTargetContext();
-        assertThat(InstrumentationRegistry.getInstrumentation()).isNotNull();
-        sPullReturnValue = StatsManager.PULL_SUCCESS;
-        sPullLatencyMillis = 0;
-        sPullTimeoutMillis = 10_000L;
-        sCoolDownMillis = 1_000L;
-        sAtomsPerPull = 1;
-    }
-
-    /**
-     * Teardown the tests.
-     */
-    @After
-    public void tearDown() throws Exception {
-        clearStatsPuller(PULL_ATOM_TAG);
-        StatsManager statsManager = (StatsManager) mContext.getSystemService(
-                Context.STATS_MANAGER);
-        statsManager.removeConfig(sConfigId);
-    }
-
-    /**
-     * Tests adding a puller callback and that pulls complete successfully.
-     */
-    @Test
-    public void testPullAtomCallbackRegistration() throws Exception {
-        StatsManager statsManager = (StatsManager) mContext.getSystemService(
-                Context.STATS_MANAGER);
-        // Upload a config that captures that pulled atom.
-        createAndAddConfigToStatsd(statsManager);
-
-        // Add the puller.
-        setStatsPuller(PULL_ATOM_TAG, sPullTimeoutMillis, sCoolDownMillis, sPullReturnValue,
-                sPullLatencyMillis, sAtomsPerPull);
-        Thread.sleep(SHORT_SLEEP_MILLIS);
-        StatsLog.logStart(APP_BREADCRUMB_LABEL);
-        // Let the current bucket finish.
-        Thread.sleep(LONG_SLEEP_MILLIS);
-        List<Atom> data = StatsConfigUtils.getGaugeMetricDataList(statsManager, sConfigId);
-        clearStatsPuller(PULL_ATOM_TAG);
-        assertThat(data.size()).isEqualTo(1);
-        TestAtoms.PullCallbackAtomWrapper atomWrapper = null;
-        try {
-            atomWrapper = TestAtoms.PullCallbackAtomWrapper.parser()
-                    .parseFrom(data.get(0).toByteArray());
-        } catch (Exception e) {
-            Log.e(LOG_TAG, "Failed to parse primitive atoms");
-        }
-        assertThat(atomWrapper).isNotNull();
-        assertThat(atomWrapper.hasPullCallbackAtom()).isTrue();
-        TestAtoms.PullCallbackAtom atom =
-                atomWrapper.getPullCallbackAtom();
-        assertThat(atom.getLongVal()).isEqualTo(1);
-    }
-
-    /**
-     * Tests that a failed pull is skipped.
-     */
-    @Test
-    public void testPullAtomCallbackFailure() throws Exception {
-        StatsManager statsManager = (StatsManager) mContext.getSystemService(
-                Context.STATS_MANAGER);
-        createAndAddConfigToStatsd(statsManager);
-        sPullReturnValue = StatsManager.PULL_SKIP;
-        // Add the puller.
-        setStatsPuller(PULL_ATOM_TAG, sPullTimeoutMillis, sCoolDownMillis, sPullReturnValue,
-                sPullLatencyMillis, sAtomsPerPull);
-        Thread.sleep(SHORT_SLEEP_MILLIS);
-        StatsLog.logStart(APP_BREADCRUMB_LABEL);
-        // Let the current bucket finish.
-        Thread.sleep(LONG_SLEEP_MILLIS);
-        List<Atom> data = StatsConfigUtils.getGaugeMetricDataList(statsManager, sConfigId);
-        clearStatsPuller(PULL_ATOM_TAG);
-        assertThat(data.size()).isEqualTo(0);
-    }
-
-    /**
-     * Tests that a pull that times out is skipped.
-     */
-    @Test
-    public void testPullAtomCallbackTimeout() throws Exception {
-        StatsManager statsManager = (StatsManager) mContext.getSystemService(
-                Context.STATS_MANAGER);
-        createAndAddConfigToStatsd(statsManager);
-        // The puller will sleep for 1.5 sec.
-        sPullLatencyMillis = 1_500;
-        // 1 second timeout
-        sPullTimeoutMillis = 1_000;
-
-        // Add the puller.
-        setStatsPuller(PULL_ATOM_TAG, sPullTimeoutMillis, sCoolDownMillis, sPullReturnValue,
-                sPullLatencyMillis, sAtomsPerPull);
-        Thread.sleep(SHORT_SLEEP_MILLIS);
-        StatsLog.logStart(APP_BREADCRUMB_LABEL);
-        // Let the current bucket finish and the pull timeout.
-        Thread.sleep(sPullLatencyMillis * 2);
-        List<Atom> data = StatsConfigUtils.getGaugeMetricDataList(statsManager, sConfigId);
-        clearStatsPuller(PULL_ATOM_TAG);
-        assertThat(data.size()).isEqualTo(0);
-    }
-
-    /**
-     * Tests that 2 pulls in quick succession use the cache instead of pulling again.
-     */
-    @Test
-    public void testPullAtomCallbackCache() throws Exception {
-        StatsManager statsManager = (StatsManager) mContext.getSystemService(
-                Context.STATS_MANAGER);
-        createAndAddConfigToStatsd(statsManager);
-
-        // Set the cooldown to 10 seconds
-        sCoolDownMillis = 10_000L;
-        // Add the puller.
-        setStatsPuller(PULL_ATOM_TAG, sPullTimeoutMillis, sCoolDownMillis, sPullReturnValue,
-                sPullLatencyMillis, sAtomsPerPull);
-
-        Thread.sleep(SHORT_SLEEP_MILLIS);
-        StatsLog.logStart(APP_BREADCRUMB_LABEL);
-        // Pull from cache.
-        StatsLog.logStart(APP_BREADCRUMB_LABEL);
-        Thread.sleep(LONG_SLEEP_MILLIS);
-        List<Atom> data = StatsConfigUtils.getGaugeMetricDataList(statsManager, sConfigId);
-        clearStatsPuller(PULL_ATOM_TAG);
-        assertThat(data.size()).isEqualTo(2);
-        for (int i = 0; i < data.size(); i++) {
-            TestAtoms.PullCallbackAtomWrapper atomWrapper = null;
-            try {
-                atomWrapper = TestAtoms.PullCallbackAtomWrapper.parser()
-                        .parseFrom(data.get(i).toByteArray());
-            } catch (Exception e) {
-                Log.e(LOG_TAG, "Failed to parse primitive atoms");
-            }
-            assertThat(atomWrapper).isNotNull();
-            assertThat(atomWrapper.hasPullCallbackAtom()).isTrue();
-            TestAtoms.PullCallbackAtom atom =
-                    atomWrapper.getPullCallbackAtom();
-            assertThat(atom.getLongVal()).isEqualTo(1);
-        }
-    }
-
-    /**
-     * Tests that a pull that returns 1000 stats events works properly.
-     */
-    @Test
-    public void testPullAtomCallbackStress() throws Exception {
-        StatsManager statsManager = (StatsManager) mContext.getSystemService(
-                Context.STATS_MANAGER);
-        // Upload a config that captures that pulled atom.
-        createAndAddConfigToStatsd(statsManager);
-        sAtomsPerPull = 1000;
-        // Add the puller.
-        setStatsPuller(PULL_ATOM_TAG, sPullTimeoutMillis, sCoolDownMillis, sPullReturnValue,
-                sPullLatencyMillis, sAtomsPerPull);
-
-        Thread.sleep(SHORT_SLEEP_MILLIS);
-        StatsLog.logStart(APP_BREADCRUMB_LABEL);
-        // Let the current bucket finish.
-        Thread.sleep(LONG_SLEEP_MILLIS);
-        List<Atom> data = StatsConfigUtils.getGaugeMetricDataList(statsManager, sConfigId);
-        clearStatsPuller(PULL_ATOM_TAG);
-        assertThat(data.size()).isEqualTo(sAtomsPerPull);
-
-        for (int i = 0; i < data.size(); i++) {
-            TestAtoms.PullCallbackAtomWrapper atomWrapper = null;
-            try {
-                atomWrapper = TestAtoms.PullCallbackAtomWrapper.parser()
-                        .parseFrom(data.get(i).toByteArray());
-            } catch (Exception e) {
-                Log.e(LOG_TAG, "Failed to parse primitive atoms");
-            }
-            assertThat(atomWrapper).isNotNull();
-            assertThat(atomWrapper.hasPullCallbackAtom()).isTrue();
-            TestAtoms.PullCallbackAtom atom =
-                    atomWrapper.getPullCallbackAtom();
-            assertThat(atom.getLongVal()).isEqualTo(1);
-        }
-    }
-
-    private void createAndAddConfigToStatsd(StatsManager statsManager) throws Exception {
-        sConfigId = System.currentTimeMillis();
-        long triggerMatcherId = sConfigId + 10;
-        long pullerMatcherId = sConfigId + 11;
-        long metricId = sConfigId + 100;
-        StatsdConfig config = StatsConfigUtils.getSimpleTestConfig(sConfigId)
-                .addAtomMatcher(
-                        StatsConfigUtils.getAppBreadcrumbMatcher(triggerMatcherId,
-                                APP_BREADCRUMB_LABEL))
-                .addAtomMatcher(AtomMatcher.newBuilder()
-                        .setId(pullerMatcherId)
-                        .setSimpleAtomMatcher(SimpleAtomMatcher.newBuilder()
-                                .setAtomId(PULL_ATOM_TAG))
-                )
-                .addGaugeMetric(GaugeMetric.newBuilder()
-                        .setId(metricId)
-                        .setWhat(pullerMatcherId)
-                        .setTriggerEvent(triggerMatcherId)
-                        .setGaugeFieldsFilter(FieldFilter.newBuilder().setIncludeAll(true))
-                        .setBucket(TimeUnit.CTS)
-                        .setSamplingType(GaugeMetric.SamplingType.FIRST_N_SAMPLES)
-                        .setMaxNumGaugeAtomsPerBucket(1000)
-                )
-                .addPullAtomPackages(PullAtomPackages.newBuilder()
-                        .setAtomId(PULL_ATOM_TAG)
-                        .addPackages(LibStatsPullTests.class.getPackage().getName()))
-                .build();
-        statsManager.addConfig(sConfigId, config.toByteArray());
-        assertThat(StatsConfigUtils.verifyValidConfigExists(statsManager, sConfigId)).isTrue();
-    }
-
-    private native void setStatsPuller(int atomTag, long timeoutMillis, long coolDownMillis,
-            int pullReturnVal, long latencyMillis, int atomPerPull);
-
-    private native void clearStatsPuller(int atomTag);
-}
-
diff --git a/apex/statsd/tests/libstatspull/src/com/android/internal/os/statsd/libstats/StatsConfigUtils.java b/apex/statsd/tests/libstatspull/src/com/android/internal/os/statsd/libstats/StatsConfigUtils.java
deleted file mode 100644
index b5afb94..0000000
--- a/apex/statsd/tests/libstatspull/src/com/android/internal/os/statsd/libstats/StatsConfigUtils.java
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Copyright (C) 2019 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.internal.os.statsd.libstats;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.app.StatsManager;
-import android.util.Log;
-
-import com.android.internal.os.StatsdConfigProto.AtomMatcher;
-import com.android.internal.os.StatsdConfigProto.FieldValueMatcher;
-import com.android.internal.os.StatsdConfigProto.SimpleAtomMatcher;
-import com.android.internal.os.StatsdConfigProto.StatsdConfig;
-import com.android.os.AtomsProto.AppBreadcrumbReported;
-import com.android.os.AtomsProto.Atom;
-import com.android.os.StatsLog.ConfigMetricsReport;
-import com.android.os.StatsLog.ConfigMetricsReportList;
-import com.android.os.StatsLog.GaugeBucketInfo;
-import com.android.os.StatsLog.GaugeMetricData;
-import com.android.os.StatsLog.StatsLogReport;
-import com.android.os.StatsLog.StatsdStatsReport;
-import com.android.os.StatsLog.StatsdStatsReport.ConfigStats;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Util class for constructing statsd configs.
- */
-public class StatsConfigUtils {
-    public static final String TAG = "statsd.StatsConfigUtils";
-    public static final int SHORT_WAIT = 2_000; // 2 seconds.
-
-    /**
-     * @return An empty StatsdConfig in serialized proto format.
-     */
-    public static StatsdConfig.Builder getSimpleTestConfig(long configId) {
-        return StatsdConfig.newBuilder().setId(configId)
-                .addAllowedLogSource(StatsConfigUtils.class.getPackage().getName());
-    }
-
-
-    public static boolean verifyValidConfigExists(StatsManager statsManager, long configId) {
-        StatsdStatsReport report = null;
-        try {
-            report = StatsdStatsReport.parser().parseFrom(statsManager.getStatsMetadata());
-        } catch (Exception e) {
-            Log.e(TAG, "getMetadata failed", e);
-        }
-        assertThat(report).isNotNull();
-        boolean foundConfig = false;
-        for (ConfigStats configStats : report.getConfigStatsList()) {
-            if (configStats.getId() == configId && configStats.getIsValid()
-                    && configStats.getDeletionTimeSec() == 0) {
-                foundConfig = true;
-            }
-        }
-        return foundConfig;
-    }
-
-    public static AtomMatcher getAppBreadcrumbMatcher(long id, int label) {
-        return AtomMatcher.newBuilder()
-                .setId(id)
-                .setSimpleAtomMatcher(
-                        SimpleAtomMatcher.newBuilder()
-                                .setAtomId(Atom.APP_BREADCRUMB_REPORTED_FIELD_NUMBER)
-                                .addFieldValueMatcher(FieldValueMatcher.newBuilder()
-                                        .setField(AppBreadcrumbReported.LABEL_FIELD_NUMBER)
-                                        .setEqInt(label)
-                                )
-                )
-                .build();
-    }
-
-    public static ConfigMetricsReport getConfigMetricsReport(StatsManager statsManager,
-            long configId) {
-        ConfigMetricsReportList reportList = null;
-        try {
-            reportList = ConfigMetricsReportList.parser()
-                    .parseFrom(statsManager.getReports(configId));
-        } catch (Exception e) {
-            Log.e(TAG, "getData failed", e);
-        }
-        assertThat(reportList).isNotNull();
-        assertThat(reportList.getReportsCount()).isEqualTo(1);
-        ConfigMetricsReport report = reportList.getReports(0);
-        assertThat(report.getDumpReportReason())
-                .isEqualTo(ConfigMetricsReport.DumpReportReason.GET_DATA_CALLED);
-        return report;
-
-    }
-    public static List<Atom> getGaugeMetricDataList(ConfigMetricsReport report) {
-        List<Atom> data = new ArrayList<>();
-        for (StatsLogReport metric : report.getMetricsList()) {
-            for (GaugeMetricData gaugeMetricData : metric.getGaugeMetrics().getDataList()) {
-                for (GaugeBucketInfo bucketInfo : gaugeMetricData.getBucketInfoList()) {
-                    for (Atom atom : bucketInfo.getAtomList()) {
-                        data.add(atom);
-                    }
-                }
-            }
-        }
-        return data;
-    }
-
-    public static List<Atom> getGaugeMetricDataList(StatsManager statsManager, long configId) {
-        ConfigMetricsReport report = getConfigMetricsReport(statsManager, configId);
-        return getGaugeMetricDataList(report);
-    }
-}
-
diff --git a/api/OWNERS b/api/OWNERS
new file mode 100644
index 0000000..88d0b61
--- /dev/null
+++ b/api/OWNERS
@@ -0,0 +1 @@
+per-file Android.bp = file:platform/build/soong:/OWNERS
diff --git a/cmds/am/OWNERS b/cmds/am/OWNERS
new file mode 100644
index 0000000..72c0a9e
--- /dev/null
+++ b/cmds/am/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/am/OWNERS
diff --git a/cmds/appops/OWNERS b/cmds/appops/OWNERS
new file mode 100644
index 0000000..999ea0e
--- /dev/null
+++ b/cmds/appops/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/permission/OWNERS
diff --git a/cmds/backup/OWNERS b/cmds/backup/OWNERS
new file mode 100644
index 0000000..d99779e
--- /dev/null
+++ b/cmds/backup/OWNERS
@@ -0,0 +1 @@
+include /services/backup/OWNERS
diff --git a/cmds/bmgr/OWNERS b/cmds/bmgr/OWNERS
new file mode 100644
index 0000000..d99779e
--- /dev/null
+++ b/cmds/bmgr/OWNERS
@@ -0,0 +1 @@
+include /services/backup/OWNERS
diff --git a/cmds/bu/OWNERS b/cmds/bu/OWNERS
new file mode 100644
index 0000000..d99779e
--- /dev/null
+++ b/cmds/bu/OWNERS
@@ -0,0 +1 @@
+include /services/backup/OWNERS
diff --git a/cmds/dpm/OWNERS b/cmds/dpm/OWNERS
new file mode 100644
index 0000000..e95633a
--- /dev/null
+++ b/cmds/dpm/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/app/admin/OWNERS
diff --git a/cmds/ime/OWNERS b/cmds/ime/OWNERS
new file mode 100644
index 0000000..5deb2ce
--- /dev/null
+++ b/cmds/ime/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/view/inputmethod/OWNERS
diff --git a/cmds/incident/OWNERS b/cmds/incident/OWNERS
new file mode 100644
index 0000000..f766115
--- /dev/null
+++ b/cmds/incident/OWNERS
@@ -0,0 +1 @@
+include /cmds/incidentd/OWNERS
diff --git a/cmds/input/OWNERS b/cmds/input/OWNERS
new file mode 100644
index 0000000..d701f23
--- /dev/null
+++ b/cmds/input/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/hardware/input/OWNERS
diff --git a/cmds/locksettings/OWNERS b/cmds/locksettings/OWNERS
new file mode 100644
index 0000000..0a8dc8c
--- /dev/null
+++ b/cmds/locksettings/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/locksettings/OWNERS
diff --git a/cmds/pm/OWNERS b/cmds/pm/OWNERS
new file mode 100644
index 0000000..d825dfd
--- /dev/null
+++ b/cmds/pm/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/pm/OWNERS
diff --git a/cmds/sm/OWNERS b/cmds/sm/OWNERS
new file mode 100644
index 0000000..6f9dbea
--- /dev/null
+++ b/cmds/sm/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/os/storage/OWNERS
diff --git a/cmds/telecom/OWNERS b/cmds/telecom/OWNERS
new file mode 100644
index 0000000..2f813e6
--- /dev/null
+++ b/cmds/telecom/OWNERS
@@ -0,0 +1 @@
+include /telecomm/OWNERS
diff --git a/cmds/uinput/OWNERS b/cmds/uinput/OWNERS
new file mode 100644
index 0000000..d701f23
--- /dev/null
+++ b/cmds/uinput/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/hardware/input/OWNERS
diff --git a/cmds/wm/OWNERS b/cmds/wm/OWNERS
new file mode 100644
index 0000000..0862c05
--- /dev/null
+++ b/cmds/wm/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/wm/OWNERS
diff --git a/config/OWNERS b/config/OWNERS
index 3d4924d..d59c6f2 100644
--- a/config/OWNERS
+++ b/config/OWNERS
@@ -1,4 +1,7 @@
+include /ZYGOTE_OWNERS
+
 # compat-team@ for changes to hiddenapi files
+
 per-file hiddenapi-* = [email protected], [email protected], [email protected]
 
 # Escalations:
diff --git a/core/api/OWNERS b/core/api/OWNERS
new file mode 100644
index 0000000..0b95c51
--- /dev/null
+++ b/core/api/OWNERS
@@ -0,0 +1,2 @@
+# API changes are managed via Prolog rules, not OWNERS
+*
diff --git a/core/api/current.txt b/core/api/current.txt
index 49d1e75..cf73689 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -165,6 +165,7 @@
     field public static final String USE_BIOMETRIC = "android.permission.USE_BIOMETRIC";
     field @Deprecated public static final String USE_FINGERPRINT = "android.permission.USE_FINGERPRINT";
     field public static final String USE_FULL_SCREEN_INTENT = "android.permission.USE_FULL_SCREEN_INTENT";
+    field public static final String USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER = "android.permission.USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER";
     field public static final String USE_SIP = "android.permission.USE_SIP";
     field public static final String VIBRATE = "android.permission.VIBRATE";
     field public static final String WAKE_LOCK = "android.permission.WAKE_LOCK";
@@ -6920,6 +6921,7 @@
     method public int getGlobalPrivateDnsMode(@NonNull android.content.ComponentName);
     method @NonNull public java.util.List<byte[]> getInstalledCaCerts(@Nullable android.content.ComponentName);
     method @Nullable public java.util.List<java.lang.String> getKeepUninstalledPackages(@Nullable android.content.ComponentName);
+    method @NonNull public java.util.Set<java.util.Set<java.lang.String>> getKeyPairGrants(@NonNull String);
     method public int getKeyguardDisabledFeatures(@Nullable android.content.ComponentName);
     method public int getLockTaskFeatures(@NonNull android.content.ComponentName);
     method @NonNull public String[] getLockTaskPackages(@NonNull android.content.ComponentName);
@@ -34862,6 +34864,27 @@
     method public void onCancel();
   }
 
+  public abstract class CombinedVibrationEffect implements android.os.Parcelable {
+    method @NonNull public static android.os.CombinedVibrationEffect createSynced(@NonNull android.os.VibrationEffect);
+    method public int describeContents();
+    method @NonNull public static android.os.CombinedVibrationEffect.SequentialCombination startSequential();
+    method @NonNull public static android.os.CombinedVibrationEffect.SyncedCombination startSynced();
+    field @NonNull public static final android.os.Parcelable.Creator<android.os.CombinedVibrationEffect> CREATOR;
+  }
+
+  public static final class CombinedVibrationEffect.SequentialCombination {
+    method @NonNull public android.os.CombinedVibrationEffect.SequentialCombination addNext(int, @NonNull android.os.VibrationEffect);
+    method @NonNull public android.os.CombinedVibrationEffect.SequentialCombination addNext(int, @NonNull android.os.VibrationEffect, int);
+    method @NonNull public android.os.CombinedVibrationEffect.SequentialCombination addNext(@NonNull android.os.CombinedVibrationEffect);
+    method @NonNull public android.os.CombinedVibrationEffect.SequentialCombination addNext(@NonNull android.os.CombinedVibrationEffect, int);
+    method @NonNull public android.os.CombinedVibrationEffect combine();
+  }
+
+  public static final class CombinedVibrationEffect.SyncedCombination {
+    method @NonNull public android.os.CombinedVibrationEffect.SyncedCombination addVibrator(int, @NonNull android.os.VibrationEffect);
+    method @NonNull public android.os.CombinedVibrationEffect combine();
+  }
+
   public class ConditionVariable {
     ctor public ConditionVariable();
     ctor public ConditionVariable(boolean);
@@ -36088,6 +36111,13 @@
     field public static final int VIBRATION_EFFECT_SUPPORT_YES = 1; // 0x1
   }
 
+  public abstract class VibratorManager {
+    method @NonNull public abstract android.os.Vibrator getDefaultVibrator();
+    method @NonNull public abstract android.os.Vibrator getVibrator(int);
+    method @NonNull public abstract int[] getVibratorIds();
+    method public abstract void vibrate(@NonNull android.os.CombinedVibrationEffect);
+  }
+
   public class WorkSource implements android.os.Parcelable {
     ctor public WorkSource();
     ctor public WorkSource(android.os.WorkSource);
@@ -47014,7 +47044,6 @@
     method public boolean isVoicemailVibrationEnabled(android.telecom.PhoneAccountHandle);
     method public boolean isWorldPhone();
     method @Deprecated public void listen(android.telephony.PhoneStateListener, int);
-    method @Deprecated public void listen(long, @NonNull android.telephony.PhoneStateListener);
     method public void registerPhoneStateListener(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.PhoneStateListener);
     method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public void requestCellInfoUpdate(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyManager.CellInfoCallback);
     method @RequiresPermission(allOf={android.Manifest.permission.MODIFY_PHONE_STATE, android.Manifest.permission.ACCESS_FINE_LOCATION}) public android.telephony.NetworkScan requestNetworkScan(android.telephony.NetworkScanRequest, java.util.concurrent.Executor, android.telephony.TelephonyScanManager.NetworkScanCallback);
@@ -47785,6 +47814,7 @@
     field public static final int CODE_WIFI_LOST = 1407; // 0x57f
     field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.ImsReasonInfo> CREATOR;
     field public static final int EXTRA_CODE_CALL_RETRY_BY_SETTINGS = 3; // 0x3
+    field public static final int EXTRA_CODE_CALL_RETRY_EMERGENCY = 4; // 0x4
     field public static final int EXTRA_CODE_CALL_RETRY_NORMAL = 1; // 0x1
     field public static final int EXTRA_CODE_CALL_RETRY_SILENT_REDIAL = 2; // 0x2
   }
@@ -51337,6 +51367,7 @@
     method public int getSources();
     method public int getVendorId();
     method public android.os.Vibrator getVibrator();
+    method @NonNull public android.os.VibratorManager getVibratorManager();
     method public boolean[] hasKeys(int...);
     method public boolean hasMicrophone();
     method public boolean isEnabled();
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index a1d3594..8e440fb1 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -211,6 +211,7 @@
     field public static final String RETRIEVE_WINDOW_CONTENT = "android.permission.RETRIEVE_WINDOW_CONTENT";
     field public static final String REVIEW_ACCESSIBILITY_SERVICES = "android.permission.REVIEW_ACCESSIBILITY_SERVICES";
     field public static final String REVOKE_RUNTIME_PERMISSIONS = "android.permission.REVOKE_RUNTIME_PERMISSIONS";
+    field public static final String ROTATE_SURFACE_FLINGER = "android.permission.ROTATE_SURFACE_FLINGER";
     field public static final String SCORE_NETWORKS = "android.permission.SCORE_NETWORKS";
     field public static final String SECURE_ELEMENT_PRIVILEGED_OPERATION = "android.permission.SECURE_ELEMENT_PRIVILEGED_OPERATION";
     field public static final String SEND_CATEGORY_CAR_NOTIFICATIONS = "android.permission.SEND_CATEGORY_CAR_NOTIFICATIONS";
@@ -608,7 +609,10 @@
     method @RequiresPermission(android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND) public void setBackgroundActivityStartsAllowed(boolean);
     method public void setDontSendToRestrictedApps(boolean);
     method @RequiresPermission(anyOf={android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST, android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND, android.Manifest.permission.START_FOREGROUND_SERVICES_FROM_BACKGROUND}) public void setTemporaryAppWhitelistDuration(long);
+    method @RequiresPermission(anyOf={android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST, android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND, android.Manifest.permission.START_FOREGROUND_SERVICES_FROM_BACKGROUND}) public void setTemporaryAppWhitelistDuration(int, long);
     method public android.os.Bundle toBundle();
+    field public static final int TEMPORARY_WHITELIST_TYPE_FOREGROUND_SERVICE_ALLOWED = 0; // 0x0
+    field public static final int TEMPORARY_WHITELIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED = 1; // 0x1
   }
 
   public class DownloadManager {
@@ -4117,6 +4121,22 @@
     method @Deprecated public void onStatusChanged(int);
   }
 
+  public final class LastLocationRequest implements android.os.Parcelable {
+    method public int describeContents();
+    method public boolean isHiddenFromAppOps();
+    method public boolean isLocationSettingsIgnored();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.location.LastLocationRequest> CREATOR;
+  }
+
+  public static final class LastLocationRequest.Builder {
+    ctor public LastLocationRequest.Builder();
+    ctor public LastLocationRequest.Builder(@NonNull android.location.LastLocationRequest);
+    method @NonNull public android.location.LastLocationRequest build();
+    method @NonNull @RequiresPermission(android.Manifest.permission.UPDATE_APP_OPS_STATS) public android.location.LastLocationRequest.Builder setHiddenFromAppOps(boolean);
+    method @NonNull @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public android.location.LastLocationRequest.Builder setLocationSettingsIgnored(boolean);
+  }
+
   public class Location implements android.os.Parcelable {
     method public boolean isComplete();
     method public void makeComplete();
@@ -4129,6 +4149,7 @@
     method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void getCurrentLocation(@NonNull android.location.LocationRequest, @Nullable android.os.CancellationSignal, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.location.Location>);
     method @Nullable public String getExtraLocationControllerPackage();
     method @Deprecated public int getGnssBatchSize();
+    method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public android.location.Location getLastKnownLocation(@NonNull String, @NonNull android.location.LastLocationRequest);
     method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public void injectGnssMeasurementCorrections(@NonNull android.location.GnssMeasurementCorrections);
     method public boolean isExtraLocationControllerPackageEnabled();
     method public boolean isLocationEnabledForUser(@NonNull android.os.UserHandle);
@@ -4351,6 +4372,7 @@
     field public static final int PLAYER_STATE_STARTED = 2; // 0x2
     field public static final int PLAYER_STATE_STOPPED = 4; // 0x4
     field public static final int PLAYER_STATE_UNKNOWN = -1; // 0xffffffff
+    field public static final int PLAYER_TYPE_AAUDIO = 13; // 0xd
     field public static final int PLAYER_TYPE_JAM_AUDIOTRACK = 1; // 0x1
     field public static final int PLAYER_TYPE_JAM_MEDIAPLAYER = 2; // 0x2
     field public static final int PLAYER_TYPE_JAM_SOUNDPOOL = 3; // 0x3
@@ -4997,6 +5019,7 @@
   public class Descrambler implements java.lang.AutoCloseable {
     method public int addPid(int, int, @Nullable android.media.tv.tuner.filter.Filter);
     method public void close();
+    method public static boolean isValidKeyToken(@NonNull byte[]);
     method public int removePid(int, int, @Nullable android.media.tv.tuner.filter.Filter);
     method public int setKeyToken(@NonNull byte[]);
     field public static final int PID_TYPE_MMTP = 2; // 0x2
@@ -5071,7 +5094,6 @@
     field public static final int INVALID_FIRST_MACROBLOCK_IN_SLICE = -1; // 0xffffffff
     field public static final int INVALID_FRONTEND_ID = -1; // 0xffffffff
     field public static final int INVALID_FRONTEND_SETTING_FREQUENCY = -1; // 0xffffffff
-    field @NonNull public static final byte[] INVALID_KEYTOKEN;
     field public static final int INVALID_LTS_ID = -1; // 0xffffffff
     field public static final int INVALID_MMTP_RECORD_EVENT_MPT_SEQUENCE_NUM = -1; // 0xffffffff
     field public static final int INVALID_STREAM_ID = 65535; // 0xffff
@@ -5087,6 +5109,7 @@
     field public static final int SCAN_TYPE_AUTO = 1; // 0x1
     field public static final int SCAN_TYPE_BLIND = 2; // 0x2
     field public static final int SCAN_TYPE_UNDEFINED = 0; // 0x0
+    field @NonNull public static final byte[] VOID_KEYTOKEN;
   }
 
   public static interface Tuner.OnResourceLostListener {
@@ -5891,8 +5914,8 @@
 
   public class DvbsFrontendSettings extends android.media.tv.tuner.frontend.FrontendSettings {
     method @NonNull public static android.media.tv.tuner.frontend.DvbsFrontendSettings.Builder builder();
+    method public boolean canHandleDiseqcRxMessage();
     method @Nullable public android.media.tv.tuner.frontend.DvbsCodeRate getCodeRate();
-    method public boolean getCouldHandleDiseqcRxMessage();
     method public int getInputStreamId();
     method public int getModulation();
     method public int getPilot();
@@ -5944,8 +5967,8 @@
 
   public static class DvbsFrontendSettings.Builder {
     method @NonNull public android.media.tv.tuner.frontend.DvbsFrontendSettings build();
+    method @NonNull public android.media.tv.tuner.frontend.DvbsFrontendSettings.Builder setCanHandleDiseqcRxMessage(boolean);
     method @NonNull public android.media.tv.tuner.frontend.DvbsFrontendSettings.Builder setCodeRate(@Nullable android.media.tv.tuner.frontend.DvbsCodeRate);
-    method @NonNull public android.media.tv.tuner.frontend.DvbsFrontendSettings.Builder setCouldHandleDiseqcRxMessage(boolean);
     method @IntRange(from=1) @NonNull public android.media.tv.tuner.frontend.DvbsFrontendSettings.Builder setFrequency(int);
     method @NonNull public android.media.tv.tuner.frontend.DvbsFrontendSettings.Builder setInputStreamId(int);
     method @NonNull public android.media.tv.tuner.frontend.DvbsFrontendSettings.Builder setModulation(int);
@@ -7819,7 +7842,7 @@
     method @Nullable public <T extends android.os.Parcelable> T getParcelable(@NonNull Class<T>);
     method public int getStability();
     method public void readFromParcel(@NonNull android.os.Parcel);
-    method public boolean setParcelable(@Nullable android.os.Parcelable);
+    method public void setParcelable(@Nullable android.os.Parcelable);
     method public void writeToParcel(@NonNull android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.os.ParcelableHolder> CREATOR;
   }
@@ -10991,8 +11014,10 @@
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setRadio(boolean);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setRadioEnabled(boolean);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setRadioPower(boolean);
-    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setSimPowerState(int);
-    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setSimPowerStateForSlot(int, int);
+    method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setSimPowerState(int);
+    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setSimPowerState(int, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
+    method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setSimPowerStateForSlot(int, int);
+    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setSimPowerStateForSlot(int, int, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setSystemSelectionChannels(@NonNull java.util.List<android.telephony.RadioAccessSpecifier>, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setSystemSelectionChannels(@NonNull java.util.List<android.telephony.RadioAccessSpecifier>);
     method @Deprecated public void setVisualVoicemailEnabled(android.telecom.PhoneAccountHandle, boolean);
@@ -11082,6 +11107,11 @@
     field public static final int SET_CARRIER_RESTRICTION_ERROR = 2; // 0x2
     field public static final int SET_CARRIER_RESTRICTION_NOT_SUPPORTED = 1; // 0x1
     field public static final int SET_CARRIER_RESTRICTION_SUCCESS = 0; // 0x0
+    field public static final int SET_SIM_POWER_STATE_ALREADY_IN_STATE = 1; // 0x1
+    field public static final int SET_SIM_POWER_STATE_MODEM_ERROR = 2; // 0x2
+    field public static final int SET_SIM_POWER_STATE_NOT_SUPPORTED = 4; // 0x4
+    field public static final int SET_SIM_POWER_STATE_SIM_ERROR = 3; // 0x3
+    field public static final int SET_SIM_POWER_STATE_SUCCESS = 0; // 0x0
     field public static final int SIM_ACTIVATION_STATE_ACTIVATED = 2; // 0x2
     field public static final int SIM_ACTIVATION_STATE_ACTIVATING = 1; // 0x1
     field public static final int SIM_ACTIVATION_STATE_DEACTIVATED = 3; // 0x3
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 80a160a..1253197 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -216,6 +216,7 @@
     field public static final String KEY_FG_SERVICE_STATE_SETTLE_TIME = "fg_service_state_settle_time";
     field public static final String KEY_TOP_STATE_SETTLE_TIME = "top_state_settle_time";
     field public static final String OPSTR_MANAGE_ONGOING_CALLS = "android:manage_ongoing_calls";
+    field public static final String OPSTR_USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER = "android:use_icc_auth_with_device_identifier";
     field public static final int OP_COARSE_LOCATION = 0; // 0x0
     field public static final int OP_RECORD_AUDIO = 27; // 0x1b
     field public static final int OP_START_FOREGROUND = 76; // 0x4c
@@ -272,6 +273,7 @@
     method public void allowAssistantAdjustment(String);
     method public void disallowAssistantAdjustment(String);
     method public android.content.ComponentName getEffectsSuppressor();
+    method public boolean isNotificationPolicyAccessGrantedForPackage(@NonNull String);
     method public boolean matchesCallFilter(android.os.Bundle);
     method @RequiresPermission(android.Manifest.permission.MANAGE_NOTIFICATION_LISTENERS) public void setNotificationListenerAccessGranted(@NonNull android.content.ComponentName, boolean, boolean);
     method public void updateNotificationChannel(@NonNull String, int, @NonNull android.app.NotificationChannel);
@@ -372,8 +374,15 @@
     method public java.util.List<java.lang.String> getOwnerInstalledCaCerts(@NonNull android.os.UserHandle);
     method public boolean isCurrentInputMethodSetByOwner();
     method public boolean isFactoryResetProtectionPolicySupported();
+    method @NonNull public static String operationToString(int);
+    method @RequiresPermission("android.permission.MANAGE_DEVICE_ADMINS") public void setNextOperationSafety(int, boolean);
     field public static final String ACTION_DATA_SHARING_RESTRICTION_APPLIED = "android.app.action.DATA_SHARING_RESTRICTION_APPLIED";
+    field public static final int OPERATION_CREATE_AND_MANAGE_USER = 5; // 0x5
     field public static final int OPERATION_LOCK_NOW = 1; // 0x1
+    field public static final int OPERATION_REMOVE_USER = 6; // 0x6
+    field public static final int OPERATION_START_USER_IN_BACKGROUND = 3; // 0x3
+    field public static final int OPERATION_STOP_USER = 4; // 0x4
+    field public static final int OPERATION_SWITCH_USER = 2; // 0x2
   }
 
   public static final class SecurityLog.SecurityEvent implements android.os.Parcelable {
diff --git a/core/java/android/animation/OWNERS b/core/java/android/animation/OWNERS
new file mode 100644
index 0000000..822a35c
--- /dev/null
+++ b/core/java/android/animation/OWNERS
@@ -0,0 +1,6 @@
+# Bug component: 47085
+
[email protected]
[email protected]
[email protected]
[email protected]
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 4dd6a7e..f60f569 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -1166,8 +1166,12 @@
     public static final int OP_MANAGE_CREDENTIALS = AppProtoEnums.APP_OP_MANAGE_CREDENTIALS;
 
     /** @hide */
+    public static final int OP_USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER =
+            AppProtoEnums.APP_OP_USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER;
+
+    /** @hide */
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    public static final int _NUM_OP = 105;
+    public static final int _NUM_OP = 106;
 
     /** Access to coarse location information. */
     public static final String OPSTR_COARSE_LOCATION = "android:coarse_location";
@@ -1525,6 +1529,15 @@
      */
     public static final String OPSTR_MANAGE_CREDENTIALS = "android:manage_credentials";
 
+    /**
+     * Allows to read device identifiers and use ICC based authentication like EAP-AKA.
+     *
+     * @hide
+     */
+    @TestApi
+    public static final String OPSTR_USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER =
+            "android:use_icc_auth_with_device_identifier";
+
     /** {@link #sAppOpsToNote} not initialized yet for this op */
     private static final byte SHOULD_COLLECT_NOTE_OP_NOT_INITIALIZED = 0;
     /** Should not collect noting of this app-op in {@link #sAppOpsToNote} */
@@ -1604,6 +1617,7 @@
             OP_INTERACT_ACROSS_PROFILES,
             OP_LOADER_USAGE_STATS,
             OP_MANAGE_ONGOING_CALLS,
+            OP_USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER,
     };
 
     /**
@@ -1720,6 +1734,7 @@
             OP_RECORD_AUDIO_HOTWORD,            // RECORD_AUDIO_HOTWORD
             OP_MANAGE_ONGOING_CALLS,            // MANAGE_ONGOING_CALLS
             OP_MANAGE_CREDENTIALS,              // MANAGE_CREDENTIALS
+            OP_USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER, // USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER
     };
 
     /**
@@ -1831,6 +1846,7 @@
             OPSTR_RECORD_AUDIO_HOTWORD,
             OPSTR_MANAGE_ONGOING_CALLS,
             OPSTR_MANAGE_CREDENTIALS,
+            OPSTR_USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER,
     };
 
     /**
@@ -1943,6 +1959,7 @@
             "RECORD_AUDIO_HOTWORD",
             "MANAGE_ONGOING_CALLS",
             "MANAGE_CREDENTIALS",
+            "USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER",
     };
 
     /**
@@ -2056,6 +2073,7 @@
             null, // no permission for OP_RECORD_AUDIO_HOTWORD
             Manifest.permission.MANAGE_ONGOING_CALLS,
             null, // no permission for OP_MANAGE_CREDENTIALS
+            Manifest.permission.USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER,
     };
 
     /**
@@ -2169,6 +2187,7 @@
             null, // RECORD_AUDIO_HOTWORD
             null, // MANAGE_ONGOING_CALLS
             null, // MANAGE_CREDENTIALS
+            null, // USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER
     };
 
     /**
@@ -2281,6 +2300,7 @@
             null, // RECORD_AUDIO_HOTWORD
             null, // MANAGE_ONGOING_CALLS
             null, // MANAGE_CREDENTIALS
+            null, // USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER
     };
 
     /**
@@ -2392,6 +2412,7 @@
             AppOpsManager.MODE_ALLOWED, // OP_RECORD_AUDIO_HOTWORD
             AppOpsManager.MODE_DEFAULT, // MANAGE_ONGOING_CALLS
             AppOpsManager.MODE_DEFAULT, // MANAGE_CREDENTIALS
+            AppOpsManager.MODE_DEFAULT, // USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER
     };
 
     /**
@@ -2507,6 +2528,7 @@
             false, // RECORD_AUDIO_HOTWORD
             true, // MANAGE_ONGOING_CALLS
             false, // MANAGE_CREDENTIALS
+            true, // USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER
     };
 
     /**
diff --git a/core/java/android/app/BroadcastOptions.java b/core/java/android/app/BroadcastOptions.java
index 298c455..a16f6a8 100644
--- a/core/java/android/app/BroadcastOptions.java
+++ b/core/java/android/app/BroadcastOptions.java
@@ -16,11 +16,15 @@
 
 package android.app;
 
+import android.annotation.IntDef;
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
 import android.os.Build;
 import android.os.Bundle;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
 /**
  * Helper class for building an options Bundle that can be used with
  * {@link android.content.Context#sendBroadcast(android.content.Intent)
@@ -30,6 +34,7 @@
 @SystemApi
 public class BroadcastOptions {
     private long mTemporaryAppWhitelistDuration;
+    private @TempAllowListType int mTemporaryAppWhitelistType;
     private int mMinManifestReceiverApiLevel = 0;
     private int mMaxManifestReceiverApiLevel = Build.VERSION_CODES.CUR_DEVELOPMENT;
     private boolean mDontSendToRestrictedApps = false;
@@ -42,6 +47,9 @@
     static final String KEY_TEMPORARY_APP_WHITELIST_DURATION
             = "android:broadcast.temporaryAppWhitelistDuration";
 
+    static final String KEY_TEMPORARY_APP_WHITELIST_TYPE
+            = "android:broadcast.temporaryAppWhitelistType";
+
     /**
      * Corresponds to {@link #setMinManifestReceiverApiLevel}.
      */
@@ -66,6 +74,27 @@
     static final String KEY_ALLOW_BACKGROUND_ACTIVITY_STARTS =
             "android:broadcast.allowBackgroundActivityStarts";
 
+    /**
+     * Allow the temp allowlist behavior, plus allow foreground service start from background.
+     */
+    public static final int TEMPORARY_WHITELIST_TYPE_FOREGROUND_SERVICE_ALLOWED = 0;
+    /**
+     * Only allow the temp allowlist behavior, not allow foreground service start from
+     * background.
+     */
+    public static final int TEMPORARY_WHITELIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED = 1;
+
+    /**
+     * The list of temp allowlist types.
+     * @hide
+     */
+    @IntDef(flag = true, prefix = { "TEMPORARY_WHITELIST_TYPE_" }, value = {
+            TEMPORARY_WHITELIST_TYPE_FOREGROUND_SERVICE_ALLOWED,
+            TEMPORARY_WHITELIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface TempAllowListType {}
+
     public static BroadcastOptions makeBasic() {
         BroadcastOptions opts = new BroadcastOptions();
         return opts;
@@ -77,6 +106,7 @@
     /** @hide */
     public BroadcastOptions(Bundle opts) {
         mTemporaryAppWhitelistDuration = opts.getLong(KEY_TEMPORARY_APP_WHITELIST_DURATION);
+        mTemporaryAppWhitelistType = opts.getInt(KEY_TEMPORARY_APP_WHITELIST_TYPE);
         mMinManifestReceiverApiLevel = opts.getInt(KEY_MIN_MANIFEST_RECEIVER_API_LEVEL, 0);
         mMaxManifestReceiverApiLevel = opts.getInt(KEY_MAX_MANIFEST_RECEIVER_API_LEVEL,
                 Build.VERSION_CODES.CUR_DEVELOPMENT);
@@ -95,6 +125,22 @@
             android.Manifest.permission.START_FOREGROUND_SERVICES_FROM_BACKGROUND})
     public void setTemporaryAppWhitelistDuration(long duration) {
         mTemporaryAppWhitelistDuration = duration;
+        mTemporaryAppWhitelistType = TEMPORARY_WHITELIST_TYPE_FOREGROUND_SERVICE_ALLOWED;
+    }
+
+    /**
+     * Set a duration for which the system should temporary place an application on the
+     * power allowlist when this broadcast is being delivered to it, specify the temp allowlist
+     * type.
+     * @param type one of {@link TempAllowListType}
+     * @param duration the duration in milliseconds; 0 means to not place on allowlist.
+     */
+    @RequiresPermission(anyOf = {android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST,
+            android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND,
+            android.Manifest.permission.START_FOREGROUND_SERVICES_FROM_BACKGROUND})
+    public void setTemporaryAppWhitelistDuration(@TempAllowListType int type, long duration) {
+        mTemporaryAppWhitelistDuration = duration;
+        mTemporaryAppWhitelistType = type;
     }
 
     /**
@@ -106,6 +152,14 @@
     }
 
     /**
+     * Return {@link #mTemporaryAppWhitelistType}.
+     * @hide
+     */
+    public @TempAllowListType int getTemporaryAppWhitelistType() {
+        return mTemporaryAppWhitelistType;
+    }
+
+    /**
      * Set the minimum target API level of receivers of the broadcast.  If an application
      * is targeting an API level less than this, the broadcast will not be delivered to
      * them.  This only applies to receivers declared in the app's AndroidManifest.xml.
@@ -190,6 +244,9 @@
         if (mTemporaryAppWhitelistDuration > 0) {
             b.putLong(KEY_TEMPORARY_APP_WHITELIST_DURATION, mTemporaryAppWhitelistDuration);
         }
+        if (mTemporaryAppWhitelistType != 0) {
+            b.putInt(KEY_TEMPORARY_APP_WHITELIST_TYPE, mTemporaryAppWhitelistType);
+        }
         if (mMinManifestReceiverApiLevel != 0) {
             b.putInt(KEY_MIN_MANIFEST_RECEIVER_API_LEVEL, mMinManifestReceiverApiLevel);
         }
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index 12460ba..da7a29f 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -1501,7 +1501,8 @@
     }
 
     /** @hide */
-    public boolean isNotificationPolicyAccessGrantedForPackage(String pkg) {
+    @TestApi
+    public boolean isNotificationPolicyAccessGrantedForPackage(@NonNull String pkg) {
         INotificationManager service = getService();
         try {
             return service.isNotificationPolicyAccessGrantedForPackage(pkg);
diff --git a/core/java/android/app/OWNERS b/core/java/android/app/OWNERS
new file mode 100644
index 0000000..633d093
--- /dev/null
+++ b/core/java/android/app/OWNERS
@@ -0,0 +1 @@
+per-file *Zygote* = file:/ZYGOTE_OWNERS
diff --git a/core/java/android/app/PictureInPictureParams.java b/core/java/android/app/PictureInPictureParams.java
index 32252a3f..29c9c67 100644
--- a/core/java/android/app/PictureInPictureParams.java
+++ b/core/java/android/app/PictureInPictureParams.java
@@ -26,6 +26,7 @@
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Objects;
 
 /**
  * Represents a set of parameters used to initialize and update an Activity in picture-in-picture
@@ -194,6 +195,16 @@
     }
 
     /**
+     * Makes a copy from the other picture-in-picture args.
+     * @hide
+     */
+    public PictureInPictureParams(PictureInPictureParams other) {
+        this(other.mAspectRatio, other.mUserActions,
+                other.hasSourceBoundsHint() ? new Rect(other.getSourceRectHint()) : null,
+                other.mAutoEnterEnabled);
+    }
+
+    /**
      * Copies the set parameters from the other picture-in-picture args.
      * @hide
      */
@@ -297,6 +308,22 @@
     }
 
     @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (!(o instanceof PictureInPictureParams)) return false;
+        PictureInPictureParams that = (PictureInPictureParams) o;
+        return mAutoEnterEnabled == that.mAutoEnterEnabled
+                && Objects.equals(mAspectRatio, that.mAspectRatio)
+                && Objects.equals(mUserActions, that.mUserActions)
+                && Objects.equals(mSourceRectHint, that.mSourceRectHint);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(mAspectRatio, mUserActions, mSourceRectHint, mAutoEnterEnabled);
+    }
+
+    @Override
     public int describeContents() {
         return 0;
     }
diff --git a/core/java/android/app/RemoteAction.java b/core/java/android/app/RemoteAction.java
index 5a4244f..26f324b 100644
--- a/core/java/android/app/RemoteAction.java
+++ b/core/java/android/app/RemoteAction.java
@@ -23,6 +23,7 @@
 import android.text.TextUtils;
 
 import java.io.PrintWriter;
+import java.util.Objects;
 
 /**
  * Represents a remote action that can be called from another process.  The action can have an
@@ -127,6 +128,25 @@
     }
 
     @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (!(o instanceof RemoteAction)) return false;
+        RemoteAction that = (RemoteAction) o;
+        return mEnabled == that.mEnabled
+                && mShouldShowIcon == that.mShouldShowIcon
+                && mIcon.equals(that.mIcon)
+                && mTitle.equals(that.mTitle)
+                && mContentDescription.equals(that.mContentDescription)
+                && mActionIntent.equals(that.mActionIntent);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(mIcon, mTitle, mContentDescription, mActionIntent, mEnabled,
+                mShouldShowIcon);
+    }
+
+    @Override
     public int describeContents() {
         return 0;
     }
diff --git a/core/java/android/app/TaskInfo.java b/core/java/android/app/TaskInfo.java
index 1a8a4b7..8367bde 100644
--- a/core/java/android/app/TaskInfo.java
+++ b/core/java/android/app/TaskInfo.java
@@ -313,7 +313,7 @@
                 && isResizeable == that.isResizeable
                 && Objects.equals(positionInParent, that.positionInParent)
                 && equalsLetterboxParams(that)
-                && pictureInPictureParams == that.pictureInPictureParams
+                && Objects.equals(pictureInPictureParams, that.pictureInPictureParams)
                 && getWindowingMode() == that.getWindowingMode()
                 && Objects.equals(taskDescription, that.taskDescription)
                 && isFocused == that.isFocused
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index da1219b..251252e 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -39,6 +39,7 @@
 import android.app.Activity;
 import android.app.IServiceConnection;
 import android.app.KeyguardManager;
+import android.app.admin.DevicePolicyManager.DevicePolicyOperation;
 import android.app.admin.SecurityLog.SecurityEvent;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.ComponentName;
@@ -2591,27 +2592,27 @@
     @Retention(RetentionPolicy.SOURCE)
     public @interface PersonalAppsSuspensionReason {}
 
-    // TODO(b/172376923) - make all (or none) @TestApi
-
     /** @hide */
     @TestApi
     public static final int OPERATION_LOCK_NOW = 1;
-
     /** @hide */
+    @TestApi
     public static final int OPERATION_SWITCH_USER = 2;
     /** @hide */
+    @TestApi
     public static final int OPERATION_START_USER_IN_BACKGROUND = 3;
     /** @hide */
+    @TestApi
     public static final int OPERATION_STOP_USER = 4;
     /** @hide */
+    @TestApi
     public static final int OPERATION_CREATE_AND_MANAGE_USER = 5;
     /** @hide */
+    @TestApi
     public static final int OPERATION_REMOVE_USER = 6;
 
     private static final String PREFIX_OPERATION = "OPERATION_";
 
-
-    // TODO(b/172376923) - add all operations
     /** @hide */
     @IntDef(prefix = PREFIX_OPERATION, value = {
             OPERATION_LOCK_NOW,
@@ -2626,6 +2627,8 @@
     }
 
     /** @hide */
+    @TestApi
+    @NonNull
     public static String operationToString(@DevicePolicyOperation int operation) {
         return DebugUtils.constantToString(DevicePolicyManager.class, PREFIX_OPERATION, operation);
     }
@@ -5755,7 +5758,6 @@
         return null;
     }
 
-
     /**
      * Called by a device or profile owner, or delegated certificate chooser (an app that has been
      * delegated the {@link #DELEGATION_CERT_SELECTION} privilege), to grant an application access
@@ -5793,6 +5795,51 @@
 
     /**
      * Called by a device or profile owner, or delegated certificate chooser (an app that has been
+     * delegated the {@link #DELEGATION_CERT_SELECTION} privilege), to query which apps have access
+     * to a given KeyChain key.
+     *
+     * Key are granted on a per-UID basis, so if several apps share the same UID, granting access to
+     * one of them automatically grants it to others. This method returns a set of sets of package
+     * names, where each internal set contains all packages sharing the same UID. Grantee packages
+     * that don't share UID with other packages are represented by singleton sets.
+     *
+     * @param alias The alias of the key to grant access to.
+     * @return package names of apps that have access to a given key, grouped by UIDs
+     *
+     * @throws SecurityException if the caller is not a device owner, a profile owner or
+     *         delegated certificate chooser.
+     * @throws IllegalArgumentException if {@code alias} doesn't correspond to an existing key.
+     *
+     * @see #grantKeyPairToApp(ComponentName, String, String)
+     */
+    public @NonNull Set<Set<String>> getKeyPairGrants(@NonNull String alias) {
+        throwIfParentInstance("getKeyPairGrants");
+        try {
+            // Set of sets is flattened into a null-separated list.
+            final List<String> flattened =
+                    mService.getKeyPairGrants(mContext.getPackageName(), alias);
+            final Set<Set<String>> result = new HashSet<>();
+            Set<String> pkgsForOneUid = new HashSet<>();
+            for (final String pkg : flattened) {
+                if (pkg == null) {
+                    result.add(pkgsForOneUid);
+                    pkgsForOneUid = new HashSet<>();
+                } else {
+                    pkgsForOneUid.add(pkg);
+                }
+            }
+            if (!pkgsForOneUid.isEmpty()) {
+                result.add(pkgsForOneUid);
+            }
+            return result;
+        } catch (RemoteException e) {
+            e.rethrowFromSystemServer();
+        }
+        return null;
+    }
+
+    /**
+     * Called by a device or profile owner, or delegated certificate chooser (an app that has been
      * delegated the {@link #DELEGATION_CERT_SELECTION} privilege), to revoke an application's
      * grant to a KeyChain key pair.
      * Calls by the application to {@link android.security.KeyChain#getPrivateKey}
@@ -12534,4 +12581,21 @@
         }
         return false;
     }
+
+    /**
+     * Used by CTS to set the result of the next safety operation check.
+     *
+     * @hide
+     */
+    @TestApi
+    @RequiresPermission(android.Manifest.permission.MANAGE_DEVICE_ADMINS)
+    public void setNextOperationSafety(@DevicePolicyOperation int operation, boolean safe) {
+        if (mService != null) {
+            try {
+                mService.setNextOperationSafety(operation, safe);
+            } catch (RemoteException re) {
+                throw re.rethrowFromSystemServer();
+            }
+        }
+    }
 }
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 8be3cdc..bcc90f7 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -471,6 +471,7 @@
     boolean startViewCalendarEventInManagedProfile(String packageName, long eventId, long start, long end, boolean allDay, int flags);
 
     boolean setKeyGrantForApp(in ComponentName admin, String callerPackage, String alias, String packageName, boolean hasGrant);
+    List<String> getKeyPairGrants(in String callerPackage, in String alias);
 
     void setUserControlDisabledPackages(in ComponentName admin, in List<String> packages);
 
@@ -484,5 +485,7 @@
 
     long getManagedProfileMaximumTimeOff(in ComponentName admin);
     void setManagedProfileMaximumTimeOff(in ComponentName admin, long timeoutMs);
-    boolean canProfileOwnerResetPasswordWhenLocked(in int userId);
+    boolean canProfileOwnerResetPasswordWhenLocked(int userId);
+
+    void setNextOperationSafety(int operation, boolean safe);
 }
diff --git a/core/java/android/app/admin/OWNERS b/core/java/android/app/admin/OWNERS
new file mode 100644
index 0000000..64a1d27
--- /dev/null
+++ b/core/java/android/app/admin/OWNERS
@@ -0,0 +1,4 @@
+# Bug component: 142675
+
[email protected]
[email protected]
diff --git a/core/java/android/app/assist/OWNERS b/core/java/android/app/assist/OWNERS
new file mode 100644
index 0000000..46b5ea0
--- /dev/null
+++ b/core/java/android/app/assist/OWNERS
@@ -0,0 +1,7 @@
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
diff --git a/core/java/android/app/backup/BackupManager.java b/core/java/android/app/backup/BackupManager.java
index 44a4b78..673de8f 100644
--- a/core/java/android/app/backup/BackupManager.java
+++ b/core/java/android/app/backup/BackupManager.java
@@ -205,13 +205,16 @@
     @Retention(RetentionPolicy.SOURCE)
     @IntDef({
         OperationType.BACKUP,
-        OperationType.MIGRATION
+        OperationType.MIGRATION,
+        OperationType.ADB_BACKUP,
     })
     public @interface OperationType {
-        // A regular backup / restore operation.
+        // A backup / restore to / from an off-device location, e.g. cloud.
         int BACKUP = 0;
-        // A full migration: all app data for non-system apps is eligible.
+        // A direct transfer to another device.
         int MIGRATION = 1;
+        // Backup via adb, data saved on the host machine.
+        int ADB_BACKUP = 3;
     }
 
     private Context mContext;
diff --git a/core/java/android/app/contentsuggestions/OWNERS b/core/java/android/app/contentsuggestions/OWNERS
new file mode 100644
index 0000000..482abb2
--- /dev/null
+++ b/core/java/android/app/contentsuggestions/OWNERS
@@ -0,0 +1,9 @@
+# Bug component: 643919
+
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
diff --git a/core/java/android/app/prediction/OWNERS b/core/java/android/app/prediction/OWNERS
new file mode 100644
index 0000000..fe012da
--- /dev/null
+++ b/core/java/android/app/prediction/OWNERS
@@ -0,0 +1,2 @@
[email protected]
[email protected]
diff --git a/core/java/android/app/role/OWNERS b/core/java/android/app/role/OWNERS
index b94d988..b8076366 100644
--- a/core/java/android/app/role/OWNERS
+++ b/core/java/android/app/role/OWNERS
@@ -1,6 +1,4 @@
[email protected]
[email protected]
+# Bug component: 137825
+
 [email protected]
[email protected]
[email protected]
[email protected]
[email protected]
diff --git a/core/java/android/app/servertransaction/OWNERS b/core/java/android/app/servertransaction/OWNERS
new file mode 100644
index 0000000..aa6248e
--- /dev/null
+++ b/core/java/android/app/servertransaction/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 316125
+
+include /services/core/java/com/android/server/wm/OWNERS
diff --git a/core/java/android/app/slice/OWNERS b/core/java/android/app/slice/OWNERS
new file mode 100644
index 0000000..b0a44fb
--- /dev/null
+++ b/core/java/android/app/slice/OWNERS
@@ -0,0 +1,6 @@
+# Bug component: 342804
+
[email protected]
[email protected]
[email protected]
[email protected]
diff --git a/core/java/android/app/timedetector/OWNERS b/core/java/android/app/timedetector/OWNERS
new file mode 100644
index 0000000..8c11324
--- /dev/null
+++ b/core/java/android/app/timedetector/OWNERS
@@ -0,0 +1,4 @@
+# Bug component: 847766
+
[email protected]
[email protected]
diff --git a/core/java/android/app/timezone/OWNERS b/core/java/android/app/timezone/OWNERS
new file mode 100644
index 0000000..8c11324
--- /dev/null
+++ b/core/java/android/app/timezone/OWNERS
@@ -0,0 +1,4 @@
+# Bug component: 847766
+
[email protected]
[email protected]
diff --git a/core/java/android/app/usage/OWNERS b/core/java/android/app/usage/OWNERS
new file mode 100644
index 0000000..a33d0ad
--- /dev/null
+++ b/core/java/android/app/usage/OWNERS
@@ -0,0 +1,5 @@
+# Bug component: 532296
+
[email protected]
[email protected]
[email protected]
diff --git a/core/java/android/attention/OWNERS b/core/java/android/attention/OWNERS
new file mode 100644
index 0000000..dd579b6
--- /dev/null
+++ b/core/java/android/attention/OWNERS
@@ -0,0 +1 @@
[email protected]
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index c07cd52..1713a0c 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -3689,7 +3689,7 @@
      *
      * @hide
      */
-    public abstract class BluetoothConnectionCallback {
+    public abstract static class BluetoothConnectionCallback {
         /**
          * Callback triggered when a bluetooth device (classic or BLE) is connected
          * @param device is the connected bluetooth device
diff --git a/core/java/android/bluetooth/OWNERS b/core/java/android/bluetooth/OWNERS
new file mode 100644
index 0000000..3523ee0
--- /dev/null
+++ b/core/java/android/bluetooth/OWNERS
@@ -0,0 +1,4 @@
+# Bug component: 27441
+
[email protected]
[email protected]
diff --git a/core/java/android/bluetooth/le/OWNERS b/core/java/android/bluetooth/le/OWNERS
new file mode 100644
index 0000000..3523ee0
--- /dev/null
+++ b/core/java/android/bluetooth/le/OWNERS
@@ -0,0 +1,4 @@
+# Bug component: 27441
+
[email protected]
[email protected]
diff --git a/core/java/android/companion/Association.java b/core/java/android/companion/Association.java
index 06a3f2f..17bf11b 100644
--- a/core/java/android/companion/Association.java
+++ b/core/java/android/companion/Association.java
@@ -37,6 +37,8 @@
     private final @UserIdInt int mUserId;
     private final @NonNull String mDeviceMacAddress;
     private final @NonNull String mPackageName;
+    private final @Nullable String mDeviceProfile;
+    private final boolean mKeepProfilePrivilegesWhenDeviceAway;
 
     /** @hide */
     public int getUserId() {
@@ -45,7 +47,7 @@
 
 
 
-    // Code below generated by codegen v1.0.15.
+    // Code below generated by codegen v1.0.21.
     //
     // DO NOT MODIFY!
     // CHECKSTYLE:OFF Generated code
@@ -67,7 +69,9 @@
     public Association(
             @UserIdInt int userId,
             @NonNull String deviceMacAddress,
-            @NonNull String packageName) {
+            @NonNull String packageName,
+            @Nullable String deviceProfile,
+            boolean keepProfilePrivilegesWhenDeviceAway) {
         this.mUserId = userId;
         com.android.internal.util.AnnotationValidations.validate(
                 UserIdInt.class, null, mUserId);
@@ -77,6 +81,8 @@
         this.mPackageName = packageName;
         com.android.internal.util.AnnotationValidations.validate(
                 NonNull.class, null, mPackageName);
+        this.mDeviceProfile = deviceProfile;
+        this.mKeepProfilePrivilegesWhenDeviceAway = keepProfilePrivilegesWhenDeviceAway;
 
         // onConstructed(); // You can define this method to get a callback
     }
@@ -91,6 +97,16 @@
         return mPackageName;
     }
 
+    @DataClass.Generated.Member
+    public @Nullable String getDeviceProfile() {
+        return mDeviceProfile;
+    }
+
+    @DataClass.Generated.Member
+    public boolean isKeepProfilePrivilegesWhenDeviceAway() {
+        return mKeepProfilePrivilegesWhenDeviceAway;
+    }
+
     @Override
     @DataClass.Generated.Member
     public String toString() {
@@ -100,7 +116,9 @@
         return "Association { " +
                 "userId = " + mUserId + ", " +
                 "deviceMacAddress = " + mDeviceMacAddress + ", " +
-                "packageName = " + mPackageName +
+                "packageName = " + mPackageName + ", " +
+                "deviceProfile = " + mDeviceProfile + ", " +
+                "keepProfilePrivilegesWhenDeviceAway = " + mKeepProfilePrivilegesWhenDeviceAway +
         " }";
     }
 
@@ -119,7 +137,9 @@
         return true
                 && mUserId == that.mUserId
                 && Objects.equals(mDeviceMacAddress, that.mDeviceMacAddress)
-                && Objects.equals(mPackageName, that.mPackageName);
+                && Objects.equals(mPackageName, that.mPackageName)
+                && Objects.equals(mDeviceProfile, that.mDeviceProfile)
+                && mKeepProfilePrivilegesWhenDeviceAway == that.mKeepProfilePrivilegesWhenDeviceAway;
     }
 
     @Override
@@ -132,6 +152,8 @@
         _hash = 31 * _hash + mUserId;
         _hash = 31 * _hash + Objects.hashCode(mDeviceMacAddress);
         _hash = 31 * _hash + Objects.hashCode(mPackageName);
+        _hash = 31 * _hash + Objects.hashCode(mDeviceProfile);
+        _hash = 31 * _hash + Boolean.hashCode(mKeepProfilePrivilegesWhenDeviceAway);
         return _hash;
     }
 
@@ -141,9 +163,14 @@
         // You can override field parcelling by defining methods like:
         // void parcelFieldName(Parcel dest, int flags) { ... }
 
+        byte flg = 0;
+        if (mKeepProfilePrivilegesWhenDeviceAway) flg |= 0x10;
+        if (mDeviceProfile != null) flg |= 0x8;
+        dest.writeByte(flg);
         dest.writeInt(mUserId);
         dest.writeString(mDeviceMacAddress);
         dest.writeString(mPackageName);
+        if (mDeviceProfile != null) dest.writeString(mDeviceProfile);
     }
 
     @Override
@@ -157,9 +184,12 @@
         // You can override field unparcelling by defining methods like:
         // static FieldType unparcelFieldName(Parcel in) { ... }
 
+        byte flg = in.readByte();
+        boolean keepProfilePrivilegesWhenDeviceAway = (flg & 0x10) != 0;
         int userId = in.readInt();
         String deviceMacAddress = in.readString();
         String packageName = in.readString();
+        String deviceProfile = (flg & 0x8) == 0 ? null : in.readString();
 
         this.mUserId = userId;
         com.android.internal.util.AnnotationValidations.validate(
@@ -170,6 +200,8 @@
         this.mPackageName = packageName;
         com.android.internal.util.AnnotationValidations.validate(
                 NonNull.class, null, mPackageName);
+        this.mDeviceProfile = deviceProfile;
+        this.mKeepProfilePrivilegesWhenDeviceAway = keepProfilePrivilegesWhenDeviceAway;
 
         // onConstructed(); // You can define this method to get a callback
     }
@@ -189,10 +221,10 @@
     };
 
     @DataClass.Generated(
-            time = 1599083149942L,
-            codegenVersion = "1.0.15",
+            time = 1606940835778L,
+            codegenVersion = "1.0.21",
             sourceFile = "frameworks/base/core/java/android/companion/Association.java",
-            inputSignatures = "private final @android.annotation.UserIdInt int mUserId\nprivate final @android.annotation.NonNull java.lang.String mDeviceMacAddress\nprivate final @android.annotation.NonNull java.lang.String mPackageName\npublic  int getUserId()\nclass Association extends java.lang.Object implements [android.os.Parcelable]\[email protected](genEqualsHashCode=true, genToString=true, genHiddenConstructor=true)")
+            inputSignatures = "private final @android.annotation.UserIdInt int mUserId\nprivate final @android.annotation.NonNull java.lang.String mDeviceMacAddress\nprivate final @android.annotation.NonNull java.lang.String mPackageName\nprivate final @android.annotation.Nullable java.lang.String mDeviceProfile\nprivate final  boolean mKeepProfilePrivilegesWhenDeviceAway\npublic  int getUserId()\nclass Association extends java.lang.Object implements [android.os.Parcelable]\[email protected](genEqualsHashCode=true, genToString=true, genHiddenConstructor=true)")
     @Deprecated
     private void __metadata() {}
 
diff --git a/core/java/android/content/om/OWNERS b/core/java/android/content/om/OWNERS
new file mode 100644
index 0000000..91a0abf
--- /dev/null
+++ b/core/java/android/content/om/OWNERS
@@ -0,0 +1,6 @@
+# Bug component: 568631
+
[email protected]
[email protected]
[email protected]
[email protected]
diff --git a/core/java/android/content/pm/OWNERS b/core/java/android/content/pm/OWNERS
index a16bb4f..3a590da 100644
--- a/core/java/android/content/pm/OWNERS
+++ b/core/java/android/content/pm/OWNERS
@@ -1 +1,7 @@
+# Bug component: 36137
+
[email protected]
[email protected]
[email protected]
+
 per-file PackageParser.java = [email protected]
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index d4a98f8..4347f99 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -37,6 +37,7 @@
 import android.content.IntentSender;
 import android.content.pm.PackageManager.DeleteFlags;
 import android.content.pm.PackageManager.InstallReason;
+import android.content.pm.PackageManager.InstallScenario;
 import android.graphics.Bitmap;
 import android.net.Uri;
 import android.os.Build;
@@ -1525,6 +1526,14 @@
         public int installLocation = PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY;
         /** {@hide} */
         public @InstallReason int installReason = PackageManager.INSTALL_REASON_UNKNOWN;
+        /**
+         * {@hide}
+         *
+         * This flag indicates which installation scenario best describes this session.  The system
+         * may use this value when making decisions about how to handle the installation, such as
+         * prioritizing system health or user experience.
+         */
+        public @InstallScenario int installScenario = PackageManager.INSTALL_SCENARIO_DEFAULT;
         /** {@hide} */
         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
         public long sizeBytes = -1;
@@ -1588,6 +1597,7 @@
             installFlags = source.readInt();
             installLocation = source.readInt();
             installReason = source.readInt();
+            installScenario = source.readInt();
             sizeBytes = source.readLong();
             appPackageName = source.readString();
             appIcon = source.readParcelable(null);
@@ -1619,6 +1629,7 @@
             ret.installFlags = installFlags;
             ret.installLocation = installLocation;
             ret.installReason = installReason;
+            ret.installScenario = installScenario;
             ret.sizeBytes = sizeBytes;
             ret.appPackageName = appPackageName;
             ret.appIcon = appIcon;  // not a copy.
@@ -2044,6 +2055,8 @@
             pw.printPair("mode", mode);
             pw.printHexPair("installFlags", installFlags);
             pw.printPair("installLocation", installLocation);
+            pw.printPair("installReason", installReason);
+            pw.printPair("installScenario", installScenario);
             pw.printPair("sizeBytes", sizeBytes);
             pw.printPair("appPackageName", appPackageName);
             pw.printPair("appIcon", (appIcon != null));
@@ -2077,6 +2090,7 @@
             dest.writeInt(installFlags);
             dest.writeInt(installLocation);
             dest.writeInt(installReason);
+            dest.writeInt(installScenario);
             dest.writeLong(sizeBytes);
             dest.writeString(appPackageName);
             dest.writeParcelable(appIcon, flags);
@@ -2195,6 +2209,8 @@
         /** {@hide} */
         public @InstallReason int installReason;
         /** {@hide} */
+        public @InstallReason int installScenario;
+        /** {@hide} */
         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
         public long sizeBytes;
         /** {@hide} */
@@ -2273,6 +2289,7 @@
 
             mode = source.readInt();
             installReason = source.readInt();
+            installScenario = source.readInt();
             sizeBytes = source.readLong();
             appPackageName = source.readString();
             appIcon = source.readParcelable(null);
@@ -2820,6 +2837,7 @@
 
             dest.writeInt(mode);
             dest.writeInt(installReason);
+            dest.writeInt(installScenario);
             dest.writeLong(sizeBytes);
             dest.writeString(appPackageName);
             dest.writeParcelable(appIcon, flags);
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 19e4d14..cf3f706 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -1323,6 +1323,60 @@
     public static final int INSTALL_REASON_ROLLBACK = 5;
 
     /** @hide */
+    @IntDef(prefix = { "INSTALL_SCENARIO_" }, value = {
+            INSTALL_SCENARIO_DEFAULT,
+            INSTALL_SCENARIO_FAST,
+            INSTALL_SCENARIO_BULK,
+            INSTALL_SCENARIO_BULK_SECONDARY,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface InstallScenario {}
+
+    /**
+     * A value to indicate the lack of CUJ information, disabling all installation scenario logic.
+     *
+     * @hide
+     */
+    public static final int INSTALL_SCENARIO_DEFAULT = 0;
+
+    /**
+     * Installation scenario providing the fastest “install button to launch" experience possible.
+     *
+     * @hide
+     */
+    public static final int INSTALL_SCENARIO_FAST = 1;
+
+    /**
+     * Installation scenario indicating a bulk operation with the desired result of a fully
+     * optimized application.  If the system is busy or resources are scarce the system will
+     * perform less work to avoid impacting system health.
+     *
+     * Examples of bulk installation scenarios might include device restore, background updates of
+     * multiple applications, or user-triggered updates for all applications.
+     *
+     * The decision to use BULK or BULK_SECONDARY should be based on the desired user experience.
+     * BULK_SECONDARY operations may take less time to complete but, when they do, will produce
+     * less optimized applications.  The device state (e.g. memory usage or battery status) should
+     * not be considered when making this decision as those factors are taken into account by the
+     * Package Manager when acting on the installation scenario.
+     *
+     * @hide
+     */
+    public static final int INSTALL_SCENARIO_BULK = 2;
+
+    /**
+     * Installation scenario indicating a bulk operation that prioritizes minimal system health
+     * impact over application optimization.  The application may undergo additional optimization
+     * if the system is idle and system resources are abundant.  The more elements of a bulk
+     * operation that are marked BULK_SECONDARY, the faster the entire bulk operation will be.
+     *
+     * See the comments for INSTALL_SCENARIO_BULK for more information.
+     *
+     * @hide
+     */
+    public static final int INSTALL_SCENARIO_BULK_SECONDARY = 3;
+
+    /** @hide */
     @IntDef(prefix = { "UNINSTALL_REASON_" }, value = {
             UNINSTALL_REASON_UNKNOWN,
             UNINSTALL_REASON_USER_TYPE,
@@ -4131,6 +4185,14 @@
      */
     public static final int UNSTARTABLE_REASON_INSUFFICIENT_STORAGE = 2;
 
+    /**
+     * A manifest property to control app's participation in {@code adb backup}. Should only
+     * be used by system / privileged apps.
+     *
+     * @hide
+     */
+    public static final String PROPERTY_ALLOW_ADB_BACKUP = "android.backup.ALLOW_ADB_BACKUP";
+
     /** {@hide} */
     public int getUserId() {
         return UserHandle.myUserId();
diff --git a/core/java/android/content/pm/dex/OWNERS b/core/java/android/content/pm/dex/OWNERS
new file mode 100644
index 0000000..267e5d58
--- /dev/null
+++ b/core/java/android/content/pm/dex/OWNERS
@@ -0,0 +1,7 @@
+# Bug component: 86431
+
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
diff --git a/core/java/android/content/pm/permission/OWNERS b/core/java/android/content/pm/permission/OWNERS
new file mode 100644
index 0000000..cde7b2a
--- /dev/null
+++ b/core/java/android/content/pm/permission/OWNERS
@@ -0,0 +1,11 @@
+# Bug component: 137825
+
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
diff --git a/core/java/android/content/pm/split/OWNERS b/core/java/android/content/pm/split/OWNERS
new file mode 100644
index 0000000..3d126d2
--- /dev/null
+++ b/core/java/android/content/pm/split/OWNERS
@@ -0,0 +1,5 @@
+# Bug component: 36137
+
[email protected]
[email protected]
[email protected]
diff --git a/core/java/android/content/res/OWNERS b/core/java/android/content/res/OWNERS
new file mode 100644
index 0000000..bc2355c
--- /dev/null
+++ b/core/java/android/content/res/OWNERS
@@ -0,0 +1,6 @@
+# Bug component: 568761
+
[email protected]
[email protected]
[email protected]
[email protected]
diff --git a/core/java/android/content/rollback/OWNERS b/core/java/android/content/rollback/OWNERS
new file mode 100644
index 0000000..3093fd6
--- /dev/null
+++ b/core/java/android/content/rollback/OWNERS
@@ -0,0 +1,5 @@
+# Bug component: 557916
+
[email protected]
[email protected]
[email protected]
diff --git a/core/java/android/database/OWNERS b/core/java/android/database/OWNERS
index 7e19942..1734cfc 100644
--- a/core/java/android/database/OWNERS
+++ b/core/java/android/database/OWNERS
@@ -1,3 +1,3 @@
 [email protected]
[email protected]
[email protected]
 [email protected]
diff --git a/core/java/android/gesture/OWNERS b/core/java/android/gesture/OWNERS
new file mode 100644
index 0000000..b3b8775
--- /dev/null
+++ b/core/java/android/gesture/OWNERS
@@ -0,0 +1,8 @@
+# Bug component: 25700
+
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
diff --git a/core/java/android/hardware/biometrics/OWNERS b/core/java/android/hardware/biometrics/OWNERS
new file mode 100644
index 0000000..33527f8
--- /dev/null
+++ b/core/java/android/hardware/biometrics/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 879035
+
[email protected]
diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java
index a0c1223..0f595b7 100644
--- a/core/java/android/hardware/camera2/CameraCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraCharacteristics.java
@@ -1467,12 +1467,13 @@
      * to any real physical measurement, but <code>0.0f</code> still represents farthest
      * focus, and {@link CameraCharacteristics#LENS_INFO_MINIMUM_FOCUS_DISTANCE android.lens.info.minimumFocusDistance} represents the
      * nearest focus the device can achieve.</p>
-     * <p><b>Possible values:</b>
+     * <p><b>Possible values:</b></p>
      * <ul>
      *   <li>{@link #LENS_INFO_FOCUS_DISTANCE_CALIBRATION_UNCALIBRATED UNCALIBRATED}</li>
      *   <li>{@link #LENS_INFO_FOCUS_DISTANCE_CALIBRATION_APPROXIMATE APPROXIMATE}</li>
      *   <li>{@link #LENS_INFO_FOCUS_DISTANCE_CALIBRATION_CALIBRATED CALIBRATED}</li>
-     * </ul></p>
+     * </ul>
+     *
      * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p>
      * <p><b>Limited capability</b> -
      * Present on all camera devices that report being at least {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED HARDWARE_LEVEL_LIMITED} devices in the
@@ -1495,12 +1496,13 @@
     /**
      * <p>Direction the camera faces relative to
      * device screen.</p>
-     * <p><b>Possible values:</b>
+     * <p><b>Possible values:</b></p>
      * <ul>
      *   <li>{@link #LENS_FACING_FRONT FRONT}</li>
      *   <li>{@link #LENS_FACING_BACK BACK}</li>
      *   <li>{@link #LENS_FACING_EXTERNAL EXTERNAL}</li>
-     * </ul></p>
+     * </ul>
+     *
      * <p>This key is available on all devices.</p>
      * @see #LENS_FACING_FRONT
      * @see #LENS_FACING_BACK
@@ -1726,12 +1728,13 @@
      * {@link CameraCharacteristics#LENS_POSE_TRANSLATION android.lens.poseTranslation} and {@link CameraCharacteristics#LENS_POSE_ROTATION android.lens.poseRotation}.</p>
      * <p>Different calibration methods and use cases can produce better or worse results
      * depending on the selected coordinate origin.</p>
-     * <p><b>Possible values:</b>
+     * <p><b>Possible values:</b></p>
      * <ul>
      *   <li>{@link #LENS_POSE_REFERENCE_PRIMARY_CAMERA PRIMARY_CAMERA}</li>
      *   <li>{@link #LENS_POSE_REFERENCE_GYROSCOPE GYROSCOPE}</li>
      *   <li>{@link #LENS_POSE_REFERENCE_UNDEFINED UNDEFINED}</li>
-     * </ul></p>
+     * </ul>
+     *
      * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p>
      * <p><b>Permission {@link android.Manifest.permission#CAMERA } is needed to access this property</b></p>
      *
@@ -2057,7 +2060,7 @@
      * </ul>
      * <p>Other capabilities may be available on either FULL or LIMITED
      * devices, but the application should query this key to be sure.</p>
-     * <p><b>Possible values:</b>
+     * <p><b>Possible values:</b></p>
      * <ul>
      *   <li>{@link #REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE BACKWARD_COMPATIBLE}</li>
      *   <li>{@link #REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR MANUAL_SENSOR}</li>
@@ -2075,7 +2078,8 @@
      *   <li>{@link #REQUEST_AVAILABLE_CAPABILITIES_SECURE_IMAGE_DATA SECURE_IMAGE_DATA}</li>
      *   <li>{@link #REQUEST_AVAILABLE_CAPABILITIES_SYSTEM_CAMERA SYSTEM_CAMERA}</li>
      *   <li>{@link #REQUEST_AVAILABLE_CAPABILITIES_OFFLINE_PROCESSING OFFLINE_PROCESSING}</li>
-     * </ul></p>
+     * </ul>
+     *
      * <p>This key is available on all devices.</p>
      *
      * @see CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL
@@ -2777,11 +2781,12 @@
      * array.</li>
      * </ul>
      * <p>LEGACY capability devices will only support CENTER_ONLY cropping.</p>
-     * <p><b>Possible values:</b>
+     * <p><b>Possible values:</b></p>
      * <ul>
      *   <li>{@link #SCALER_CROPPING_TYPE_CENTER_ONLY CENTER_ONLY}</li>
      *   <li>{@link #SCALER_CROPPING_TYPE_FREEFORM FREEFORM}</li>
-     * </ul></p>
+     * </ul>
+     *
      * <p>This key is available on all devices.</p>
      *
      * @see CaptureRequest#CONTROL_ZOOM_RATIO
@@ -2966,7 +2971,7 @@
      * represents the colors in the top-left 2x2 section of
      * the sensor, in reading order, for a Bayer camera, or the
      * light spectrum it captures for MONOCHROME camera.</p>
-     * <p><b>Possible values:</b>
+     * <p><b>Possible values:</b></p>
      * <ul>
      *   <li>{@link #SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_RGGB RGGB}</li>
      *   <li>{@link #SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_GRBG GRBG}</li>
@@ -2975,7 +2980,8 @@
      *   <li>{@link #SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_RGB RGB}</li>
      *   <li>{@link #SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_MONO MONO}</li>
      *   <li>{@link #SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_NIR NIR}</li>
-     * </ul></p>
+     * </ul>
+     *
      * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p>
      * <p><b>Full capability</b> -
      * Present on all camera devices that report being {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL_FULL HARDWARE_LEVEL_FULL} devices in the
@@ -3117,11 +3123,12 @@
      * may not based on a time source that can be compared to other system time sources.</p>
      * <p>This characteristic defines the source for the timestamps, and therefore whether they
      * can be compared against other system time sources/timestamps.</p>
-     * <p><b>Possible values:</b>
+     * <p><b>Possible values:</b></p>
      * <ul>
      *   <li>{@link #SENSOR_INFO_TIMESTAMP_SOURCE_UNKNOWN UNKNOWN}</li>
      *   <li>{@link #SENSOR_INFO_TIMESTAMP_SOURCE_REALTIME REALTIME}</li>
-     * </ul></p>
+     * </ul>
+     *
      * <p>This key is available on all devices.</p>
      * @see #SENSOR_INFO_TIMESTAMP_SOURCE_UNKNOWN
      * @see #SENSOR_INFO_TIMESTAMP_SOURCE_REALTIME
@@ -3231,7 +3238,7 @@
      * {@link CameraCharacteristics#SENSOR_REFERENCE_ILLUMINANT2 android.sensor.referenceIlluminant2} and its corresponding matrices.</p>
      * <p>Starting from Android Q, this key will not be present for a MONOCHROME camera, even if
      * the camera device has RAW capability.</p>
-     * <p><b>Possible values:</b>
+     * <p><b>Possible values:</b></p>
      * <ul>
      *   <li>{@link #SENSOR_REFERENCE_ILLUMINANT1_DAYLIGHT DAYLIGHT}</li>
      *   <li>{@link #SENSOR_REFERENCE_ILLUMINANT1_FLUORESCENT FLUORESCENT}</li>
@@ -3252,7 +3259,8 @@
      *   <li>{@link #SENSOR_REFERENCE_ILLUMINANT1_D75 D75}</li>
      *   <li>{@link #SENSOR_REFERENCE_ILLUMINANT1_D50 D50}</li>
      *   <li>{@link #SENSOR_REFERENCE_ILLUMINANT1_ISO_STUDIO_TUNGSTEN ISO_STUDIO_TUNGSTEN}</li>
-     * </ul></p>
+     * </ul>
+     *
      * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p>
      * <p><b>Permission {@link android.Manifest.permission#CAMERA } is needed to access this property</b></p>
      *
@@ -3727,10 +3735,11 @@
 
     /**
      * <p>A list of camera LEDs that are available on this system.</p>
-     * <p><b>Possible values:</b>
+     * <p><b>Possible values:</b></p>
      * <ul>
      *   <li>{@link #LED_AVAILABLE_LEDS_TRANSMIT TRANSMIT}</li>
-     * </ul></p>
+     * </ul>
+     *
      * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p>
      * @see #LED_AVAILABLE_LEDS_TRANSMIT
      * @hide
@@ -3799,14 +3808,15 @@
      *   ({@link CameraCharacteristics#LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION android.lens.info.availableOpticalStabilization},
      *    {@link CameraCharacteristics#CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES android.control.availableVideoStabilizationModes})</li>
      * </ul>
-     * <p><b>Possible values:</b>
+     * <p><b>Possible values:</b></p>
      * <ul>
      *   <li>{@link #INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED LIMITED}</li>
      *   <li>{@link #INFO_SUPPORTED_HARDWARE_LEVEL_FULL FULL}</li>
      *   <li>{@link #INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY LEGACY}</li>
      *   <li>{@link #INFO_SUPPORTED_HARDWARE_LEVEL_3 3}</li>
      *   <li>{@link #INFO_SUPPORTED_HARDWARE_LEVEL_EXTERNAL EXTERNAL}</li>
-     * </ul></p>
+     * </ul>
+     *
      * <p>This key is available on all devices.</p>
      *
      * @see CameraCharacteristics#CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES
@@ -3850,11 +3860,12 @@
      * must occur before the camera device knows for a fact that the new
      * submitted camera settings have been applied in outgoing frames.</p>
      * <p><b>Units</b>: Frame counts</p>
-     * <p><b>Possible values:</b>
+     * <p><b>Possible values:</b></p>
      * <ul>
      *   <li>{@link #SYNC_MAX_LATENCY_PER_FRAME_CONTROL PER_FRAME_CONTROL}</li>
      *   <li>{@link #SYNC_MAX_LATENCY_UNKNOWN UNKNOWN}</li>
-     * </ul></p>
+     * </ul>
+     *
      * <p><b>Available values for this device:</b><br>
      * A positive value, PER_FRAME_CONTROL, or UNKNOWN.</p>
      * <p>This key is available on all devices.</p>
@@ -4102,11 +4113,12 @@
      * onCaptureStarted callback.</p>
      * <p>This tag is only applicable if the logical camera device supports concurrent physical
      * streams from different physical cameras.</p>
-     * <p><b>Possible values:</b>
+     * <p><b>Possible values:</b></p>
      * <ul>
      *   <li>{@link #LOGICAL_MULTI_CAMERA_SENSOR_SYNC_TYPE_APPROXIMATE APPROXIMATE}</li>
      *   <li>{@link #LOGICAL_MULTI_CAMERA_SENSOR_SYNC_TYPE_CALIBRATED CALIBRATED}</li>
-     * </ul></p>
+     * </ul>
+     *
      * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p>
      * <p><b>Limited capability</b> -
      * Present on all camera devices that report being at least {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED HARDWARE_LEVEL_LIMITED} devices in the
diff --git a/core/java/android/hardware/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java
index d85bcbd..d7aee10 100644
--- a/core/java/android/hardware/camera2/CaptureRequest.java
+++ b/core/java/android/hardware/camera2/CaptureRequest.java
@@ -1028,12 +1028,13 @@
      * </code></pre>
      * <p>Both the input and output value ranges must match. Overflow/underflow
      * values are clipped to fit within the range.</p>
-     * <p><b>Possible values:</b>
+     * <p><b>Possible values:</b></p>
      * <ul>
      *   <li>{@link #COLOR_CORRECTION_MODE_TRANSFORM_MATRIX TRANSFORM_MATRIX}</li>
      *   <li>{@link #COLOR_CORRECTION_MODE_FAST FAST}</li>
      *   <li>{@link #COLOR_CORRECTION_MODE_HIGH_QUALITY HIGH_QUALITY}</li>
-     * </ul></p>
+     * </ul>
+     *
      * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p>
      * <p><b>Full capability</b> -
      * Present on all camera devices that report being {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL_FULL HARDWARE_LEVEL_FULL} devices in the
@@ -1121,12 +1122,13 @@
      * capture rate. FAST means the camera device will not slow down capture rate when
      * applying aberration correction.</p>
      * <p>LEGACY devices will always be in FAST mode.</p>
-     * <p><b>Possible values:</b>
+     * <p><b>Possible values:</b></p>
      * <ul>
      *   <li>{@link #COLOR_CORRECTION_ABERRATION_MODE_OFF OFF}</li>
      *   <li>{@link #COLOR_CORRECTION_ABERRATION_MODE_FAST FAST}</li>
      *   <li>{@link #COLOR_CORRECTION_ABERRATION_MODE_HIGH_QUALITY HIGH_QUALITY}</li>
-     * </ul></p>
+     * </ul>
+     *
      * <p><b>Available values for this device:</b><br>
      * {@link CameraCharacteristics#COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES android.colorCorrection.availableAberrationModes}</p>
      * <p>This key is available on all devices.</p>
@@ -1173,13 +1175,14 @@
      * ensure it selects exposure times that do not cause banding
      * issues. The {@link CaptureResult#STATISTICS_SCENE_FLICKER android.statistics.sceneFlicker} key can assist
      * the application in this.</p>
-     * <p><b>Possible values:</b>
+     * <p><b>Possible values:</b></p>
      * <ul>
      *   <li>{@link #CONTROL_AE_ANTIBANDING_MODE_OFF OFF}</li>
      *   <li>{@link #CONTROL_AE_ANTIBANDING_MODE_50HZ 50HZ}</li>
      *   <li>{@link #CONTROL_AE_ANTIBANDING_MODE_60HZ 60HZ}</li>
      *   <li>{@link #CONTROL_AE_ANTIBANDING_MODE_AUTO AUTO}</li>
-     * </ul></p>
+     * </ul>
+     *
      * <p><b>Available values for this device:</b><br></p>
      * <p>{@link CameraCharacteristics#CONTROL_AE_AVAILABLE_ANTIBANDING_MODES android.control.aeAvailableAntibandingModes}</p>
      * <p>This key is available on all devices.</p>
@@ -1304,7 +1307,7 @@
      * camera device auto-exposure routine for the overridden
      * fields for a given capture will be available in its
      * CaptureResult.</p>
-     * <p><b>Possible values:</b>
+     * <p><b>Possible values:</b></p>
      * <ul>
      *   <li>{@link #CONTROL_AE_MODE_OFF OFF}</li>
      *   <li>{@link #CONTROL_AE_MODE_ON ON}</li>
@@ -1312,7 +1315,8 @@
      *   <li>{@link #CONTROL_AE_MODE_ON_ALWAYS_FLASH ON_ALWAYS_FLASH}</li>
      *   <li>{@link #CONTROL_AE_MODE_ON_AUTO_FLASH_REDEYE ON_AUTO_FLASH_REDEYE}</li>
      *   <li>{@link #CONTROL_AE_MODE_ON_EXTERNAL_FLASH ON_EXTERNAL_FLASH}</li>
-     * </ul></p>
+     * </ul>
+     *
      * <p><b>Available values for this device:</b><br>
      * {@link CameraCharacteristics#CONTROL_AE_AVAILABLE_MODES android.control.aeAvailableModes}</p>
      * <p>This key is available on all devices.</p>
@@ -1478,12 +1482,13 @@
      * example.</p>
      * <p>If both the precapture and the auto-focus trigger are activated on the same request, then
      * the camera device will complete them in the optimal order for that device.</p>
-     * <p><b>Possible values:</b>
+     * <p><b>Possible values:</b></p>
      * <ul>
      *   <li>{@link #CONTROL_AE_PRECAPTURE_TRIGGER_IDLE IDLE}</li>
      *   <li>{@link #CONTROL_AE_PRECAPTURE_TRIGGER_START START}</li>
      *   <li>{@link #CONTROL_AE_PRECAPTURE_TRIGGER_CANCEL CANCEL}</li>
-     * </ul></p>
+     * </ul>
+     *
      * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p>
      * <p><b>Limited capability</b> -
      * Present on all camera devices that report being at least {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED HARDWARE_LEVEL_LIMITED} devices in the
@@ -1514,7 +1519,7 @@
      * <p>If the lens is controlled by the camera device auto-focus algorithm,
      * the camera device will report the current AF status in {@link CaptureResult#CONTROL_AF_STATE android.control.afState}
      * in result metadata.</p>
-     * <p><b>Possible values:</b>
+     * <p><b>Possible values:</b></p>
      * <ul>
      *   <li>{@link #CONTROL_AF_MODE_OFF OFF}</li>
      *   <li>{@link #CONTROL_AF_MODE_AUTO AUTO}</li>
@@ -1522,7 +1527,8 @@
      *   <li>{@link #CONTROL_AF_MODE_CONTINUOUS_VIDEO CONTINUOUS_VIDEO}</li>
      *   <li>{@link #CONTROL_AF_MODE_CONTINUOUS_PICTURE CONTINUOUS_PICTURE}</li>
      *   <li>{@link #CONTROL_AF_MODE_EDOF EDOF}</li>
-     * </ul></p>
+     * </ul>
+     *
      * <p><b>Available values for this device:</b><br>
      * {@link CameraCharacteristics#CONTROL_AF_AVAILABLE_MODES android.control.afAvailableModes}</p>
      * <p>This key is available on all devices.</p>
@@ -1637,12 +1643,13 @@
      * focus sweep), the camera device may delay acting on a later trigger until the previous
      * trigger has been fully handled. This may lead to longer intervals between the trigger and
      * changes to {@link CaptureResult#CONTROL_AF_STATE android.control.afState}, for example.</p>
-     * <p><b>Possible values:</b>
+     * <p><b>Possible values:</b></p>
      * <ul>
      *   <li>{@link #CONTROL_AF_TRIGGER_IDLE IDLE}</li>
      *   <li>{@link #CONTROL_AF_TRIGGER_START START}</li>
      *   <li>{@link #CONTROL_AF_TRIGGER_CANCEL CANCEL}</li>
-     * </ul></p>
+     * </ul>
+     *
      * <p>This key is available on all devices.</p>
      *
      * @see CaptureRequest#CONTROL_AE_PRECAPTURE_TRIGGER
@@ -1710,7 +1717,7 @@
      * {@link CaptureRequest#COLOR_CORRECTION_TRANSFORM android.colorCorrection.transform},
      * {@link CaptureRequest#COLOR_CORRECTION_GAINS android.colorCorrection.gains} and
      * {@link CaptureRequest#COLOR_CORRECTION_MODE android.colorCorrection.mode} are ignored.</p>
-     * <p><b>Possible values:</b>
+     * <p><b>Possible values:</b></p>
      * <ul>
      *   <li>{@link #CONTROL_AWB_MODE_OFF OFF}</li>
      *   <li>{@link #CONTROL_AWB_MODE_AUTO AUTO}</li>
@@ -1721,7 +1728,8 @@
      *   <li>{@link #CONTROL_AWB_MODE_CLOUDY_DAYLIGHT CLOUDY_DAYLIGHT}</li>
      *   <li>{@link #CONTROL_AWB_MODE_TWILIGHT TWILIGHT}</li>
      *   <li>{@link #CONTROL_AWB_MODE_SHADE SHADE}</li>
-     * </ul></p>
+     * </ul>
+     *
      * <p><b>Available values for this device:</b><br>
      * {@link CameraCharacteristics#CONTROL_AWB_AVAILABLE_MODES android.control.awbAvailableModes}</p>
      * <p>This key is available on all devices.</p>
@@ -1835,7 +1843,7 @@
      * MANUAL_SENSOR.
      *   * MOTION_TRACKING will be supported if {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities} contains
      * MOTION_TRACKING.</p>
-     * <p><b>Possible values:</b>
+     * <p><b>Possible values:</b></p>
      * <ul>
      *   <li>{@link #CONTROL_CAPTURE_INTENT_CUSTOM CUSTOM}</li>
      *   <li>{@link #CONTROL_CAPTURE_INTENT_PREVIEW PREVIEW}</li>
@@ -1845,7 +1853,8 @@
      *   <li>{@link #CONTROL_CAPTURE_INTENT_ZERO_SHUTTER_LAG ZERO_SHUTTER_LAG}</li>
      *   <li>{@link #CONTROL_CAPTURE_INTENT_MANUAL MANUAL}</li>
      *   <li>{@link #CONTROL_CAPTURE_INTENT_MOTION_TRACKING MOTION_TRACKING}</li>
-     * </ul></p>
+     * </ul>
+     *
      * <p>This key is available on all devices.</p>
      *
      * @see CaptureRequest#CONTROL_MODE
@@ -1872,7 +1881,7 @@
      * implementor of the camera device, and should not be
      * depended on to be consistent (or present) across all
      * devices.</p>
-     * <p><b>Possible values:</b>
+     * <p><b>Possible values:</b></p>
      * <ul>
      *   <li>{@link #CONTROL_EFFECT_MODE_OFF OFF}</li>
      *   <li>{@link #CONTROL_EFFECT_MODE_MONO MONO}</li>
@@ -1883,7 +1892,8 @@
      *   <li>{@link #CONTROL_EFFECT_MODE_WHITEBOARD WHITEBOARD}</li>
      *   <li>{@link #CONTROL_EFFECT_MODE_BLACKBOARD BLACKBOARD}</li>
      *   <li>{@link #CONTROL_EFFECT_MODE_AQUA AQUA}</li>
-     * </ul></p>
+     * </ul>
+     *
      * <p><b>Available values for this device:</b><br>
      * {@link CameraCharacteristics#CONTROL_AVAILABLE_EFFECTS android.control.availableEffects}</p>
      * <p>This key is available on all devices.</p>
@@ -1922,14 +1932,15 @@
      * update, as if this frame is never captured. This mode can be used in the scenario
      * where the application doesn't want a 3A manual control capture to affect
      * the subsequent auto 3A capture results.</p>
-     * <p><b>Possible values:</b>
+     * <p><b>Possible values:</b></p>
      * <ul>
      *   <li>{@link #CONTROL_MODE_OFF OFF}</li>
      *   <li>{@link #CONTROL_MODE_AUTO AUTO}</li>
      *   <li>{@link #CONTROL_MODE_USE_SCENE_MODE USE_SCENE_MODE}</li>
      *   <li>{@link #CONTROL_MODE_OFF_KEEP_STATE OFF_KEEP_STATE}</li>
      *   <li>{@link #CONTROL_MODE_USE_EXTENDED_SCENE_MODE USE_EXTENDED_SCENE_MODE}</li>
-     * </ul></p>
+     * </ul>
+     *
      * <p><b>Available values for this device:</b><br>
      * {@link CameraCharacteristics#CONTROL_AVAILABLE_MODES android.control.availableModes}</p>
      * <p>This key is available on all devices.</p>
@@ -1959,7 +1970,7 @@
      * to the implementor of the camera device. Their behavior will not be
      * consistent across all devices, and any given device may only implement
      * a subset of these modes.</p>
-     * <p><b>Possible values:</b>
+     * <p><b>Possible values:</b></p>
      * <ul>
      *   <li>{@link #CONTROL_SCENE_MODE_DISABLED DISABLED}</li>
      *   <li>{@link #CONTROL_SCENE_MODE_FACE_PRIORITY FACE_PRIORITY}</li>
@@ -1980,7 +1991,8 @@
      *   <li>{@link #CONTROL_SCENE_MODE_BARCODE BARCODE}</li>
      *   <li>{@link #CONTROL_SCENE_MODE_HIGH_SPEED_VIDEO HIGH_SPEED_VIDEO}</li>
      *   <li>{@link #CONTROL_SCENE_MODE_HDR HDR}</li>
-     * </ul></p>
+     * </ul>
+     *
      * <p><b>Available values for this device:</b><br>
      * {@link CameraCharacteristics#CONTROL_AVAILABLE_SCENE_MODES android.control.availableSceneModes}</p>
      * <p>This key is available on all devices.</p>
@@ -2041,11 +2053,12 @@
      * ({@link CaptureRequest#LENS_OPTICAL_STABILIZATION_MODE android.lens.opticalStabilizationMode}), turning both modes on may
      * produce undesirable interaction, so it is recommended not to enable
      * both at the same time.</p>
-     * <p><b>Possible values:</b>
+     * <p><b>Possible values:</b></p>
      * <ul>
      *   <li>{@link #CONTROL_VIDEO_STABILIZATION_MODE_OFF OFF}</li>
      *   <li>{@link #CONTROL_VIDEO_STABILIZATION_MODE_ON ON}</li>
-     * </ul></p>
+     * </ul>
+     *
      * <p>This key is available on all devices.</p>
      *
      * @see CaptureRequest#CONTROL_VIDEO_STABILIZATION_MODE
@@ -2155,12 +2168,13 @@
      * with different field of view. As a result, when bokeh mode is enabled, the camera device
      * may override {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion} or {@link CaptureRequest#CONTROL_ZOOM_RATIO android.control.zoomRatio}, and the field of
      * view may be smaller than when bokeh mode is off.</p>
-     * <p><b>Possible values:</b>
+     * <p><b>Possible values:</b></p>
      * <ul>
      *   <li>{@link #CONTROL_EXTENDED_SCENE_MODE_DISABLED DISABLED}</li>
      *   <li>{@link #CONTROL_EXTENDED_SCENE_MODE_BOKEH_STILL_CAPTURE BOKEH_STILL_CAPTURE}</li>
      *   <li>{@link #CONTROL_EXTENDED_SCENE_MODE_BOKEH_CONTINUOUS BOKEH_CONTINUOUS}</li>
-     * </ul></p>
+     * </ul>
+     *
      * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p>
      *
      * @see CaptureRequest#CONTROL_ZOOM_RATIO
@@ -2287,13 +2301,14 @@
      * device will apply FAST/HIGH_QUALITY YUV-domain edge enhancement, respectively.
      * The camera device may adjust its internal edge enhancement parameters for best
      * image quality based on the {@link CaptureRequest#REPROCESS_EFFECTIVE_EXPOSURE_FACTOR android.reprocess.effectiveExposureFactor}, if it is set.</p>
-     * <p><b>Possible values:</b>
+     * <p><b>Possible values:</b></p>
      * <ul>
      *   <li>{@link #EDGE_MODE_OFF OFF}</li>
      *   <li>{@link #EDGE_MODE_FAST FAST}</li>
      *   <li>{@link #EDGE_MODE_HIGH_QUALITY HIGH_QUALITY}</li>
      *   <li>{@link #EDGE_MODE_ZERO_SHUTTER_LAG ZERO_SHUTTER_LAG}</li>
-     * </ul></p>
+     * </ul>
+     *
      * <p><b>Available values for this device:</b><br>
      * {@link CameraCharacteristics#EDGE_AVAILABLE_EDGE_MODES android.edge.availableEdgeModes}</p>
      * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p>
@@ -2329,12 +2344,13 @@
      * <p>When set to TORCH, the flash will be on continuously. This mode can be used
      * for use cases such as preview, auto-focus assist, still capture, or video recording.</p>
      * <p>The flash status will be reported by {@link CaptureResult#FLASH_STATE android.flash.state} in the capture result metadata.</p>
-     * <p><b>Possible values:</b>
+     * <p><b>Possible values:</b></p>
      * <ul>
      *   <li>{@link #FLASH_MODE_OFF OFF}</li>
      *   <li>{@link #FLASH_MODE_SINGLE SINGLE}</li>
      *   <li>{@link #FLASH_MODE_TORCH TORCH}</li>
-     * </ul></p>
+     * </ul>
+     *
      * <p>This key is available on all devices.</p>
      *
      * @see CaptureRequest#CONTROL_AE_MODE
@@ -2355,12 +2371,13 @@
      * <p>Hotpixel correction interpolates out, or otherwise removes, pixels
      * that do not accurately measure the incoming light (i.e. pixels that
      * are stuck at an arbitrary value or are oversensitive).</p>
-     * <p><b>Possible values:</b>
+     * <p><b>Possible values:</b></p>
      * <ul>
      *   <li>{@link #HOT_PIXEL_MODE_OFF OFF}</li>
      *   <li>{@link #HOT_PIXEL_MODE_FAST FAST}</li>
      *   <li>{@link #HOT_PIXEL_MODE_HIGH_QUALITY HIGH_QUALITY}</li>
-     * </ul></p>
+     * </ul>
+     *
      * <p><b>Available values for this device:</b><br>
      * {@link CameraCharacteristics#HOT_PIXEL_AVAILABLE_HOT_PIXEL_MODES android.hotPixel.availableHotPixelModes}</p>
      * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p>
@@ -2688,11 +2705,12 @@
      * <p>Not all devices will support OIS; see
      * {@link CameraCharacteristics#LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION android.lens.info.availableOpticalStabilization} for
      * available controls.</p>
-     * <p><b>Possible values:</b>
+     * <p><b>Possible values:</b></p>
      * <ul>
      *   <li>{@link #LENS_OPTICAL_STABILIZATION_MODE_OFF OFF}</li>
      *   <li>{@link #LENS_OPTICAL_STABILIZATION_MODE_ON ON}</li>
-     * </ul></p>
+     * </ul>
+     *
      * <p><b>Available values for this device:</b><br>
      * {@link CameraCharacteristics#LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION android.lens.info.availableOpticalStabilization}</p>
      * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p>
@@ -2738,14 +2756,15 @@
      * will apply FAST/HIGH_QUALITY YUV domain noise reduction, respectively. The camera device
      * may adjust the noise reduction parameters for best image quality based on the
      * {@link CaptureRequest#REPROCESS_EFFECTIVE_EXPOSURE_FACTOR android.reprocess.effectiveExposureFactor} if it is set.</p>
-     * <p><b>Possible values:</b>
+     * <p><b>Possible values:</b></p>
      * <ul>
      *   <li>{@link #NOISE_REDUCTION_MODE_OFF OFF}</li>
      *   <li>{@link #NOISE_REDUCTION_MODE_FAST FAST}</li>
      *   <li>{@link #NOISE_REDUCTION_MODE_HIGH_QUALITY HIGH_QUALITY}</li>
      *   <li>{@link #NOISE_REDUCTION_MODE_MINIMAL MINIMAL}</li>
      *   <li>{@link #NOISE_REDUCTION_MODE_ZERO_SHUTTER_LAG ZERO_SHUTTER_LAG}</li>
-     * </ul></p>
+     * </ul>
+     *
      * <p><b>Available values for this device:</b><br>
      * {@link CameraCharacteristics#NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES android.noiseReduction.availableNoiseReductionModes}</p>
      * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p>
@@ -2959,14 +2978,15 @@
      * <li>640x480 stream: top-left: <code>(781, 375)</code> on active array, size: <code>(640, 480)</code>, downscaled 1.17x from sensor pixels</li>
      * <li>1280x720 stream: top-left: <code>(711, 375)</code> on active array, size: <code>(1280, 720)</code>, upscaled 1.71x from sensor pixels</li>
      * </ul>
-     * <p><b>Possible values:</b>
+     * <p><b>Possible values:</b></p>
      * <ul>
      *   <li>{@link #SCALER_ROTATE_AND_CROP_NONE NONE}</li>
      *   <li>{@link #SCALER_ROTATE_AND_CROP_90 90}</li>
      *   <li>{@link #SCALER_ROTATE_AND_CROP_180 180}</li>
      *   <li>{@link #SCALER_ROTATE_AND_CROP_270 270}</li>
      *   <li>{@link #SCALER_ROTATE_AND_CROP_AUTO AUTO}</li>
-     * </ul></p>
+     * </ul>
+     *
      * <p><b>Available values for this device:</b><br>
      * {@link CameraCharacteristics#SCALER_AVAILABLE_ROTATE_AND_CROP_MODES android.scaler.availableRotateAndCropModes}</p>
      * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p>
@@ -3166,7 +3186,7 @@
      * occur (and that the test pattern remain unmodified, since the flash
      * would not actually affect it).</p>
      * <p>Defaults to OFF.</p>
-     * <p><b>Possible values:</b>
+     * <p><b>Possible values:</b></p>
      * <ul>
      *   <li>{@link #SENSOR_TEST_PATTERN_MODE_OFF OFF}</li>
      *   <li>{@link #SENSOR_TEST_PATTERN_MODE_SOLID_COLOR SOLID_COLOR}</li>
@@ -3174,7 +3194,8 @@
      *   <li>{@link #SENSOR_TEST_PATTERN_MODE_COLOR_BARS_FADE_TO_GRAY COLOR_BARS_FADE_TO_GRAY}</li>
      *   <li>{@link #SENSOR_TEST_PATTERN_MODE_PN9 PN9}</li>
      *   <li>{@link #SENSOR_TEST_PATTERN_MODE_CUSTOM1 CUSTOM1}</li>
-     * </ul></p>
+     * </ul>
+     *
      * <p><b>Available values for this device:</b><br>
      * {@link CameraCharacteristics#SENSOR_AVAILABLE_TEST_PATTERN_MODES android.sensor.availableTestPatternModes}</p>
      * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p>
@@ -3218,12 +3239,13 @@
      * AWB are in AUTO modes({@link CaptureRequest#CONTROL_AE_MODE android.control.aeMode} <code>!=</code> OFF and {@link CaptureRequest#CONTROL_AWB_MODE android.control.awbMode} <code>!=</code>
      * OFF), to get best results, it is recommended that the applications wait for the AE and AWB
      * to be converged before using the returned shading map data.</p>
-     * <p><b>Possible values:</b>
+     * <p><b>Possible values:</b></p>
      * <ul>
      *   <li>{@link #SHADING_MODE_OFF OFF}</li>
      *   <li>{@link #SHADING_MODE_FAST FAST}</li>
      *   <li>{@link #SHADING_MODE_HIGH_QUALITY HIGH_QUALITY}</li>
-     * </ul></p>
+     * </ul>
+     *
      * <p><b>Available values for this device:</b><br>
      * {@link CameraCharacteristics#SHADING_AVAILABLE_MODES android.shading.availableModes}</p>
      * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p>
@@ -3252,12 +3274,13 @@
      * <p>Whether face detection is enabled, and whether it
      * should output just the basic fields or the full set of
      * fields.</p>
-     * <p><b>Possible values:</b>
+     * <p><b>Possible values:</b></p>
      * <ul>
      *   <li>{@link #STATISTICS_FACE_DETECT_MODE_OFF OFF}</li>
      *   <li>{@link #STATISTICS_FACE_DETECT_MODE_SIMPLE SIMPLE}</li>
      *   <li>{@link #STATISTICS_FACE_DETECT_MODE_FULL FULL}</li>
-     * </ul></p>
+     * </ul>
+     *
      * <p><b>Available values for this device:</b><br>
      * {@link CameraCharacteristics#STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES android.statistics.info.availableFaceDetectModes}</p>
      * <p>This key is available on all devices.</p>
@@ -3295,11 +3318,12 @@
      * android.statistics.lensShadingMap will be provided in
      * the output result metadata.</p>
      * <p>ON is always supported on devices with the RAW capability.</p>
-     * <p><b>Possible values:</b>
+     * <p><b>Possible values:</b></p>
      * <ul>
      *   <li>{@link #STATISTICS_LENS_SHADING_MAP_MODE_OFF OFF}</li>
      *   <li>{@link #STATISTICS_LENS_SHADING_MAP_MODE_ON ON}</li>
-     * </ul></p>
+     * </ul>
+     *
      * <p><b>Available values for this device:</b><br>
      * {@link CameraCharacteristics#STATISTICS_INFO_AVAILABLE_LENS_SHADING_MAP_MODES android.statistics.info.availableLensShadingMapModes}</p>
      * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p>
@@ -3326,11 +3350,12 @@
      * at 30fps may have 6-7 OIS samples per capture result. This information can be combined
      * with the rolling shutter skew to account for lens motion during image exposure in
      * post-processing algorithms.</p>
-     * <p><b>Possible values:</b>
+     * <p><b>Possible values:</b></p>
      * <ul>
      *   <li>{@link #STATISTICS_OIS_DATA_MODE_OFF OFF}</li>
      *   <li>{@link #STATISTICS_OIS_DATA_MODE_ON ON}</li>
-     * </ul></p>
+     * </ul>
+     *
      * <p><b>Available values for this device:</b><br>
      * {@link CameraCharacteristics#STATISTICS_INFO_AVAILABLE_OIS_DATA_MODES android.statistics.info.availableOisDataModes}</p>
      * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p>
@@ -3523,14 +3548,15 @@
      * <p>If a request is sent with CONTRAST_CURVE with the camera device's
      * provided curve in FAST or HIGH_QUALITY, the image's tonemap will be
      * roughly the same.</p>
-     * <p><b>Possible values:</b>
+     * <p><b>Possible values:</b></p>
      * <ul>
      *   <li>{@link #TONEMAP_MODE_CONTRAST_CURVE CONTRAST_CURVE}</li>
      *   <li>{@link #TONEMAP_MODE_FAST FAST}</li>
      *   <li>{@link #TONEMAP_MODE_HIGH_QUALITY HIGH_QUALITY}</li>
      *   <li>{@link #TONEMAP_MODE_GAMMA_VALUE GAMMA_VALUE}</li>
      *   <li>{@link #TONEMAP_MODE_PRESET_CURVE PRESET_CURVE}</li>
-     * </ul></p>
+     * </ul>
+     *
      * <p><b>Available values for this device:</b><br>
      * {@link CameraCharacteristics#TONEMAP_AVAILABLE_TONE_MAP_MODES android.tonemap.availableToneMapModes}</p>
      * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p>
@@ -3585,11 +3611,12 @@
      * <p><img alt="Rec. 709 tonemapping curve" src="/reference/images/camera2/metadata/android.tonemap.curveRed/rec709_tonemap.png" /></p>
      * <p>Note that above figures show a 16 control points approximation of preset
      * curves. Camera devices may apply a different approximation to the curve.</p>
-     * <p><b>Possible values:</b>
+     * <p><b>Possible values:</b></p>
      * <ul>
      *   <li>{@link #TONEMAP_PRESET_CURVE_SRGB SRGB}</li>
      *   <li>{@link #TONEMAP_PRESET_CURVE_REC709 REC709}</li>
-     * </ul></p>
+     * </ul>
+     *
      * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p>
      *
      * @see CaptureRequest#TONEMAP_MODE
@@ -3754,12 +3781,13 @@
      * <li>{@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion}</li>
      * <li>{@link CaptureResult#STATISTICS_FACES android.statistics.faces}</li>
      * </ul>
-     * <p><b>Possible values:</b>
+     * <p><b>Possible values:</b></p>
      * <ul>
      *   <li>{@link #DISTORTION_CORRECTION_MODE_OFF OFF}</li>
      *   <li>{@link #DISTORTION_CORRECTION_MODE_FAST FAST}</li>
      *   <li>{@link #DISTORTION_CORRECTION_MODE_HIGH_QUALITY HIGH_QUALITY}</li>
-     * </ul></p>
+     * </ul>
+     *
      * <p><b>Available values for this device:</b><br>
      * {@link CameraCharacteristics#DISTORTION_CORRECTION_AVAILABLE_MODES android.distortionCorrection.availableModes}</p>
      * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p>
diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java
index 4424a71..66d8b50 100644
--- a/core/java/android/hardware/camera2/CaptureResult.java
+++ b/core/java/android/hardware/camera2/CaptureResult.java
@@ -449,12 +449,13 @@
      * </code></pre>
      * <p>Both the input and output value ranges must match. Overflow/underflow
      * values are clipped to fit within the range.</p>
-     * <p><b>Possible values:</b>
+     * <p><b>Possible values:</b></p>
      * <ul>
      *   <li>{@link #COLOR_CORRECTION_MODE_TRANSFORM_MATRIX TRANSFORM_MATRIX}</li>
      *   <li>{@link #COLOR_CORRECTION_MODE_FAST FAST}</li>
      *   <li>{@link #COLOR_CORRECTION_MODE_HIGH_QUALITY HIGH_QUALITY}</li>
-     * </ul></p>
+     * </ul>
+     *
      * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p>
      * <p><b>Full capability</b> -
      * Present on all camera devices that report being {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL_FULL HARDWARE_LEVEL_FULL} devices in the
@@ -542,12 +543,13 @@
      * capture rate. FAST means the camera device will not slow down capture rate when
      * applying aberration correction.</p>
      * <p>LEGACY devices will always be in FAST mode.</p>
-     * <p><b>Possible values:</b>
+     * <p><b>Possible values:</b></p>
      * <ul>
      *   <li>{@link #COLOR_CORRECTION_ABERRATION_MODE_OFF OFF}</li>
      *   <li>{@link #COLOR_CORRECTION_ABERRATION_MODE_FAST FAST}</li>
      *   <li>{@link #COLOR_CORRECTION_ABERRATION_MODE_HIGH_QUALITY HIGH_QUALITY}</li>
-     * </ul></p>
+     * </ul>
+     *
      * <p><b>Available values for this device:</b><br>
      * {@link CameraCharacteristics#COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES android.colorCorrection.availableAberrationModes}</p>
      * <p>This key is available on all devices.</p>
@@ -594,13 +596,14 @@
      * ensure it selects exposure times that do not cause banding
      * issues. The {@link CaptureResult#STATISTICS_SCENE_FLICKER android.statistics.sceneFlicker} key can assist
      * the application in this.</p>
-     * <p><b>Possible values:</b>
+     * <p><b>Possible values:</b></p>
      * <ul>
      *   <li>{@link #CONTROL_AE_ANTIBANDING_MODE_OFF OFF}</li>
      *   <li>{@link #CONTROL_AE_ANTIBANDING_MODE_50HZ 50HZ}</li>
      *   <li>{@link #CONTROL_AE_ANTIBANDING_MODE_60HZ 60HZ}</li>
      *   <li>{@link #CONTROL_AE_ANTIBANDING_MODE_AUTO AUTO}</li>
-     * </ul></p>
+     * </ul>
+     *
      * <p><b>Available values for this device:</b><br></p>
      * <p>{@link CameraCharacteristics#CONTROL_AE_AVAILABLE_ANTIBANDING_MODES android.control.aeAvailableAntibandingModes}</p>
      * <p>This key is available on all devices.</p>
@@ -725,7 +728,7 @@
      * camera device auto-exposure routine for the overridden
      * fields for a given capture will be available in its
      * CaptureResult.</p>
-     * <p><b>Possible values:</b>
+     * <p><b>Possible values:</b></p>
      * <ul>
      *   <li>{@link #CONTROL_AE_MODE_OFF OFF}</li>
      *   <li>{@link #CONTROL_AE_MODE_ON ON}</li>
@@ -733,7 +736,8 @@
      *   <li>{@link #CONTROL_AE_MODE_ON_ALWAYS_FLASH ON_ALWAYS_FLASH}</li>
      *   <li>{@link #CONTROL_AE_MODE_ON_AUTO_FLASH_REDEYE ON_AUTO_FLASH_REDEYE}</li>
      *   <li>{@link #CONTROL_AE_MODE_ON_EXTERNAL_FLASH ON_EXTERNAL_FLASH}</li>
-     * </ul></p>
+     * </ul>
+     *
      * <p><b>Available values for this device:</b><br>
      * {@link CameraCharacteristics#CONTROL_AE_AVAILABLE_MODES android.control.aeAvailableModes}</p>
      * <p>This key is available on all devices.</p>
@@ -899,12 +903,13 @@
      * example.</p>
      * <p>If both the precapture and the auto-focus trigger are activated on the same request, then
      * the camera device will complete them in the optimal order for that device.</p>
-     * <p><b>Possible values:</b>
+     * <p><b>Possible values:</b></p>
      * <ul>
      *   <li>{@link #CONTROL_AE_PRECAPTURE_TRIGGER_IDLE IDLE}</li>
      *   <li>{@link #CONTROL_AE_PRECAPTURE_TRIGGER_START START}</li>
      *   <li>{@link #CONTROL_AE_PRECAPTURE_TRIGGER_CANCEL CANCEL}</li>
-     * </ul></p>
+     * </ul>
+     *
      * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p>
      * <p><b>Limited capability</b> -
      * Present on all camera devices that report being at least {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED HARDWARE_LEVEL_LIMITED} devices in the
@@ -1139,7 +1144,7 @@
      * </tr>
      * </tbody>
      * </table>
-     * <p><b>Possible values:</b>
+     * <p><b>Possible values:</b></p>
      * <ul>
      *   <li>{@link #CONTROL_AE_STATE_INACTIVE INACTIVE}</li>
      *   <li>{@link #CONTROL_AE_STATE_SEARCHING SEARCHING}</li>
@@ -1147,7 +1152,8 @@
      *   <li>{@link #CONTROL_AE_STATE_LOCKED LOCKED}</li>
      *   <li>{@link #CONTROL_AE_STATE_FLASH_REQUIRED FLASH_REQUIRED}</li>
      *   <li>{@link #CONTROL_AE_STATE_PRECAPTURE PRECAPTURE}</li>
-     * </ul></p>
+     * </ul>
+     *
      * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p>
      * <p><b>Limited capability</b> -
      * Present on all camera devices that report being at least {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED HARDWARE_LEVEL_LIMITED} devices in the
@@ -1184,7 +1190,7 @@
      * <p>If the lens is controlled by the camera device auto-focus algorithm,
      * the camera device will report the current AF status in {@link CaptureResult#CONTROL_AF_STATE android.control.afState}
      * in result metadata.</p>
-     * <p><b>Possible values:</b>
+     * <p><b>Possible values:</b></p>
      * <ul>
      *   <li>{@link #CONTROL_AF_MODE_OFF OFF}</li>
      *   <li>{@link #CONTROL_AF_MODE_AUTO AUTO}</li>
@@ -1192,7 +1198,8 @@
      *   <li>{@link #CONTROL_AF_MODE_CONTINUOUS_VIDEO CONTINUOUS_VIDEO}</li>
      *   <li>{@link #CONTROL_AF_MODE_CONTINUOUS_PICTURE CONTINUOUS_PICTURE}</li>
      *   <li>{@link #CONTROL_AF_MODE_EDOF EDOF}</li>
-     * </ul></p>
+     * </ul>
+     *
      * <p><b>Available values for this device:</b><br>
      * {@link CameraCharacteristics#CONTROL_AF_AVAILABLE_MODES android.control.afAvailableModes}</p>
      * <p>This key is available on all devices.</p>
@@ -1307,12 +1314,13 @@
      * focus sweep), the camera device may delay acting on a later trigger until the previous
      * trigger has been fully handled. This may lead to longer intervals between the trigger and
      * changes to {@link CaptureResult#CONTROL_AF_STATE android.control.afState}, for example.</p>
-     * <p><b>Possible values:</b>
+     * <p><b>Possible values:</b></p>
      * <ul>
      *   <li>{@link #CONTROL_AF_TRIGGER_IDLE IDLE}</li>
      *   <li>{@link #CONTROL_AF_TRIGGER_START START}</li>
      *   <li>{@link #CONTROL_AF_TRIGGER_CANCEL CANCEL}</li>
-     * </ul></p>
+     * </ul>
+     *
      * <p>This key is available on all devices.</p>
      *
      * @see CaptureRequest#CONTROL_AE_PRECAPTURE_TRIGGER
@@ -1708,7 +1716,7 @@
      * </tr>
      * </tbody>
      * </table>
-     * <p><b>Possible values:</b>
+     * <p><b>Possible values:</b></p>
      * <ul>
      *   <li>{@link #CONTROL_AF_STATE_INACTIVE INACTIVE}</li>
      *   <li>{@link #CONTROL_AF_STATE_PASSIVE_SCAN PASSIVE_SCAN}</li>
@@ -1717,7 +1725,8 @@
      *   <li>{@link #CONTROL_AF_STATE_FOCUSED_LOCKED FOCUSED_LOCKED}</li>
      *   <li>{@link #CONTROL_AF_STATE_NOT_FOCUSED_LOCKED NOT_FOCUSED_LOCKED}</li>
      *   <li>{@link #CONTROL_AF_STATE_PASSIVE_UNFOCUSED PASSIVE_UNFOCUSED}</li>
-     * </ul></p>
+     * </ul>
+     *
      * <p>This key is available on all devices.</p>
      *
      * @see CaptureRequest#CONTROL_AF_MODE
@@ -1790,7 +1799,7 @@
      * {@link CaptureRequest#COLOR_CORRECTION_TRANSFORM android.colorCorrection.transform},
      * {@link CaptureRequest#COLOR_CORRECTION_GAINS android.colorCorrection.gains} and
      * {@link CaptureRequest#COLOR_CORRECTION_MODE android.colorCorrection.mode} are ignored.</p>
-     * <p><b>Possible values:</b>
+     * <p><b>Possible values:</b></p>
      * <ul>
      *   <li>{@link #CONTROL_AWB_MODE_OFF OFF}</li>
      *   <li>{@link #CONTROL_AWB_MODE_AUTO AUTO}</li>
@@ -1801,7 +1810,8 @@
      *   <li>{@link #CONTROL_AWB_MODE_CLOUDY_DAYLIGHT CLOUDY_DAYLIGHT}</li>
      *   <li>{@link #CONTROL_AWB_MODE_TWILIGHT TWILIGHT}</li>
      *   <li>{@link #CONTROL_AWB_MODE_SHADE SHADE}</li>
-     * </ul></p>
+     * </ul>
+     *
      * <p><b>Available values for this device:</b><br>
      * {@link CameraCharacteristics#CONTROL_AWB_AVAILABLE_MODES android.control.awbAvailableModes}</p>
      * <p>This key is available on all devices.</p>
@@ -1915,7 +1925,7 @@
      * MANUAL_SENSOR.
      *   * MOTION_TRACKING will be supported if {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities} contains
      * MOTION_TRACKING.</p>
-     * <p><b>Possible values:</b>
+     * <p><b>Possible values:</b></p>
      * <ul>
      *   <li>{@link #CONTROL_CAPTURE_INTENT_CUSTOM CUSTOM}</li>
      *   <li>{@link #CONTROL_CAPTURE_INTENT_PREVIEW PREVIEW}</li>
@@ -1925,7 +1935,8 @@
      *   <li>{@link #CONTROL_CAPTURE_INTENT_ZERO_SHUTTER_LAG ZERO_SHUTTER_LAG}</li>
      *   <li>{@link #CONTROL_CAPTURE_INTENT_MANUAL MANUAL}</li>
      *   <li>{@link #CONTROL_CAPTURE_INTENT_MOTION_TRACKING MOTION_TRACKING}</li>
-     * </ul></p>
+     * </ul>
+     *
      * <p>This key is available on all devices.</p>
      *
      * @see CaptureRequest#CONTROL_MODE
@@ -2061,13 +2072,14 @@
      * </tr>
      * </tbody>
      * </table>
-     * <p><b>Possible values:</b>
+     * <p><b>Possible values:</b></p>
      * <ul>
      *   <li>{@link #CONTROL_AWB_STATE_INACTIVE INACTIVE}</li>
      *   <li>{@link #CONTROL_AWB_STATE_SEARCHING SEARCHING}</li>
      *   <li>{@link #CONTROL_AWB_STATE_CONVERGED CONVERGED}</li>
      *   <li>{@link #CONTROL_AWB_STATE_LOCKED LOCKED}</li>
-     * </ul></p>
+     * </ul>
+     *
      * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p>
      * <p><b>Limited capability</b> -
      * Present on all camera devices that report being at least {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED HARDWARE_LEVEL_LIMITED} devices in the
@@ -2096,7 +2108,7 @@
      * implementor of the camera device, and should not be
      * depended on to be consistent (or present) across all
      * devices.</p>
-     * <p><b>Possible values:</b>
+     * <p><b>Possible values:</b></p>
      * <ul>
      *   <li>{@link #CONTROL_EFFECT_MODE_OFF OFF}</li>
      *   <li>{@link #CONTROL_EFFECT_MODE_MONO MONO}</li>
@@ -2107,7 +2119,8 @@
      *   <li>{@link #CONTROL_EFFECT_MODE_WHITEBOARD WHITEBOARD}</li>
      *   <li>{@link #CONTROL_EFFECT_MODE_BLACKBOARD BLACKBOARD}</li>
      *   <li>{@link #CONTROL_EFFECT_MODE_AQUA AQUA}</li>
-     * </ul></p>
+     * </ul>
+     *
      * <p><b>Available values for this device:</b><br>
      * {@link CameraCharacteristics#CONTROL_AVAILABLE_EFFECTS android.control.availableEffects}</p>
      * <p>This key is available on all devices.</p>
@@ -2146,14 +2159,15 @@
      * update, as if this frame is never captured. This mode can be used in the scenario
      * where the application doesn't want a 3A manual control capture to affect
      * the subsequent auto 3A capture results.</p>
-     * <p><b>Possible values:</b>
+     * <p><b>Possible values:</b></p>
      * <ul>
      *   <li>{@link #CONTROL_MODE_OFF OFF}</li>
      *   <li>{@link #CONTROL_MODE_AUTO AUTO}</li>
      *   <li>{@link #CONTROL_MODE_USE_SCENE_MODE USE_SCENE_MODE}</li>
      *   <li>{@link #CONTROL_MODE_OFF_KEEP_STATE OFF_KEEP_STATE}</li>
      *   <li>{@link #CONTROL_MODE_USE_EXTENDED_SCENE_MODE USE_EXTENDED_SCENE_MODE}</li>
-     * </ul></p>
+     * </ul>
+     *
      * <p><b>Available values for this device:</b><br>
      * {@link CameraCharacteristics#CONTROL_AVAILABLE_MODES android.control.availableModes}</p>
      * <p>This key is available on all devices.</p>
@@ -2183,7 +2197,7 @@
      * to the implementor of the camera device. Their behavior will not be
      * consistent across all devices, and any given device may only implement
      * a subset of these modes.</p>
-     * <p><b>Possible values:</b>
+     * <p><b>Possible values:</b></p>
      * <ul>
      *   <li>{@link #CONTROL_SCENE_MODE_DISABLED DISABLED}</li>
      *   <li>{@link #CONTROL_SCENE_MODE_FACE_PRIORITY FACE_PRIORITY}</li>
@@ -2204,7 +2218,8 @@
      *   <li>{@link #CONTROL_SCENE_MODE_BARCODE BARCODE}</li>
      *   <li>{@link #CONTROL_SCENE_MODE_HIGH_SPEED_VIDEO HIGH_SPEED_VIDEO}</li>
      *   <li>{@link #CONTROL_SCENE_MODE_HDR HDR}</li>
-     * </ul></p>
+     * </ul>
+     *
      * <p><b>Available values for this device:</b><br>
      * {@link CameraCharacteristics#CONTROL_AVAILABLE_SCENE_MODES android.control.availableSceneModes}</p>
      * <p>This key is available on all devices.</p>
@@ -2265,11 +2280,12 @@
      * ({@link CaptureRequest#LENS_OPTICAL_STABILIZATION_MODE android.lens.opticalStabilizationMode}), turning both modes on may
      * produce undesirable interaction, so it is recommended not to enable
      * both at the same time.</p>
-     * <p><b>Possible values:</b>
+     * <p><b>Possible values:</b></p>
      * <ul>
      *   <li>{@link #CONTROL_VIDEO_STABILIZATION_MODE_OFF OFF}</li>
      *   <li>{@link #CONTROL_VIDEO_STABILIZATION_MODE_ON ON}</li>
-     * </ul></p>
+     * </ul>
+     *
      * <p>This key is available on all devices.</p>
      *
      * @see CaptureRequest#CONTROL_VIDEO_STABILIZATION_MODE
@@ -2362,11 +2378,12 @@
      * result. Otherwise the value will be NOT_DETECTED. The threshold for detection is similar
      * to what would trigger a new passive focus scan to begin in CONTINUOUS autofocus modes.</p>
      * <p>This key will be available if the camera device advertises this key via {@link android.hardware.camera2.CameraCharacteristics#getAvailableCaptureResultKeys }.</p>
-     * <p><b>Possible values:</b>
+     * <p><b>Possible values:</b></p>
      * <ul>
      *   <li>{@link #CONTROL_AF_SCENE_CHANGE_NOT_DETECTED NOT_DETECTED}</li>
      *   <li>{@link #CONTROL_AF_SCENE_CHANGE_DETECTED DETECTED}</li>
-     * </ul></p>
+     * </ul>
+     *
      * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p>
      * @see #CONTROL_AF_SCENE_CHANGE_NOT_DETECTED
      * @see #CONTROL_AF_SCENE_CHANGE_DETECTED
@@ -2402,12 +2419,13 @@
      * with different field of view. As a result, when bokeh mode is enabled, the camera device
      * may override {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion} or {@link CaptureRequest#CONTROL_ZOOM_RATIO android.control.zoomRatio}, and the field of
      * view may be smaller than when bokeh mode is off.</p>
-     * <p><b>Possible values:</b>
+     * <p><b>Possible values:</b></p>
      * <ul>
      *   <li>{@link #CONTROL_EXTENDED_SCENE_MODE_DISABLED DISABLED}</li>
      *   <li>{@link #CONTROL_EXTENDED_SCENE_MODE_BOKEH_STILL_CAPTURE BOKEH_STILL_CAPTURE}</li>
      *   <li>{@link #CONTROL_EXTENDED_SCENE_MODE_BOKEH_CONTINUOUS BOKEH_CONTINUOUS}</li>
-     * </ul></p>
+     * </ul>
+     *
      * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p>
      *
      * @see CaptureRequest#CONTROL_ZOOM_RATIO
@@ -2534,13 +2552,14 @@
      * device will apply FAST/HIGH_QUALITY YUV-domain edge enhancement, respectively.
      * The camera device may adjust its internal edge enhancement parameters for best
      * image quality based on the {@link CaptureRequest#REPROCESS_EFFECTIVE_EXPOSURE_FACTOR android.reprocess.effectiveExposureFactor}, if it is set.</p>
-     * <p><b>Possible values:</b>
+     * <p><b>Possible values:</b></p>
      * <ul>
      *   <li>{@link #EDGE_MODE_OFF OFF}</li>
      *   <li>{@link #EDGE_MODE_FAST FAST}</li>
      *   <li>{@link #EDGE_MODE_HIGH_QUALITY HIGH_QUALITY}</li>
      *   <li>{@link #EDGE_MODE_ZERO_SHUTTER_LAG ZERO_SHUTTER_LAG}</li>
-     * </ul></p>
+     * </ul>
+     *
      * <p><b>Available values for this device:</b><br>
      * {@link CameraCharacteristics#EDGE_AVAILABLE_EDGE_MODES android.edge.availableEdgeModes}</p>
      * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p>
@@ -2576,12 +2595,13 @@
      * <p>When set to TORCH, the flash will be on continuously. This mode can be used
      * for use cases such as preview, auto-focus assist, still capture, or video recording.</p>
      * <p>The flash status will be reported by {@link CaptureResult#FLASH_STATE android.flash.state} in the capture result metadata.</p>
-     * <p><b>Possible values:</b>
+     * <p><b>Possible values:</b></p>
      * <ul>
      *   <li>{@link #FLASH_MODE_OFF OFF}</li>
      *   <li>{@link #FLASH_MODE_SINGLE SINGLE}</li>
      *   <li>{@link #FLASH_MODE_TORCH TORCH}</li>
-     * </ul></p>
+     * </ul>
+     *
      * <p>This key is available on all devices.</p>
      *
      * @see CaptureRequest#CONTROL_AE_MODE
@@ -2613,14 +2633,15 @@
      * </ul>
      * <p>In all other conditions the state will not be available on
      * LEGACY devices (i.e. it will be <code>null</code>).</p>
-     * <p><b>Possible values:</b>
+     * <p><b>Possible values:</b></p>
      * <ul>
      *   <li>{@link #FLASH_STATE_UNAVAILABLE UNAVAILABLE}</li>
      *   <li>{@link #FLASH_STATE_CHARGING CHARGING}</li>
      *   <li>{@link #FLASH_STATE_READY READY}</li>
      *   <li>{@link #FLASH_STATE_FIRED FIRED}</li>
      *   <li>{@link #FLASH_STATE_PARTIAL PARTIAL}</li>
-     * </ul></p>
+     * </ul>
+     *
      * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p>
      * <p><b>Limited capability</b> -
      * Present on all camera devices that report being at least {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED HARDWARE_LEVEL_LIMITED} devices in the
@@ -2646,12 +2667,13 @@
      * <p>Hotpixel correction interpolates out, or otherwise removes, pixels
      * that do not accurately measure the incoming light (i.e. pixels that
      * are stuck at an arbitrary value or are oversensitive).</p>
-     * <p><b>Possible values:</b>
+     * <p><b>Possible values:</b></p>
      * <ul>
      *   <li>{@link #HOT_PIXEL_MODE_OFF OFF}</li>
      *   <li>{@link #HOT_PIXEL_MODE_FAST FAST}</li>
      *   <li>{@link #HOT_PIXEL_MODE_HIGH_QUALITY HIGH_QUALITY}</li>
-     * </ul></p>
+     * </ul>
+     *
      * <p><b>Available values for this device:</b><br>
      * {@link CameraCharacteristics#HOT_PIXEL_AVAILABLE_HOT_PIXEL_MODES android.hotPixel.availableHotPixelModes}</p>
      * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p>
@@ -2988,11 +3010,12 @@
      * <p>Not all devices will support OIS; see
      * {@link CameraCharacteristics#LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION android.lens.info.availableOpticalStabilization} for
      * available controls.</p>
-     * <p><b>Possible values:</b>
+     * <p><b>Possible values:</b></p>
      * <ul>
      *   <li>{@link #LENS_OPTICAL_STABILIZATION_MODE_OFF OFF}</li>
      *   <li>{@link #LENS_OPTICAL_STABILIZATION_MODE_ON ON}</li>
-     * </ul></p>
+     * </ul>
+     *
      * <p><b>Available values for this device:</b><br>
      * {@link CameraCharacteristics#LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION android.lens.info.availableOpticalStabilization}</p>
      * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p>
@@ -3032,11 +3055,12 @@
      * <p>Then this state will always be STATIONARY.</p>
      * <p>When the state is MOVING, it indicates that at least one of the lens parameters
      * is changing.</p>
-     * <p><b>Possible values:</b>
+     * <p><b>Possible values:</b></p>
      * <ul>
      *   <li>{@link #LENS_STATE_STATIONARY STATIONARY}</li>
      *   <li>{@link #LENS_STATE_MOVING MOVING}</li>
-     * </ul></p>
+     * </ul>
+     *
      * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p>
      * <p><b>Limited capability</b> -
      * Present on all camera devices that report being at least {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED HARDWARE_LEVEL_LIMITED} devices in the
@@ -3338,14 +3362,15 @@
      * will apply FAST/HIGH_QUALITY YUV domain noise reduction, respectively. The camera device
      * may adjust the noise reduction parameters for best image quality based on the
      * {@link CaptureRequest#REPROCESS_EFFECTIVE_EXPOSURE_FACTOR android.reprocess.effectiveExposureFactor} if it is set.</p>
-     * <p><b>Possible values:</b>
+     * <p><b>Possible values:</b></p>
      * <ul>
      *   <li>{@link #NOISE_REDUCTION_MODE_OFF OFF}</li>
      *   <li>{@link #NOISE_REDUCTION_MODE_FAST FAST}</li>
      *   <li>{@link #NOISE_REDUCTION_MODE_HIGH_QUALITY HIGH_QUALITY}</li>
      *   <li>{@link #NOISE_REDUCTION_MODE_MINIMAL MINIMAL}</li>
      *   <li>{@link #NOISE_REDUCTION_MODE_ZERO_SHUTTER_LAG ZERO_SHUTTER_LAG}</li>
-     * </ul></p>
+     * </ul>
+     *
      * <p><b>Available values for this device:</b><br>
      * {@link CameraCharacteristics#NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES android.noiseReduction.availableNoiseReductionModes}</p>
      * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p>
@@ -3622,14 +3647,15 @@
      * <li>640x480 stream: top-left: <code>(781, 375)</code> on active array, size: <code>(640, 480)</code>, downscaled 1.17x from sensor pixels</li>
      * <li>1280x720 stream: top-left: <code>(711, 375)</code> on active array, size: <code>(1280, 720)</code>, upscaled 1.71x from sensor pixels</li>
      * </ul>
-     * <p><b>Possible values:</b>
+     * <p><b>Possible values:</b></p>
      * <ul>
      *   <li>{@link #SCALER_ROTATE_AND_CROP_NONE NONE}</li>
      *   <li>{@link #SCALER_ROTATE_AND_CROP_90 90}</li>
      *   <li>{@link #SCALER_ROTATE_AND_CROP_180 180}</li>
      *   <li>{@link #SCALER_ROTATE_AND_CROP_270 270}</li>
      *   <li>{@link #SCALER_ROTATE_AND_CROP_AUTO AUTO}</li>
-     * </ul></p>
+     * </ul>
+     *
      * <p><b>Available values for this device:</b><br>
      * {@link CameraCharacteristics#SCALER_AVAILABLE_ROTATE_AND_CROP_MODES android.scaler.availableRotateAndCropModes}</p>
      * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p>
@@ -3951,7 +3977,7 @@
      * occur (and that the test pattern remain unmodified, since the flash
      * would not actually affect it).</p>
      * <p>Defaults to OFF.</p>
-     * <p><b>Possible values:</b>
+     * <p><b>Possible values:</b></p>
      * <ul>
      *   <li>{@link #SENSOR_TEST_PATTERN_MODE_OFF OFF}</li>
      *   <li>{@link #SENSOR_TEST_PATTERN_MODE_SOLID_COLOR SOLID_COLOR}</li>
@@ -3959,7 +3985,8 @@
      *   <li>{@link #SENSOR_TEST_PATTERN_MODE_COLOR_BARS_FADE_TO_GRAY COLOR_BARS_FADE_TO_GRAY}</li>
      *   <li>{@link #SENSOR_TEST_PATTERN_MODE_PN9 PN9}</li>
      *   <li>{@link #SENSOR_TEST_PATTERN_MODE_CUSTOM1 CUSTOM1}</li>
-     * </ul></p>
+     * </ul>
+     *
      * <p><b>Available values for this device:</b><br>
      * {@link CameraCharacteristics#SENSOR_AVAILABLE_TEST_PATTERN_MODES android.sensor.availableTestPatternModes}</p>
      * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p>
@@ -4105,12 +4132,13 @@
      * AWB are in AUTO modes({@link CaptureRequest#CONTROL_AE_MODE android.control.aeMode} <code>!=</code> OFF and {@link CaptureRequest#CONTROL_AWB_MODE android.control.awbMode} <code>!=</code>
      * OFF), to get best results, it is recommended that the applications wait for the AE and AWB
      * to be converged before using the returned shading map data.</p>
-     * <p><b>Possible values:</b>
+     * <p><b>Possible values:</b></p>
      * <ul>
      *   <li>{@link #SHADING_MODE_OFF OFF}</li>
      *   <li>{@link #SHADING_MODE_FAST FAST}</li>
      *   <li>{@link #SHADING_MODE_HIGH_QUALITY HIGH_QUALITY}</li>
-     * </ul></p>
+     * </ul>
+     *
      * <p><b>Available values for this device:</b><br>
      * {@link CameraCharacteristics#SHADING_AVAILABLE_MODES android.shading.availableModes}</p>
      * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p>
@@ -4139,12 +4167,13 @@
      * <p>Whether face detection is enabled, and whether it
      * should output just the basic fields or the full set of
      * fields.</p>
-     * <p><b>Possible values:</b>
+     * <p><b>Possible values:</b></p>
      * <ul>
      *   <li>{@link #STATISTICS_FACE_DETECT_MODE_OFF OFF}</li>
      *   <li>{@link #STATISTICS_FACE_DETECT_MODE_SIMPLE SIMPLE}</li>
      *   <li>{@link #STATISTICS_FACE_DETECT_MODE_FULL FULL}</li>
-     * </ul></p>
+     * </ul>
+     *
      * <p><b>Available values for this device:</b><br>
      * {@link CameraCharacteristics#STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES android.statistics.info.availableFaceDetectModes}</p>
      * <p>This key is available on all devices.</p>
@@ -4509,12 +4538,13 @@
      * into this metadata field. See
      * {@link CaptureRequest#CONTROL_AE_ANTIBANDING_MODE android.control.aeAntibandingMode} for more details.</p>
      * <p>Reports NONE if there doesn't appear to be flickering illumination.</p>
-     * <p><b>Possible values:</b>
+     * <p><b>Possible values:</b></p>
      * <ul>
      *   <li>{@link #STATISTICS_SCENE_FLICKER_NONE NONE}</li>
      *   <li>{@link #STATISTICS_SCENE_FLICKER_50HZ 50HZ}</li>
      *   <li>{@link #STATISTICS_SCENE_FLICKER_60HZ 60HZ}</li>
-     * </ul></p>
+     * </ul>
+     *
      * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p>
      * <p><b>Full capability</b> -
      * Present on all camera devices that report being {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL_FULL HARDWARE_LEVEL_FULL} devices in the
@@ -4578,11 +4608,12 @@
      * android.statistics.lensShadingMap will be provided in
      * the output result metadata.</p>
      * <p>ON is always supported on devices with the RAW capability.</p>
-     * <p><b>Possible values:</b>
+     * <p><b>Possible values:</b></p>
      * <ul>
      *   <li>{@link #STATISTICS_LENS_SHADING_MAP_MODE_OFF OFF}</li>
      *   <li>{@link #STATISTICS_LENS_SHADING_MAP_MODE_ON ON}</li>
-     * </ul></p>
+     * </ul>
+     *
      * <p><b>Available values for this device:</b><br>
      * {@link CameraCharacteristics#STATISTICS_INFO_AVAILABLE_LENS_SHADING_MAP_MODES android.statistics.info.availableLensShadingMapModes}</p>
      * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p>
@@ -4609,11 +4640,12 @@
      * at 30fps may have 6-7 OIS samples per capture result. This information can be combined
      * with the rolling shutter skew to account for lens motion during image exposure in
      * post-processing algorithms.</p>
-     * <p><b>Possible values:</b>
+     * <p><b>Possible values:</b></p>
      * <ul>
      *   <li>{@link #STATISTICS_OIS_DATA_MODE_OFF OFF}</li>
      *   <li>{@link #STATISTICS_OIS_DATA_MODE_ON ON}</li>
-     * </ul></p>
+     * </ul>
+     *
      * <p><b>Available values for this device:</b><br>
      * {@link CameraCharacteristics#STATISTICS_INFO_AVAILABLE_OIS_DATA_MODES android.statistics.info.availableOisDataModes}</p>
      * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p>
@@ -4881,14 +4913,15 @@
      * <p>If a request is sent with CONTRAST_CURVE with the camera device's
      * provided curve in FAST or HIGH_QUALITY, the image's tonemap will be
      * roughly the same.</p>
-     * <p><b>Possible values:</b>
+     * <p><b>Possible values:</b></p>
      * <ul>
      *   <li>{@link #TONEMAP_MODE_CONTRAST_CURVE CONTRAST_CURVE}</li>
      *   <li>{@link #TONEMAP_MODE_FAST FAST}</li>
      *   <li>{@link #TONEMAP_MODE_HIGH_QUALITY HIGH_QUALITY}</li>
      *   <li>{@link #TONEMAP_MODE_GAMMA_VALUE GAMMA_VALUE}</li>
      *   <li>{@link #TONEMAP_MODE_PRESET_CURVE PRESET_CURVE}</li>
-     * </ul></p>
+     * </ul>
+     *
      * <p><b>Available values for this device:</b><br>
      * {@link CameraCharacteristics#TONEMAP_AVAILABLE_TONE_MAP_MODES android.tonemap.availableToneMapModes}</p>
      * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p>
@@ -4943,11 +4976,12 @@
      * <p><img alt="Rec. 709 tonemapping curve" src="/reference/images/camera2/metadata/android.tonemap.curveRed/rec709_tonemap.png" /></p>
      * <p>Note that above figures show a 16 control points approximation of preset
      * curves. Camera devices may apply a different approximation to the curve.</p>
-     * <p><b>Possible values:</b>
+     * <p><b>Possible values:</b></p>
      * <ul>
      *   <li>{@link #TONEMAP_PRESET_CURVE_SRGB SRGB}</li>
      *   <li>{@link #TONEMAP_PRESET_CURVE_REC709 REC709}</li>
-     * </ul></p>
+     * </ul>
+     *
      * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p>
      *
      * @see CaptureRequest#TONEMAP_MODE
@@ -5048,11 +5082,12 @@
      * <p>In other words, results for this current request and up to
      * {@link CameraCharacteristics#REQUEST_PIPELINE_MAX_DEPTH android.request.pipelineMaxDepth} prior requests may have their
      * android.sync.frameNumber change to CONVERGING.</p>
-     * <p><b>Possible values:</b>
+     * <p><b>Possible values:</b></p>
      * <ul>
      *   <li>{@link #SYNC_FRAME_NUMBER_CONVERGING CONVERGING}</li>
      *   <li>{@link #SYNC_FRAME_NUMBER_UNKNOWN UNKNOWN}</li>
-     * </ul></p>
+     * </ul>
+     *
      * <p><b>Available values for this device:</b><br>
      * Either a non-negative value corresponding to a
      * <code>frame_number</code>, or one of the two enums (CONVERGING / UNKNOWN).</p>
@@ -5174,12 +5209,13 @@
      * <li>{@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion}</li>
      * <li>{@link CaptureResult#STATISTICS_FACES android.statistics.faces}</li>
      * </ul>
-     * <p><b>Possible values:</b>
+     * <p><b>Possible values:</b></p>
      * <ul>
      *   <li>{@link #DISTORTION_CORRECTION_MODE_OFF OFF}</li>
      *   <li>{@link #DISTORTION_CORRECTION_MODE_FAST FAST}</li>
      *   <li>{@link #DISTORTION_CORRECTION_MODE_HIGH_QUALITY HIGH_QUALITY}</li>
-     * </ul></p>
+     * </ul>
+     *
      * <p><b>Available values for this device:</b><br>
      * {@link CameraCharacteristics#DISTORTION_CORRECTION_AVAILABLE_MODES android.distortionCorrection.availableModes}</p>
      * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p>
diff --git a/core/java/android/hardware/display/OWNERS b/core/java/android/hardware/display/OWNERS
index 9ca3910..5bcd9bb8 100644
--- a/core/java/android/hardware/display/OWNERS
+++ b/core/java/android/hardware/display/OWNERS
@@ -1,2 +1,6 @@
+# Bug component: 345010
+
+include /services/core/java/com/android/server/display/OWNERS
+
 [email protected]
 [email protected]
diff --git a/core/java/android/hardware/face/OWNERS b/core/java/android/hardware/face/OWNERS
new file mode 100644
index 0000000..33527f8
--- /dev/null
+++ b/core/java/android/hardware/face/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 879035
+
[email protected]
diff --git a/core/java/android/hardware/fingerprint/OWNERS b/core/java/android/hardware/fingerprint/OWNERS
new file mode 100644
index 0000000..dcead40
--- /dev/null
+++ b/core/java/android/hardware/fingerprint/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 114777
+
[email protected]
diff --git a/core/java/android/hardware/hdmi/OWNERS b/core/java/android/hardware/hdmi/OWNERS
new file mode 100644
index 0000000..16c15e3
--- /dev/null
+++ b/core/java/android/hardware/hdmi/OWNERS
@@ -0,0 +1,6 @@
+# Bug component: 826094
+
+include /services/core/java/com/android/server/display/OWNERS
+
[email protected]
[email protected]
diff --git a/core/java/android/hardware/input/IInputManager.aidl b/core/java/android/hardware/input/IInputManager.aidl
index dc6f579..57c0398 100644
--- a/core/java/android/hardware/input/IInputManager.aidl
+++ b/core/java/android/hardware/input/IInputManager.aidl
@@ -22,6 +22,7 @@
 import android.hardware.input.IInputDevicesChangedListener;
 import android.hardware.input.ITabletModeChangedListener;
 import android.hardware.input.TouchCalibration;
+import android.os.CombinedVibrationEffect;
 import android.os.IBinder;
 import android.os.VibrationEffect;
 import android.view.InputDevice;
@@ -85,7 +86,10 @@
 
     // Input device vibrator control.
     void vibrate(int deviceId, in VibrationEffect effect, IBinder token);
+    void vibrateCombined(int deviceId, in CombinedVibrationEffect effect, IBinder token);
     void cancelVibrate(int deviceId, IBinder token);
+    int[] getVibratorIds(int deviceId);
+    boolean isVibrating(int deviceId);
 
     void setPointerIconType(int typeId);
     void setCustomPointerIcon(in PointerIcon icon);
diff --git a/core/java/android/hardware/input/InputDeviceVibrator.java b/core/java/android/hardware/input/InputDeviceVibrator.java
new file mode 100644
index 0000000..c60d6ce
--- /dev/null
+++ b/core/java/android/hardware/input/InputDeviceVibrator.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.input;
+
+import android.annotation.CallbackExecutor;
+import android.annotation.NonNull;
+import android.os.Binder;
+import android.os.VibrationAttributes;
+import android.os.VibrationEffect;
+import android.os.Vibrator;
+
+import java.util.concurrent.Executor;
+
+/**
+ * Vibrator implementation that communicates with the input device vibrators.
+ */
+final class InputDeviceVibrator extends Vibrator {
+    // mDeviceId represents InputDevice ID the vibrator belongs to
+    private final int mDeviceId;
+    private final int mVibratorId;
+    private final Binder mToken;
+    private final InputManager mInputManager;
+
+    InputDeviceVibrator(InputManager inputManager, int deviceId, int vibratorId) {
+        mInputManager = inputManager;
+        mDeviceId = deviceId;
+        mVibratorId = vibratorId;
+        mToken = new Binder();
+    }
+
+    @Override
+    public boolean hasVibrator() {
+        return true;
+    }
+
+    @Override
+    public boolean isVibrating() {
+        return mInputManager.isVibrating(mDeviceId);
+    }
+
+    /* TODO: b/161634264 Support Vibrator listener API in input devices */
+    @Override
+    public void addVibratorStateListener(@NonNull OnVibratorStateChangedListener listener) {
+        throw new UnsupportedOperationException(
+            "addVibratorStateListener not supported in InputDeviceVibrator");
+    }
+
+    @Override
+    public void addVibratorStateListener(
+            @NonNull @CallbackExecutor Executor executor,
+            @NonNull OnVibratorStateChangedListener listener) {
+        throw new UnsupportedOperationException(
+            "addVibratorStateListener not supported in InputDeviceVibrator");
+    }
+
+    @Override
+    public void removeVibratorStateListener(@NonNull OnVibratorStateChangedListener listener) {
+        throw new UnsupportedOperationException(
+            "removeVibratorStateListener not supported in InputDeviceVibrator");
+    }
+
+    @Override
+    public boolean hasAmplitudeControl() {
+        return true;
+    }
+
+    /**
+     * @hide
+     */
+    @Override
+    public void vibrate(int uid, String opPkg, @NonNull VibrationEffect effect,
+            String reason, @NonNull VibrationAttributes attributes) {
+        mInputManager.vibrate(mDeviceId, effect, mToken);
+    }
+
+    @Override
+    public void cancel() {
+        mInputManager.cancelVibrate(mDeviceId, mToken);
+    }
+}
diff --git a/core/java/android/hardware/input/InputDeviceVibratorManager.java b/core/java/android/hardware/input/InputDeviceVibratorManager.java
new file mode 100644
index 0000000..a381b02
--- /dev/null
+++ b/core/java/android/hardware/input/InputDeviceVibratorManager.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.input;
+
+import android.os.Binder;
+import android.os.CombinedVibrationEffect;
+import android.os.NullVibrator;
+import android.os.Vibrator;
+import android.os.VibratorManager;
+import android.util.SparseArray;
+import android.view.InputDevice;
+
+import com.android.internal.annotations.GuardedBy;
+
+/**
+ * Vibrator manager implementation that communicates with the input device vibrators.
+ *
+ * @hide
+ */
+public class InputDeviceVibratorManager extends VibratorManager
+        implements InputManager.InputDeviceListener {
+    private static final String TAG = "InputDeviceVibratorManager";
+    private static final boolean DEBUG = false;
+
+    private final Binder mToken;
+    private final InputManager mInputManager;
+
+    // The input device Id.
+    private final int mDeviceId;
+    // Vibrator map from Vibrator Id to Vibrator
+    @GuardedBy("mVibrators")
+    private final SparseArray<Vibrator> mVibrators = new SparseArray<>();
+
+    public InputDeviceVibratorManager(InputManager inputManager, int deviceId) {
+        mInputManager = inputManager;
+        mDeviceId = deviceId;
+        mToken = new Binder();
+
+        initializeVibrators();
+    }
+
+    private void initializeVibrators() {
+        synchronized (mVibrators) {
+            mVibrators.clear();
+            InputDevice inputDevice = InputDevice.getDevice(mDeviceId);
+            final int[] vibratorIds =
+                    mInputManager.getVibratorIds(mDeviceId);
+            for (int i = 0; i < vibratorIds.length; i++) {
+                mVibrators.put(vibratorIds[i],
+                        new InputDeviceVibrator(mInputManager, mDeviceId, vibratorIds[i]));
+            }
+        }
+    }
+
+    @Override
+    public void onInputDeviceAdded(int deviceId) {
+    }
+
+    @Override
+    public void onInputDeviceRemoved(int deviceId) {
+        synchronized (mVibrators) {
+            if (deviceId == mDeviceId) {
+                mVibrators.clear();
+            }
+        }
+    }
+
+    @Override
+    public void onInputDeviceChanged(int deviceId) {
+        if (deviceId == mDeviceId) {
+            initializeVibrators();
+        }
+    }
+
+    @Override
+    public int[] getVibratorIds() {
+        synchronized (mVibrators) {
+            int[] vibratorIds = new int[mVibrators.size()];
+            for (int idx = 0; idx < mVibrators.size(); idx++) {
+                vibratorIds[idx++] = mVibrators.keyAt(idx);
+            }
+            return vibratorIds;
+        }
+    }
+
+    @Override
+    public Vibrator getVibrator(int vibratorId) {
+        synchronized (mVibrators) {
+            if (mVibrators.contains(vibratorId)) {
+                return mVibrators.get(vibratorId);
+            }
+        }
+        return NullVibrator.getInstance();
+    }
+
+    @Override
+    public Vibrator getDefaultVibrator() {
+        // Returns vibrator ID 0
+        synchronized (mVibrators) {
+            if (mVibrators.size() > 0) {
+                return mVibrators.valueAt(0);
+            }
+        }
+        return NullVibrator.getInstance();
+    }
+
+    @Override
+    public void vibrate(CombinedVibrationEffect effect) {
+        mInputManager.vibrate(mDeviceId, effect, mToken);
+    }
+}
diff --git a/core/java/android/hardware/input/InputManager.java b/core/java/android/hardware/input/InputManager.java
index 81ea2f5..f1d60f6 100644
--- a/core/java/android/hardware/input/InputManager.java
+++ b/core/java/android/hardware/input/InputManager.java
@@ -17,7 +17,6 @@
 package android.hardware.input;
 
 import android.Manifest;
-import android.annotation.CallbackExecutor;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -29,9 +28,9 @@
 import android.compat.annotation.ChangeId;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.Context;
-import android.os.Binder;
 import android.os.BlockUntrustedTouchesMode;
 import android.os.Build;
+import android.os.CombinedVibrationEffect;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.InputEventInjectionSync;
@@ -41,9 +40,9 @@
 import android.os.ServiceManager;
 import android.os.ServiceManager.ServiceNotFoundException;
 import android.os.SystemClock;
-import android.os.VibrationAttributes;
 import android.os.VibrationEffect;
 import android.os.Vibrator;
+import android.os.VibratorManager;
 import android.provider.Settings;
 import android.provider.Settings.SettingNotFoundException;
 import android.util.Log;
@@ -64,7 +63,6 @@
 import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
 import java.util.List;
-import java.util.concurrent.Executor;
 
 /**
  * Provides information about input devices and available key layouts.
@@ -1287,8 +1285,75 @@
      * @return The vibrator, never null.
      * @hide
      */
-    public Vibrator getInputDeviceVibrator(int deviceId) {
-        return new InputDeviceVibrator(deviceId);
+    public Vibrator getInputDeviceVibrator(int deviceId, int vibratorId) {
+        return new InputDeviceVibrator(this, deviceId, vibratorId);
+    }
+
+    /**
+     * Gets a vibrator manager service associated with an input device, always create a new
+     * instance.
+     * @return The vibrator manager, never null.
+     * @hide
+     */
+    @NonNull
+    public VibratorManager getInputDeviceVibratorManager(int deviceId) {
+        return new InputDeviceVibratorManager(InputManager.this, deviceId);
+    }
+
+    /*
+     * Get the list of device vibrators
+     * @return The list of vibrators IDs
+     */
+    int[] getVibratorIds(int deviceId) {
+        try {
+            return mIm.getVibratorIds(deviceId);
+        } catch (RemoteException ex) {
+            throw ex.rethrowFromSystemServer();
+        }
+    }
+
+    /*
+     * Perform vibration effect
+     */
+    void vibrate(int deviceId, VibrationEffect effect, IBinder token) {
+        try {
+            mIm.vibrate(deviceId, effect, token);
+        } catch (RemoteException ex) {
+            throw ex.rethrowFromSystemServer();
+        }
+    }
+
+    /*
+     * Perform combined vibration effect
+     */
+    void vibrate(int deviceId, CombinedVibrationEffect effect, IBinder token) {
+        try {
+            mIm.vibrateCombined(deviceId, effect, token);
+        } catch (RemoteException ex) {
+            throw ex.rethrowFromSystemServer();
+        }
+    }
+
+    /*
+     * Cancel an ongoing vibration
+     */
+    void cancelVibrate(int deviceId, IBinder token) {
+        try {
+            mIm.cancelVibrate(deviceId, token);
+        } catch (RemoteException ex) {
+            throw ex.rethrowFromSystemServer();
+        }
+    }
+
+    /*
+     * Check if input device is vibrating
+     */
+    boolean isVibrating(int deviceId)  {
+        try {
+            return mIm.isVibrating(deviceId);
+        } catch (RemoteException ex) {
+            throw ex.rethrowFromSystemServer();
+        }
     }
 
     /**
@@ -1401,72 +1466,4 @@
             }
         }
     }
-
-    private final class InputDeviceVibrator extends Vibrator {
-        private final int mDeviceId;
-        private final Binder mToken;
-
-        public InputDeviceVibrator(int deviceId) {
-            mDeviceId = deviceId;
-            mToken = new Binder();
-        }
-
-        @Override
-        public boolean hasVibrator() {
-            return true;
-        }
-
-        @Override
-        public boolean isVibrating() {
-            throw new UnsupportedOperationException(
-                "isVibrating not supported in InputDeviceVibrator");
-        }
-
-        @Override
-        public void addVibratorStateListener(@NonNull OnVibratorStateChangedListener listener) {
-            throw new UnsupportedOperationException(
-                "addVibratorStateListener not supported in InputDeviceVibrator");
-        }
-
-        @Override
-        public void addVibratorStateListener(
-                @NonNull @CallbackExecutor Executor executor,
-                @NonNull OnVibratorStateChangedListener listener) {
-            throw new UnsupportedOperationException(
-                "addVibratorStateListener not supported in InputDeviceVibrator");
-        }
-
-        @Override
-        public void removeVibratorStateListener(@NonNull OnVibratorStateChangedListener listener) {
-            throw new UnsupportedOperationException(
-                "removeVibratorStateListener not supported in InputDeviceVibrator");
-        }
-
-        @Override
-        public boolean hasAmplitudeControl() {
-            return true;
-        }
-
-        /**
-         * @hide
-         */
-        @Override
-        public void vibrate(int uid, String opPkg, @NonNull VibrationEffect effect,
-                String reason, @NonNull VibrationAttributes attributes) {
-            try {
-                mIm.vibrate(mDeviceId, effect, mToken);
-            } catch (RemoteException ex) {
-                throw ex.rethrowFromSystemServer();
-            }
-        }
-
-        @Override
-        public void cancel() {
-            try {
-                mIm.cancelVibrate(mDeviceId, mToken);
-            } catch (RemoteException ex) {
-                throw ex.rethrowFromSystemServer();
-            }
-        }
-    }
 }
diff --git a/core/java/android/hardware/input/OWNERS b/core/java/android/hardware/input/OWNERS
index 0313a40..25e02e1 100644
--- a/core/java/android/hardware/input/OWNERS
+++ b/core/java/android/hardware/input/OWNERS
@@ -1,2 +1,6 @@
+# Bug component: 136048
+
+include /services/core/java/com/android/server/input/OWNERS
+
 [email protected]
 [email protected]
diff --git a/core/java/android/hardware/iris/OWNERS b/core/java/android/hardware/iris/OWNERS
new file mode 100644
index 0000000..33527f8
--- /dev/null
+++ b/core/java/android/hardware/iris/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 879035
+
[email protected]
diff --git a/core/java/android/hardware/lights/OWNERS b/core/java/android/hardware/lights/OWNERS
new file mode 100644
index 0000000..cb46a80
--- /dev/null
+++ b/core/java/android/hardware/lights/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/lights/OWNERS
diff --git a/core/java/android/hardware/location/OWNERS b/core/java/android/hardware/location/OWNERS
new file mode 100644
index 0000000..383321b
--- /dev/null
+++ b/core/java/android/hardware/location/OWNERS
@@ -0,0 +1,6 @@
+# Bug component: 880425
+
[email protected]
[email protected]
[email protected]
[email protected]
diff --git a/core/java/android/hardware/soundtrigger/OWNERS b/core/java/android/hardware/soundtrigger/OWNERS
new file mode 100644
index 0000000..816bc6b
--- /dev/null
+++ b/core/java/android/hardware/soundtrigger/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/media/soundtrigger/OWNERS
diff --git a/core/java/android/hardware/usb/OWNERS b/core/java/android/hardware/usb/OWNERS
index 8ee72b5..8f2b39d 100644
--- a/core/java/android/hardware/usb/OWNERS
+++ b/core/java/android/hardware/usb/OWNERS
@@ -1,6 +1,4 @@
[email protected]
[email protected]
+# Bug component: 175220
+
 [email protected]
[email protected]
[email protected]
[email protected]
\ No newline at end of file
[email protected]
diff --git a/core/java/android/inputmethodservice/OWNERS b/core/java/android/inputmethodservice/OWNERS
index 4447197..e6a04da 100644
--- a/core/java/android/inputmethodservice/OWNERS
+++ b/core/java/android/inputmethodservice/OWNERS
@@ -1,3 +1,4 @@
+# Bug component: 34867
 set noparent
 
-include ../../../../services/core/java/com/android/server/inputmethod/OWNERS
+include /services/core/java/com/android/server/inputmethod/OWNERS
diff --git a/core/java/android/metrics/OWNERS b/core/java/android/metrics/OWNERS
new file mode 100644
index 0000000..ba867e0
--- /dev/null
+++ b/core/java/android/metrics/OWNERS
@@ -0,0 +1,4 @@
+# Bug component: 26805
+
[email protected]
[email protected]
diff --git a/core/java/android/net/NetworkUtils.java b/core/java/android/net/NetworkUtils.java
index a0faafa..d84ee2a 100644
--- a/core/java/android/net/NetworkUtils.java
+++ b/core/java/android/net/NetworkUtils.java
@@ -35,7 +35,6 @@
 import java.net.InetAddress;
 import java.net.SocketException;
 import java.net.UnknownHostException;
-import java.util.Collection;
 import java.util.Locale;
 import java.util.TreeSet;
 
@@ -342,20 +341,6 @@
     }
 
     /**
-     * Create a string array of host addresses from a collection of InetAddresses
-     * @param addrs a Collection of InetAddresses
-     * @return an array of Strings containing their host addresses
-     */
-    public static String[] makeStrings(Collection<InetAddress> addrs) {
-        String[] result = new String[addrs.size()];
-        int i = 0;
-        for (InetAddress addr : addrs) {
-            result[i++] = addr.getHostAddress();
-        }
-        return result;
-    }
-
-    /**
      * Trim leading zeros from IPv4 address strings
      * Our base libraries will interpret that as octel..
      * Must leave non v4 addresses and host names alone.
diff --git a/core/java/android/net/OWNERS b/core/java/android/net/OWNERS
index 5e2a718..2f8f685 100644
--- a/core/java/android/net/OWNERS
+++ b/core/java/android/net/OWNERS
@@ -2,7 +2,7 @@
 
 [email protected]
 [email protected]
[email protected]
[email protected]
 [email protected]
 [email protected]
 [email protected]
diff --git a/core/java/android/net/Proxy.java b/core/java/android/net/Proxy.java
index f1d9669..20ccc07 100644
--- a/core/java/android/net/Proxy.java
+++ b/core/java/android/net/Proxy.java
@@ -205,7 +205,7 @@
                 if (host.equalsIgnoreCase("localhost")) {
                     return true;
                 }
-                if (NetworkUtils.numericToInetAddress(host).isLoopbackAddress()) {
+                if (InetAddresses.parseNumericAddress(host).isLoopbackAddress()) {
                     return true;
                 }
             }
diff --git a/core/java/android/nfc/OWNERS b/core/java/android/nfc/OWNERS
new file mode 100644
index 0000000..6aaf039
--- /dev/null
+++ b/core/java/android/nfc/OWNERS
@@ -0,0 +1,4 @@
+# Bug component: 48448
+
[email protected]
[email protected]
diff --git a/core/java/android/nfc/cardemulation/OWNERS b/core/java/android/nfc/cardemulation/OWNERS
new file mode 100644
index 0000000..6aaf039
--- /dev/null
+++ b/core/java/android/nfc/cardemulation/OWNERS
@@ -0,0 +1,4 @@
+# Bug component: 48448
+
[email protected]
[email protected]
diff --git a/core/java/android/nfc/dta/OWNERS b/core/java/android/nfc/dta/OWNERS
new file mode 100644
index 0000000..6aaf039
--- /dev/null
+++ b/core/java/android/nfc/dta/OWNERS
@@ -0,0 +1,4 @@
+# Bug component: 48448
+
[email protected]
[email protected]
diff --git a/core/java/android/nfc/tech/OWNERS b/core/java/android/nfc/tech/OWNERS
new file mode 100644
index 0000000..6aaf039
--- /dev/null
+++ b/core/java/android/nfc/tech/OWNERS
@@ -0,0 +1,4 @@
+# Bug component: 48448
+
[email protected]
[email protected]
diff --git a/core/java/android/os/CombinedVibrationEffect.java b/core/java/android/os/CombinedVibrationEffect.java
index c9ebc1b..7ec7fff 100644
--- a/core/java/android/os/CombinedVibrationEffect.java
+++ b/core/java/android/os/CombinedVibrationEffect.java
@@ -30,8 +30,6 @@
  * Vibrator Vibrators}.
  *
  * These effects may be any number of things, from single shot vibrations to complex waveforms.
- *
- * @hide
  * @see VibrationEffect
  */
 @SuppressWarnings({"ParcelNotFinal", "ParcelCreator"}) // Parcel only extended here.
@@ -94,7 +92,6 @@
     /**
      * A combination of haptic effects that should be played in multiple vibrators in sync.
      *
-     * @hide
      * @see CombinedVibrationEffect#startSynced()
      */
     public static final class SyncedCombination {
@@ -144,7 +141,6 @@
     /**
      * A combination of haptic effects that should be played in multiple vibrators in sequence.
      *
-     * @hide
      * @see CombinedVibrationEffect#startSequential()
      */
     public static final class SequentialCombination {
diff --git a/core/java/android/os/FileUtils.java b/core/java/android/os/FileUtils.java
index 5db4107..379d6e6 100644
--- a/core/java/android/os/FileUtils.java
+++ b/core/java/android/os/FileUtils.java
@@ -1436,7 +1436,8 @@
     public static FileDescriptor convertToModernFd(FileDescriptor fd) {
         try {
             Context context = AppGlobals.getInitialApplication();
-            if (!SystemProperties.getBoolean("persist.sys.fuse.transcode", false)
+            // TODO(b/169327180): Consider device config.
+            if (!SystemProperties.getBoolean("persist.sys.fuse.transcode_enabled", false)
                     || !SystemProperties.getBoolean("persist.sys.fuse.transcode_optimize", true)
                     || UserHandle.getAppId(Process.myUid()) == getMediaProviderAppId(context)) {
                 // If transcode is enabled we optimize by default, unless explicitly disabled.
diff --git a/core/java/android/os/OWNERS b/core/java/android/os/OWNERS
index 91eb2a5..d392d71 100644
--- a/core/java/android/os/OWNERS
+++ b/core/java/android/os/OWNERS
@@ -16,7 +16,7 @@
 per-file PowerManager.java = [email protected], [email protected]
 per-file PowerManagerInternal.java = [email protected], [email protected]
 
-# Zygote
-per-file ZygoteProcess.java = [email protected], [email protected], [email protected], [email protected], [email protected]
 
 per-file GraphicsEnvironment.java = [email protected], [email protected], [email protected], [email protected], [email protected]
+
+per-file *Zygote* = file:/ZYGOTE_OWNERS
diff --git a/core/java/android/os/ParcelableHolder.java b/core/java/android/os/ParcelableHolder.java
index fb9fa10..1be367c 100644
--- a/core/java/android/os/ParcelableHolder.java
+++ b/core/java/android/os/ParcelableHolder.java
@@ -120,31 +120,37 @@
 
     /**
      * Write a parcelable into ParcelableHolder, the previous parcelable will be removed.
-     * @return {@code false} if the parcelable's stability is more unstable ParcelableHolder.
+     * @throws BadParcelableException if the parcelable's stability is more unstable
+     *         ParcelableHolder.
      */
-    public boolean setParcelable(@Nullable Parcelable p) {
-        // a ParcelableHolder can only hold things at its stability or higher
+    public void setParcelable(@Nullable Parcelable p) {
+        // A ParcelableHolder can only hold things at its stability or higher.
         if (p != null && this.getStability() > p.getStability()) {
-            return false;
+            throw new BadParcelableException(
+                "A ParcelableHolder can only hold things at its stability or higher. "
+                + "The ParcelableHolder's stability is " + this.getStability()
+                + ", but the parcelable's stability is " + p.getStability());
         }
         mParcelable = p;
         if (mParcel != null) {
             mParcel.recycle();
             mParcel = null;
         }
-        return true;
     }
 
     /**
      * @return the parcelable that was written by {@link #setParcelable} or {@link #readFromParcel},
-     *         or {@code null} if the parcelable has not been written, or T is different from
-     *         the type written by (@link #setParcelable}.
+     *         or {@code null} if the parcelable has not been written.
+     * @throws BadParcelableException if T is different from the type written by
+     *         (@link #setParcelable}.
      */
     @Nullable
     public <T extends Parcelable> T getParcelable(@NonNull Class<T> clazz) {
         if (mParcel == null) {
-            if (!clazz.isInstance(mParcelable)) {
-                return null;
+            if (mParcelable != null && !clazz.isInstance(mParcelable)) {
+                throw new BadParcelableException(
+                    "The ParcelableHolder has " + mParcelable.getClass().getName()
+                    + ", but the requested type is " + clazz.getName());
             }
             return (T) mParcelable;
         }
@@ -152,8 +158,10 @@
         mParcel.setDataPosition(0);
 
         T parcelable = mParcel.readParcelable(clazz.getClassLoader());
-        if (!clazz.isInstance(parcelable)) {
-            return null;
+        if (parcelable != null && !clazz.isInstance(parcelable)) {
+            throw new BadParcelableException(
+                    "The ParcelableHolder has " + parcelable.getClass().getName()
+                    + ", but the requested type is " + clazz.getName());
         }
         mParcelable = parcelable;
 
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index aba1f281..e7d19c5 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -136,6 +136,12 @@
     public static final String USER_TYPE_PROFILE_MANAGED = "android.os.usertype.profile.MANAGED";
 
     /**
+     * User type representing a generic profile for testing purposes. Only on debuggable builds.
+     * @hide
+     */
+    public static final String USER_TYPE_PROFILE_TEST = "android.os.usertype.profile.TEST";
+
+    /**
      * User type representing a {@link UserHandle#USER_SYSTEM system} user that is <b>not</b> a
      * human user.
      * This type of user cannot be created; it can only pre-exist on first boot.
diff --git a/core/java/android/os/VibratorManager.java b/core/java/android/os/VibratorManager.java
new file mode 100644
index 0000000..1d5a587
--- /dev/null
+++ b/core/java/android/os/VibratorManager.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os;
+
+import android.annotation.NonNull;
+
+/**
+ * VibratorManager provides access to multiple vibrators, as well as the ability to run them in
+ * a synchronized fashion.
+ */
+public abstract class VibratorManager {
+    /** @hide */
+    protected static final String TAG = "VibratorManager";
+
+    /**
+     * {@hide}
+     */
+    public VibratorManager() {
+    }
+
+    /**
+     * This method lists all available actuator ids, returning a possible empty list.
+     * If the device has only a single actuator, this should return a single entry with a
+     * default id.
+     */
+    @NonNull
+    public abstract int[] getVibratorIds();
+
+    /**
+    * Returns a Vibrator service for given id.
+    * This allows users to perform a vibration effect on a single actuator.
+    */
+    @NonNull
+    public abstract Vibrator getVibrator(int vibratorId);
+
+    /**
+    * Returns the system default Vibrator service.
+    */
+    @NonNull
+    public abstract Vibrator getDefaultVibrator();
+
+    /**
+     * Vibrates all actuators by passing each VibrationEffect within CombinedVibrationEffect
+     * to the respective actuator, in sync.
+     */
+    public abstract void vibrate(@NonNull CombinedVibrationEffect effect);
+}
diff --git a/core/java/android/os/connectivity/OWNERS b/core/java/android/os/connectivity/OWNERS
new file mode 100644
index 0000000..a0f0238
--- /dev/null
+++ b/core/java/android/os/connectivity/OWNERS
@@ -0,0 +1 @@
[email protected]
diff --git a/core/java/android/os/health/OWNERS b/core/java/android/os/health/OWNERS
new file mode 100644
index 0000000..6045344
--- /dev/null
+++ b/core/java/android/os/health/OWNERS
@@ -0,0 +1,4 @@
+# Bug component: 26805
+
[email protected]
[email protected]
diff --git a/core/java/android/os/image/OWNERS b/core/java/android/os/image/OWNERS
new file mode 100644
index 0000000..389b55b
--- /dev/null
+++ b/core/java/android/os/image/OWNERS
@@ -0,0 +1 @@
[email protected]
diff --git a/core/java/android/os/storage/OWNERS b/core/java/android/os/storage/OWNERS
new file mode 100644
index 0000000..8af7de5
--- /dev/null
+++ b/core/java/android/os/storage/OWNERS
@@ -0,0 +1,7 @@
+# Bug component: 95221
+
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
diff --git a/core/java/android/permission/IPermissionManager.aidl b/core/java/android/permission/IPermissionManager.aidl
index 9855a9a..a94077d 100644
--- a/core/java/android/permission/IPermissionManager.aidl
+++ b/core/java/android/permission/IPermissionManager.aidl
@@ -87,10 +87,6 @@
 
     void revokeDefaultPermissionsFromLuiApps(in String[] packageNames, int userId);
 
-    void setPermissionEnforced(String permName, boolean enforced);
-
-    boolean isPermissionEnforced(String permName);
-
     boolean shouldShowRequestPermissionRationale(String permName,
             String packageName, int userId);
 
diff --git a/core/java/android/permission/OWNERS b/core/java/android/permission/OWNERS
new file mode 100644
index 0000000..d09f351
--- /dev/null
+++ b/core/java/android/permission/OWNERS
@@ -0,0 +1,8 @@
+# Bug component: 137825
+
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
diff --git a/core/java/android/permission/PermissionManagerInternal.java b/core/java/android/permission/PermissionManagerInternal.java
index 7167431..a4676c4 100644
--- a/core/java/android/permission/PermissionManagerInternal.java
+++ b/core/java/android/permission/PermissionManagerInternal.java
@@ -19,7 +19,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.UserIdInt;
-import android.os.UserHandle;
 
 /**
  * Internal interfaces to be used by other components within the system server.
@@ -28,69 +27,39 @@
  *
  * @hide
  */
-public abstract class PermissionManagerInternal {
-
+public interface PermissionManagerInternal {
     /**
-     * Listener for package permission state (permissions or flags) changes.
-     */
-    public interface OnRuntimePermissionStateChangedListener {
-
-        /**
-         * Called when the runtime permission state (permissions or flags) changed.
-         *
-         * @param packageName The package for which the change happened.
-         * @param userId the user id for which the change happened.
-         */
-        @Nullable
-        void onRuntimePermissionStateChanged(@NonNull String packageName,
-                @UserIdInt int userId);
-    }
-
-    /**
-     * Get the state of the runtime permissions as xml file.
+     * Get the state of the runtime permissions as a blob.
      *
-     * @param user The user the data should be extracted for
+     * @param userId The user ID the data should be extracted for
      *
-     * @return The state as a xml file
+     * @return the state as a blob
      */
-    public abstract @Nullable byte[] backupRuntimePermissions(@NonNull UserHandle user);
+    //@SystemApi(client = SystemApi.Client.SYSTEM_SERVER)
+    @Nullable
+    byte[] backupRuntimePermissions(@UserIdInt int userId);
 
     /**
      * Restore a permission state previously backed up via {@link #backupRuntimePermissions}.
+     * <p>
+     * If not all state can be restored, the un-restorable state will be delayed and can be
+     * retried via {@link #restoreDelayedRuntimePermissions}.
      *
-     * <p>If not all state can be restored, the un-restoreable state will be delayed and can be
-     * re-tried via {@link #restoreDelayedRuntimePermissions}.
-     *
-     * @param backup The state as an xml file
-     * @param user The user the data should be restored for
+     * @param backup the state as a blob
+     * @param userId the user ID the data should be restored for
      */
-    public abstract void restoreRuntimePermissions(@NonNull byte[] backup,
-            @NonNull UserHandle user);
+    //@SystemApi(client = SystemApi.Client.SYSTEM_SERVER)
+    void restoreRuntimePermissions(@NonNull byte[] backup, @UserIdInt int userId);
 
     /**
      * Try to apply permission backup of a package that was previously not applied.
      *
-     * @param packageName The package that is newly installed
-     * @param user The user the package is installed for
+     * @param packageName the package that is newly installed
+     * @param userId the user ID the package is installed for
      *
      * @see #restoreRuntimePermissions
      */
-    public abstract void restoreDelayedRuntimePermissions(@NonNull String packageName,
-            @NonNull UserHandle user);
-
-    /**
-     * Adds a listener for runtime permission state (permissions or flags) changes.
-     *
-     * @param listener The listener.
-     */
-    public abstract void addOnRuntimePermissionStateChangedListener(
-            @NonNull OnRuntimePermissionStateChangedListener listener);
-
-    /**
-     * Removes a listener for runtime permission state (permissions or flags) changes.
-     *
-     * @param listener The listener.
-     */
-    public abstract void removeOnRuntimePermissionStateChangedListener(
-            @NonNull OnRuntimePermissionStateChangedListener listener);
+    //@SystemApi(client = SystemApi.Client.SYSTEM_SERVER)
+    void restoreDelayedRuntimePermissions(@NonNull String packageName,
+            @UserIdInt int userId);
 }
diff --git a/core/java/android/permissionpresenterservice/OWNERS b/core/java/android/permissionpresenterservice/OWNERS
new file mode 100644
index 0000000..d09f351
--- /dev/null
+++ b/core/java/android/permissionpresenterservice/OWNERS
@@ -0,0 +1,8 @@
+# Bug component: 137825
+
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
diff --git a/core/java/android/print/OWNERS b/core/java/android/print/OWNERS
new file mode 100644
index 0000000..72f0983
--- /dev/null
+++ b/core/java/android/print/OWNERS
@@ -0,0 +1,5 @@
+# Bug component: 47273
+
[email protected]
[email protected]
[email protected]
diff --git a/core/java/android/print/pdf/OWNERS b/core/java/android/print/pdf/OWNERS
new file mode 100644
index 0000000..72f0983
--- /dev/null
+++ b/core/java/android/print/pdf/OWNERS
@@ -0,0 +1,5 @@
+# Bug component: 47273
+
[email protected]
[email protected]
[email protected]
diff --git a/core/java/android/printservice/OWNERS b/core/java/android/printservice/OWNERS
new file mode 100644
index 0000000..72f0983
--- /dev/null
+++ b/core/java/android/printservice/OWNERS
@@ -0,0 +1,5 @@
+# Bug component: 47273
+
[email protected]
[email protected]
[email protected]
diff --git a/core/java/android/printservice/recommendation/OWNERS b/core/java/android/printservice/recommendation/OWNERS
new file mode 100644
index 0000000..72f0983
--- /dev/null
+++ b/core/java/android/printservice/recommendation/OWNERS
@@ -0,0 +1,5 @@
+# Bug component: 47273
+
[email protected]
[email protected]
[email protected]
diff --git a/core/java/android/provider/OWNERS b/core/java/android/provider/OWNERS
index 97e0156..792ff20 100644
--- a/core/java/android/provider/OWNERS
+++ b/core/java/android/provider/OWNERS
@@ -2,4 +2,8 @@
 per-file DeviceConfig.java = [email protected]
 per-file DeviceConfig.java = [email protected]
 
-
+per-file CallLog.java = file:/telephony/OWNERS
+per-file DocumentsContract.java = file:/core/java/android/os/storage/OWNERS
+per-file DocumentsProvider.java = file:/core/java/android/os/storage/OWNERS
+per-file MediaStore.java = file:/core/java/android/os/storage/OWNERS
+per-file Telephony.java = file:/telephony/OWNERS
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 12791bc..fb0aea0 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -14484,10 +14484,11 @@
         public static final String SHOW_PEOPLE_SPACE = "show_people_space";
 
         /**
-         * Which types of conversations to show in People Space.
+         * Which types of conversation(s) to show in People Space.
          * Values are:
-         * 0: All conversations (default)
+         * 0: Single user-selected conversation (default)
          * 1: Priority conversations only
+         * 2: All conversations
          * @hide
          */
         public static final String PEOPLE_SPACE_CONVERSATION_TYPE =
diff --git a/core/java/android/se/OWNERS b/core/java/android/se/OWNERS
new file mode 100644
index 0000000..f1539dc
--- /dev/null
+++ b/core/java/android/se/OWNERS
@@ -0,0 +1,4 @@
+# Bug component: 456592
+
[email protected]
[email protected]
diff --git a/core/java/android/se/omapi/OWNERS b/core/java/android/se/omapi/OWNERS
new file mode 100644
index 0000000..f1539dc
--- /dev/null
+++ b/core/java/android/se/omapi/OWNERS
@@ -0,0 +1,4 @@
+# Bug component: 456592
+
[email protected]
[email protected]
diff --git a/core/java/android/security/OWNERS b/core/java/android/security/OWNERS
index 7120376..3f8d75e 100644
--- a/core/java/android/security/OWNERS
+++ b/core/java/android/security/OWNERS
@@ -1,3 +1,8 @@
+# Bug component: 36824
+
[email protected]
[email protected]
+
 per-file NetworkSecurityPolicy.java = [email protected]
 per-file NetworkSecurityPolicy.java = [email protected]
 per-file FrameworkNetworkSecurityPolicy.java = [email protected]
diff --git a/core/java/android/security/keymaster/OWNERS b/core/java/android/security/keymaster/OWNERS
new file mode 100644
index 0000000..65129a4
--- /dev/null
+++ b/core/java/android/security/keymaster/OWNERS
@@ -0,0 +1,5 @@
+# Bug component: 189335
+
[email protected]
[email protected]
[email protected]
diff --git a/core/java/android/security/keystore/OWNERS b/core/java/android/security/keystore/OWNERS
index bb487fb..65129a4 100644
--- a/core/java/android/security/keystore/OWNERS
+++ b/core/java/android/security/keystore/OWNERS
@@ -1,4 +1,5 @@
[email protected]
[email protected]
[email protected]
[email protected]
+# Bug component: 189335
+
[email protected]
[email protected]
[email protected]
diff --git a/core/java/android/security/keystore/recovery/OWNERS b/core/java/android/security/keystore/recovery/OWNERS
new file mode 100644
index 0000000..65129a4
--- /dev/null
+++ b/core/java/android/security/keystore/recovery/OWNERS
@@ -0,0 +1,5 @@
+# Bug component: 189335
+
[email protected]
[email protected]
[email protected]
diff --git a/core/java/android/security/net/OWNERS b/core/java/android/security/net/OWNERS
new file mode 100644
index 0000000..d828164
--- /dev/null
+++ b/core/java/android/security/net/OWNERS
@@ -0,0 +1,4 @@
+# Bug component: 36824
+
[email protected]
[email protected]
diff --git a/core/java/android/security/net/config/OWNERS b/core/java/android/security/net/config/OWNERS
index 5350373..85ce3c6 100644
--- a/core/java/android/security/net/config/OWNERS
+++ b/core/java/android/security/net/config/OWNERS
@@ -1,3 +1,5 @@
+# Bug component: 36824
 set noparent
+
 [email protected]
[email protected]
[email protected]
diff --git a/core/java/android/service/appprediction/OWNERS b/core/java/android/service/appprediction/OWNERS
new file mode 100644
index 0000000..fe012da
--- /dev/null
+++ b/core/java/android/service/appprediction/OWNERS
@@ -0,0 +1,2 @@
[email protected]
[email protected]
diff --git a/core/java/android/service/attention/OWNERS b/core/java/android/service/attention/OWNERS
new file mode 100644
index 0000000..dd579b6
--- /dev/null
+++ b/core/java/android/service/attention/OWNERS
@@ -0,0 +1 @@
[email protected]
diff --git a/core/java/android/service/autofill/OWNERS b/core/java/android/service/autofill/OWNERS
new file mode 100644
index 0000000..a088632
--- /dev/null
+++ b/core/java/android/service/autofill/OWNERS
@@ -0,0 +1,9 @@
+# Bug component: 351486
+
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
diff --git a/core/java/android/service/autofill/augmented/OWNERS b/core/java/android/service/autofill/augmented/OWNERS
new file mode 100644
index 0000000..a088632
--- /dev/null
+++ b/core/java/android/service/autofill/augmented/OWNERS
@@ -0,0 +1,9 @@
+# Bug component: 351486
+
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
diff --git a/core/java/android/service/carrier/OWNERS b/core/java/android/service/carrier/OWNERS
new file mode 100644
index 0000000..d768ef4
--- /dev/null
+++ b/core/java/android/service/carrier/OWNERS
@@ -0,0 +1,5 @@
+# Bug component: 20868
+
[email protected]
[email protected]
[email protected]
diff --git a/core/java/android/service/chooser/OWNERS b/core/java/android/service/chooser/OWNERS
new file mode 100644
index 0000000..a5acba5
--- /dev/null
+++ b/core/java/android/service/chooser/OWNERS
@@ -0,0 +1,4 @@
[email protected]
[email protected]
[email protected]
[email protected]
diff --git a/core/java/android/service/contentcapture/OWNERS b/core/java/android/service/contentcapture/OWNERS
new file mode 100644
index 0000000..6337327
--- /dev/null
+++ b/core/java/android/service/contentcapture/OWNERS
@@ -0,0 +1,9 @@
+# Bug component: 544200
+
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
diff --git a/core/java/android/service/contentsuggestions/OWNERS b/core/java/android/service/contentsuggestions/OWNERS
new file mode 100644
index 0000000..46b5ea0
--- /dev/null
+++ b/core/java/android/service/contentsuggestions/OWNERS
@@ -0,0 +1,7 @@
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
diff --git a/core/java/android/service/dreams/OWNERS b/core/java/android/service/dreams/OWNERS
index 708ab4c..f831805 100644
--- a/core/java/android/service/dreams/OWNERS
+++ b/core/java/android/service/dreams/OWNERS
@@ -1,4 +1,3 @@
[email protected]
[email protected]
[email protected]
[email protected]
+# Bug component: 78010
+
[email protected]
diff --git a/core/java/android/service/gatekeeper/OWNERS b/core/java/android/service/gatekeeper/OWNERS
new file mode 100644
index 0000000..2ca52cd
--- /dev/null
+++ b/core/java/android/service/gatekeeper/OWNERS
@@ -0,0 +1,3 @@
[email protected]
[email protected]
[email protected]
diff --git a/core/java/android/service/media/OWNERS b/core/java/android/service/media/OWNERS
new file mode 100644
index 0000000..916fc36
--- /dev/null
+++ b/core/java/android/service/media/OWNERS
@@ -0,0 +1,8 @@
+# Bug component: 137631
+
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
diff --git a/core/java/android/service/notification/OWNERS b/core/java/android/service/notification/OWNERS
index 2e94be5..debb493 100644
--- a/core/java/android/service/notification/OWNERS
+++ b/core/java/android/service/notification/OWNERS
@@ -1,4 +1,6 @@
+# Bug component: 34005
+
 [email protected]
[email protected]
[email protected]
 [email protected]
[email protected]
\ No newline at end of file
[email protected]
diff --git a/core/java/android/service/quicksettings/OWNERS b/core/java/android/service/quicksettings/OWNERS
new file mode 100644
index 0000000..12eb7c7
--- /dev/null
+++ b/core/java/android/service/quicksettings/OWNERS
@@ -0,0 +1,6 @@
+# Bug component: 78010
+
[email protected]
[email protected]
[email protected]
[email protected]
diff --git a/core/java/android/service/resolver/OWNERS b/core/java/android/service/resolver/OWNERS
new file mode 100644
index 0000000..10150c37
--- /dev/null
+++ b/core/java/android/service/resolver/OWNERS
@@ -0,0 +1,6 @@
+# Bug component: 78010
+
[email protected]
[email protected]
[email protected]
[email protected]
diff --git a/core/java/android/service/restrictions/OWNERS b/core/java/android/service/restrictions/OWNERS
new file mode 100644
index 0000000..eaba2e9
--- /dev/null
+++ b/core/java/android/service/restrictions/OWNERS
@@ -0,0 +1 @@
[email protected]
diff --git a/core/java/android/service/textclassifier/OWNERS b/core/java/android/service/textclassifier/OWNERS
new file mode 100644
index 0000000..a535f52
--- /dev/null
+++ b/core/java/android/service/textclassifier/OWNERS
@@ -0,0 +1,9 @@
+# Bug component: 709498
+
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
diff --git a/core/java/android/service/textservice/OWNERS b/core/java/android/service/textservice/OWNERS
new file mode 100644
index 0000000..a637754
--- /dev/null
+++ b/core/java/android/service/textservice/OWNERS
@@ -0,0 +1,5 @@
+# Bug component: 34867
+
[email protected]
[email protected]
[email protected]
diff --git a/core/java/android/service/trust/OWNERS b/core/java/android/service/trust/OWNERS
new file mode 100644
index 0000000..affe471
--- /dev/null
+++ b/core/java/android/service/trust/OWNERS
@@ -0,0 +1,4 @@
+# Bug component: 36824
+
[email protected]
[email protected]
diff --git a/core/java/android/service/voice/OWNERS b/core/java/android/service/voice/OWNERS
new file mode 100644
index 0000000..46b5ea0
--- /dev/null
+++ b/core/java/android/service/voice/OWNERS
@@ -0,0 +1,7 @@
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
diff --git a/core/java/android/service/wallpaper/OWNERS b/core/java/android/service/wallpaper/OWNERS
new file mode 100644
index 0000000..756eef8
--- /dev/null
+++ b/core/java/android/service/wallpaper/OWNERS
@@ -0,0 +1,5 @@
+# Bug component: 78010
+
[email protected]
[email protected]
[email protected]
diff --git a/core/java/android/service/watchdog/OWNERS b/core/java/android/service/watchdog/OWNERS
new file mode 100644
index 0000000..1c045e1
--- /dev/null
+++ b/core/java/android/service/watchdog/OWNERS
@@ -0,0 +1,3 @@
[email protected]
[email protected]
[email protected]
diff --git a/core/java/android/timezone/OWNERS b/core/java/android/timezone/OWNERS
new file mode 100644
index 0000000..09447a97
--- /dev/null
+++ b/core/java/android/timezone/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/app/timezone/OWNERS
diff --git a/core/java/android/transition/OWNERS b/core/java/android/transition/OWNERS
new file mode 100644
index 0000000..eb5a581
--- /dev/null
+++ b/core/java/android/transition/OWNERS
@@ -0,0 +1,6 @@
+# Bug component: 25700
+
[email protected]
[email protected]
[email protected]
[email protected]
diff --git a/core/java/android/util/proto/OWNERS b/core/java/android/util/proto/OWNERS
new file mode 100644
index 0000000..1eb6abf
--- /dev/null
+++ b/core/java/android/util/proto/OWNERS
@@ -0,0 +1,2 @@
[email protected]
[email protected]
diff --git a/core/java/android/view/IPinnedStackListener.aidl b/core/java/android/view/IPinnedStackListener.aidl
index 84dd8af..29c9c15 100644
--- a/core/java/android/view/IPinnedStackListener.aidl
+++ b/core/java/android/view/IPinnedStackListener.aidl
@@ -58,19 +58,6 @@
     void onActivityHidden(in ComponentName componentName);
 
     /**
-     * Called when the window manager has detected change on DisplayInfo,  or
-     * when the listener is first registered to allow the listener to synchronized its state with
-     * the controller.
-     */
-    void onDisplayInfoChanged(in DisplayInfo displayInfo);
-
-    /**
-     * Called by the window manager at the beginning of a configuration update cascade
-     * since the metrics from these resources are used for bounds calculations.
-     */
-    void onConfigurationChanged();
-
-    /**
      * Called by the window manager when the aspect ratio is reset.
      */
     void onAspectRatioChanged(float aspectRatio);
diff --git a/core/java/android/view/InputDevice.java b/core/java/android/view/InputDevice.java
index 8da833a..df96dc3 100644
--- a/core/java/android/view/InputDevice.java
+++ b/core/java/android/view/InputDevice.java
@@ -17,6 +17,7 @@
 package android.view;
 
 import android.annotation.IntDef;
+import android.annotation.NonNull;
 import android.annotation.RequiresPermission;
 import android.annotation.TestApi;
 import android.compat.annotation.UnsupportedAppUsage;
@@ -28,7 +29,9 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.os.Vibrator;
+import android.os.VibratorManager;
 
+import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 
 import java.lang.annotation.Retention;
@@ -72,6 +75,9 @@
 
     private Vibrator mVibrator; // guarded by mMotionRanges during initialization
 
+    @GuardedBy("mMotionRanges")
+    private VibratorManager mVibratorManager;
+
     /**
      * A mask for input source classes.
      *
@@ -415,6 +421,8 @@
 
     private static final int MAX_RANGES = 1000;
 
+    private static final int VIBRATOR_ID_ALL = -1;
+
     public static final @android.annotation.NonNull Parcelable.Creator<InputDevice> CREATOR =
             new Parcelable.Creator<InputDevice>() {
         public InputDevice createFromParcel(Parcel in) {
@@ -785,7 +793,8 @@
         synchronized (mMotionRanges) {
             if (mVibrator == null) {
                 if (mHasVibrator) {
-                    mVibrator = InputManager.getInstance().getInputDeviceVibrator(mId);
+                    mVibrator = InputManager.getInstance().getInputDeviceVibrator(mId,
+                            VIBRATOR_ID_ALL);
                 } else {
                     mVibrator = NullVibrator.getInstance();
                 }
@@ -795,6 +804,24 @@
     }
 
     /**
+     * Gets the vibrator manager associated with the device.
+     * Even if the device does not have a vibrator manager, the result is never null.
+     * Use {@link VibratorManager#getVibratorIds} to determine whether any vibrator is
+     * present.
+     *
+     * @return The vibrator manager associated with the device, never null.
+     */
+    @NonNull
+    public VibratorManager getVibratorManager() {
+        synchronized (mMotionRanges) {
+            if (mVibratorManager == null) {
+                mVibratorManager = InputManager.getInstance().getInputDeviceVibratorManager(mId);
+            }
+        }
+        return mVibratorManager;
+    }
+
+    /**
      * Returns true if input device is enabled.
      * @return Whether the input device is enabled.
      */
diff --git a/core/java/android/view/OWNERS b/core/java/android/view/OWNERS
index 7b60f2e..4f82b86 100644
--- a/core/java/android/view/OWNERS
+++ b/core/java/android/view/OWNERS
@@ -1,3 +1,14 @@
+# Bug component: 25700
+
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
+
 # Display
 per-file Display.java = [email protected], [email protected]
 per-file DisplayInfo.java = [email protected], [email protected]
diff --git a/core/java/android/view/accessibility/OWNERS b/core/java/android/view/accessibility/OWNERS
index c6f42f7..93b5a2e 100644
--- a/core/java/android/view/accessibility/OWNERS
+++ b/core/java/android/view/accessibility/OWNERS
@@ -1,4 +1,11 @@
[email protected]
+# Bug component: 44214
+
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
 [email protected]
[email protected]
[email protected]
diff --git a/core/java/android/view/animation/OWNERS b/core/java/android/view/animation/OWNERS
new file mode 100644
index 0000000..9b8f4d9
--- /dev/null
+++ b/core/java/android/view/animation/OWNERS
@@ -0,0 +1,6 @@
+# Bug component: 25700
+
[email protected]
[email protected]
[email protected]
[email protected]
diff --git a/core/java/android/view/autofill/OWNERS b/core/java/android/view/autofill/OWNERS
new file mode 100644
index 0000000..a088632
--- /dev/null
+++ b/core/java/android/view/autofill/OWNERS
@@ -0,0 +1,9 @@
+# Bug component: 351486
+
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
diff --git a/core/java/android/view/contentcapture/OWNERS b/core/java/android/view/contentcapture/OWNERS
new file mode 100644
index 0000000..6337327
--- /dev/null
+++ b/core/java/android/view/contentcapture/OWNERS
@@ -0,0 +1,9 @@
+# Bug component: 544200
+
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
diff --git a/core/java/android/view/inputmethod/OWNERS b/core/java/android/view/inputmethod/OWNERS
index 244cc30..e6a04da 100644
--- a/core/java/android/view/inputmethod/OWNERS
+++ b/core/java/android/view/inputmethod/OWNERS
@@ -1,3 +1,4 @@
+# Bug component: 34867
 set noparent
 
-include ../../../../../services/core/java/com/android/server/inputmethod/OWNERS
+include /services/core/java/com/android/server/inputmethod/OWNERS
diff --git a/core/java/android/view/inspector/OWNERS b/core/java/android/view/inspector/OWNERS
index c2827cc..705f4b3 100644
--- a/core/java/android/view/inspector/OWNERS
+++ b/core/java/android/view/inspector/OWNERS
@@ -1,3 +1,6 @@
[email protected]
 [email protected]
[email protected]
 [email protected]
[email protected]
[email protected]
[email protected]
diff --git a/core/java/android/view/textclassifier/OWNERS b/core/java/android/view/textclassifier/OWNERS
index be4fbaa..ac80d9f 100644
--- a/core/java/android/view/textclassifier/OWNERS
+++ b/core/java/android/view/textclassifier/OWNERS
@@ -1,14 +1,8 @@
 # Bug component: 709498
 
[email protected]
 [email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
 [email protected]
[email protected]
[email protected]
[email protected]
 [email protected]
[email protected]
[email protected]
\ No newline at end of file
[email protected]
diff --git a/core/java/android/view/textclassifier/intent/OWNERS b/core/java/android/view/textclassifier/intent/OWNERS
new file mode 100644
index 0000000..ac80d9f
--- /dev/null
+++ b/core/java/android/view/textclassifier/intent/OWNERS
@@ -0,0 +1,8 @@
+# Bug component: 709498
+
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
diff --git a/core/java/android/view/textclassifier/logging/OWNERS b/core/java/android/view/textclassifier/logging/OWNERS
new file mode 100644
index 0000000..ac80d9f
--- /dev/null
+++ b/core/java/android/view/textclassifier/logging/OWNERS
@@ -0,0 +1,8 @@
+# Bug component: 709498
+
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
diff --git a/core/java/android/view/textservice/OWNERS b/core/java/android/view/textservice/OWNERS
new file mode 100644
index 0000000..a637754
--- /dev/null
+++ b/core/java/android/view/textservice/OWNERS
@@ -0,0 +1,5 @@
+# Bug component: 34867
+
[email protected]
[email protected]
[email protected]
diff --git a/core/java/android/widget/OWNERS b/core/java/android/widget/OWNERS
index 5c79d21..fbb975b 100644
--- a/core/java/android/widget/OWNERS
+++ b/core/java/android/widget/OWNERS
@@ -1 +1,9 @@
+# Bug component: 25700
+
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
+
 per-file TextView.java, EditText.java, Editor.java = [email protected], [email protected], [email protected]
diff --git a/core/java/android/window/OWNERS b/core/java/android/window/OWNERS
index d10fb31..2c61df9 100644
--- a/core/java/android/window/OWNERS
+++ b/core/java/android/window/OWNERS
@@ -1,3 +1,3 @@
 set noparent
 
-include ../../../../services/core/java/com/android/server/wm/OWNERS
+include /services/core/java/com/android/server/wm/OWNERS
diff --git a/core/java/com/android/ims/OWNERS b/core/java/com/android/ims/OWNERS
new file mode 100644
index 0000000..640baf2
--- /dev/null
+++ b/core/java/com/android/ims/OWNERS
@@ -0,0 +1 @@
+include /telephony/OWNERS
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index 83cbe38..2dbcbb5 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -1220,25 +1220,6 @@
                         if (TextUtils.isEmpty(packageName)) {
                             pm.setDefaultBrowserPackageNameAsUser(ri.activityInfo.packageName, userId);
                         }
-                    } else {
-                        // Update Domain Verification status
-                        ComponentName cn = intent.getComponent();
-                        String packageName = cn.getPackageName();
-                        String dataScheme = (data != null) ? data.getScheme() : null;
-
-                        boolean isHttpOrHttps = (dataScheme != null) &&
-                                (dataScheme.equals(IntentFilter.SCHEME_HTTP) ||
-                                        dataScheme.equals(IntentFilter.SCHEME_HTTPS));
-
-                        boolean isViewAction = (action != null) && action.equals(Intent.ACTION_VIEW);
-                        boolean hasCategoryBrowsable = (categories != null) &&
-                                categories.contains(Intent.CATEGORY_BROWSABLE);
-
-                        if (isHttpOrHttps && isViewAction && hasCategoryBrowsable) {
-                            pm.updateIntentVerificationStatusAsUser(packageName,
-                                    PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS,
-                                    userId);
-                        }
                     }
                 } else {
                     try {
diff --git a/core/java/com/android/internal/config/sysui/OWNERS b/core/java/com/android/internal/config/sysui/OWNERS
new file mode 100644
index 0000000..2e96c97
--- /dev/null
+++ b/core/java/com/android/internal/config/sysui/OWNERS
@@ -0,0 +1 @@
+include /packages/SystemUI/OWNERS
diff --git a/core/java/com/android/internal/net/OWNERS b/core/java/com/android/internal/net/OWNERS
index 050cb5c..fec56c3 100644
--- a/core/java/com/android/internal/net/OWNERS
+++ b/core/java/com/android/internal/net/OWNERS
@@ -3,7 +3,7 @@
 [email protected]
 [email protected]
 [email protected]
[email protected]
[email protected]
 [email protected]
 [email protected]
 [email protected]
diff --git a/core/java/com/android/internal/os/KernelWakelockReader.java b/core/java/com/android/internal/os/KernelWakelockReader.java
index f668bba..e595db3 100644
--- a/core/java/com/android/internal/os/KernelWakelockReader.java
+++ b/core/java/com/android/internal/os/KernelWakelockReader.java
@@ -184,6 +184,7 @@
 
         try {
             wlStats = mSuspendControlService.getWakeLockStats();
+            Slog.i(TAG, "Number of wakelock obtained from SystemSuspend: " + wlStats.length);
             updateWakelockStats(wlStats, staleStats);
         } catch (RemoteException e) {
             Slog.wtf(TAG, "Failed to obtain wakelock stats from ISuspendControlService", e);
diff --git a/core/java/com/android/internal/os/OWNERS b/core/java/com/android/internal/os/OWNERS
index afc9432..633d093 100644
--- a/core/java/com/android/internal/os/OWNERS
+++ b/core/java/com/android/internal/os/OWNERS
@@ -1 +1 @@
-per-file ZygoteArguments.java,ZygoteConnection.java,ZygoteInit.java,Zygote.java,ZygoteServer.java = [email protected], [email protected], [email protected], [email protected], [email protected]
+per-file *Zygote* = file:/ZYGOTE_OWNERS
diff --git a/core/java/com/android/internal/policy/OWNERS b/core/java/com/android/internal/policy/OWNERS
new file mode 100644
index 0000000..0862c05
--- /dev/null
+++ b/core/java/com/android/internal/policy/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/wm/OWNERS
diff --git a/core/java/com/android/internal/statusbar/OWNERS b/core/java/com/android/internal/statusbar/OWNERS
new file mode 100644
index 0000000..2e96c97
--- /dev/null
+++ b/core/java/com/android/internal/statusbar/OWNERS
@@ -0,0 +1 @@
+include /packages/SystemUI/OWNERS
diff --git a/core/java/com/android/server/backup/PermissionBackupHelper.java b/core/java/com/android/server/backup/PermissionBackupHelper.java
index c7c423b..4d1949e 100644
--- a/core/java/com/android/server/backup/PermissionBackupHelper.java
+++ b/core/java/com/android/server/backup/PermissionBackupHelper.java
@@ -17,8 +17,8 @@
 package com.android.server.backup;
 
 import android.annotation.NonNull;
+import android.annotation.UserIdInt;
 import android.app.backup.BlobBackupHelper;
-import android.os.UserHandle;
 import android.permission.PermissionManagerInternal;
 import android.util.Slog;
 
@@ -34,14 +34,14 @@
     // key under which the permission-grant state blob is committed to backup
     private static final String KEY_PERMISSIONS = "permissions";
 
-    private final @NonNull UserHandle mUser;
+    private final @UserIdInt int mUserId;
 
     private final @NonNull PermissionManagerInternal mPermissionManager;
 
     public PermissionBackupHelper(int userId) {
         super(STATE_VERSION, KEY_PERMISSIONS);
 
-        mUser = UserHandle.of(userId);
+        mUserId = userId;
         mPermissionManager = LocalServices.getService(PermissionManagerInternal.class);
     }
 
@@ -53,7 +53,7 @@
         try {
             switch (key) {
                 case KEY_PERMISSIONS:
-                    return mPermissionManager.backupRuntimePermissions(mUser);
+                    return mPermissionManager.backupRuntimePermissions(mUserId);
 
                 default:
                     Slog.w(TAG, "Unexpected backup key " + key);
@@ -72,7 +72,7 @@
         try {
             switch (key) {
                 case KEY_PERMISSIONS:
-                    mPermissionManager.restoreRuntimePermissions(payload, mUser);
+                    mPermissionManager.restoreRuntimePermissions(payload, mUserId);
                     break;
 
                 default:
diff --git a/core/jni/OWNERS b/core/jni/OWNERS
index 7d80993..bcd1278 100644
--- a/core/jni/OWNERS
+++ b/core/jni/OWNERS
@@ -16,5 +16,21 @@
 per-file android_view_*MotionEvent.* = [email protected], [email protected]
 per-file android_view_PointerIcon.* = [email protected], [email protected]
 
-# Zygote
-per-file com_android_internal_os_Zygote.*,fd_utils.* = [email protected], [email protected], [email protected], [email protected], [email protected]
+per-file *Zygote* = file:/ZYGOTE_OWNERS
+per-file Android.bp = file:platform/build/soong:/OWNERS
+per-file android_animation_* = file:/core/java/android/animation/OWNERS
+per-file android_app_admin_* = file:/core/java/android/app/admin/OWNERS
+per-file android_content_res_* = file:/core/java/android/content/res/OWNERS
+per-file android_graphics_* = file:/graphics/java/android/graphics/OWNERS
+per-file android_hardware_Usb* = file:/services/usb/OWNERS
+per-file android_hardware_display_* = file:/core/java/android/hardware/display/OWNERS
+per-file android_hardware_input_* = file:/core/java/android/hardware/input/OWNERS
+per-file android_hardware_location_* = file:/core/java/android/hardware/location/OWNERS
+per-file android_media_* = file:/media/java/android/media/OWNERS
+per-file android_media_midi_* = file:/media/java/android/media/midi/OWNERS
+per-file android_opengl_* = file:/opengl/java/android/opengl/OWNERS
+per-file android_os_storage_* = file:/core/java/android/os/storage/OWNERS
+per-file android_se_* = file:/core/java/android/se/OWNERS
+per-file android_security_* = file:/core/java/android/security/OWNERS
+per-file android_view_* = file:/core/java/android/view/OWNERS
+per-file com_android_internal_net_* = file:/services/core/java/com/android/server/net/OWNERS
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 618eff0..7cd497e 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -2212,6 +2212,13 @@
     <permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE"
         android:protectionLevel="signature|privileged" />
 
+    <!-- Allows to read device identifiers and use ICC based authentication like EAP-AKA.
+         Often required in authentication to access the carrier's server and manage services
+         of the subscriber.
+         <p>Protection level: signature|appop -->
+    <permission android:name="android.permission.USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER"
+        android:protectionLevel="signature|appop" />
+
     <!-- @SystemApi Allows read access to emergency number information for ongoing calls or SMS
          sessions.
          @hide Used internally. -->
@@ -3962,6 +3969,14 @@
     <permission android:name="android.permission.ACCESS_SURFACE_FLINGER"
         android:protectionLevel="signature" />
 
+    <!-- @SystemApi Allows an application to rotate a surface by arbitrary degree.
+         This is a sub-feature of ACCESS_SURFACE_FLINGER and can be granted in a more concrete way.
+         <p>Not for use by third-party applications.
+         @hide
+    -->
+    <permission android:name="android.permission.ROTATE_SURFACE_FLINGER"
+        android:protectionLevel="signature|recents" />
+
     <!-- Allows an application to take screen shots and more generally
          get access to the frame buffer data.
          <p>Not for use by third-party applications.
diff --git a/core/res/OWNERS b/core/res/OWNERS
new file mode 100644
index 0000000..263d638
--- /dev/null
+++ b/core/res/OWNERS
@@ -0,0 +1,17 @@
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 03e64a4..f4c3063 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -3334,11 +3334,11 @@
 
         <!-- Sets whether this ViewGroup should split MotionEvents
              to separate child views during touch event dispatch.
-             If false (default), touch events will be dispatched to
+             If false (default prior to HONEYCOMB), touch events will be dispatched to
              the child view where the first pointer went down until
              the last pointer goes up.
-             If true, touch events may be dispatched to multiple children.
-             MotionEvents for each pointer will be dispatched to the child
+             If true (default for HONEYCOMB and later), touch events may be dispatched to
+             multiple children. MotionEvents for each pointer will be dispatched to the child
              view where the initial ACTION_DOWN event happened.
              See {@link android.view.ViewGroup#setMotionEventSplittingEnabled(boolean)}
              for more information. -->
diff --git a/core/tests/ConnectivityManagerTest/OWNERS b/core/tests/ConnectivityManagerTest/OWNERS
new file mode 100644
index 0000000..aa87958
--- /dev/null
+++ b/core/tests/ConnectivityManagerTest/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/net/OWNERS
diff --git a/core/tests/PackageInstallerSessions/OWNERS b/core/tests/PackageInstallerSessions/OWNERS
new file mode 100644
index 0000000..d825dfd
--- /dev/null
+++ b/core/tests/PackageInstallerSessions/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/pm/OWNERS
diff --git a/core/tests/benchmarks/src/android/net/OWNERS b/core/tests/benchmarks/src/android/net/OWNERS
new file mode 100644
index 0000000..aa87958
--- /dev/null
+++ b/core/tests/benchmarks/src/android/net/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/net/OWNERS
diff --git a/core/tests/bluetoothtests/OWNERS b/core/tests/bluetoothtests/OWNERS
new file mode 100644
index 0000000..98bb877
--- /dev/null
+++ b/core/tests/bluetoothtests/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/bluetooth/OWNERS
diff --git a/core/tests/coretests/apks/OWNERS b/core/tests/coretests/apks/OWNERS
new file mode 100644
index 0000000..d825dfd
--- /dev/null
+++ b/core/tests/coretests/apks/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/pm/OWNERS
diff --git a/core/tests/coretests/src/android/accessibilityservice/OWNERS b/core/tests/coretests/src/android/accessibilityservice/OWNERS
new file mode 100644
index 0000000..b74281e
--- /dev/null
+++ b/core/tests/coretests/src/android/accessibilityservice/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/view/accessibility/OWNERS
diff --git a/core/tests/coretests/src/android/app/appsearch/external/app/SetSchemaRequestTest.java b/core/tests/coretests/src/android/app/appsearch/external/app/SetSchemaRequestTest.java
new file mode 100644
index 0000000..e03cea3
--- /dev/null
+++ b/core/tests/coretests/src/android/app/appsearch/external/app/SetSchemaRequestTest.java
@@ -0,0 +1,65 @@
+/*
+ * 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.
+ */
+
+package android.app.appsearch;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.testng.Assert.expectThrows;
+
+import org.junit.Test;
+
+public class SetSchemaRequestTest {
+
+    @Test
+    public void testInvalidSchemaReferences() {
+        IllegalArgumentException expected =
+                expectThrows(
+                        IllegalArgumentException.class,
+                        () ->
+                                new SetSchemaRequest.Builder()
+                                        .setSchemaTypeVisibilityForSystemUi(false, "InvalidSchema")
+                                        .build());
+        assertThat(expected).hasMessageThat().contains("referenced, but were not added");
+    }
+
+    @Test
+    public void testSchemaTypeVisibilityForSystemUi_Visible() {
+        AppSearchSchema schema = new AppSearchSchema.Builder("Schema").build();
+
+        // By default, the schema is visible.
+        SetSchemaRequest request = new SetSchemaRequest.Builder().addSchema(schema).build();
+        assertThat(request.getSchemasNotPlatformSurfaceable()).isEmpty();
+
+        request =
+                new SetSchemaRequest.Builder()
+                        .addSchema(schema)
+                        .setSchemaTypeVisibilityForSystemUi(true, "Schema")
+                        .build();
+        assertThat(request.getSchemasNotPlatformSurfaceable()).isEmpty();
+    }
+
+    @Test
+    public void testSchemaTypeVisibilityForSystemUi_NotVisible() {
+        AppSearchSchema schema = new AppSearchSchema.Builder("Schema").build();
+        SetSchemaRequest request =
+                new SetSchemaRequest.Builder()
+                        .addSchema(schema)
+                        .setSchemaTypeVisibilityForSystemUi(false, "Schema")
+                        .build();
+        assertThat(request.getSchemasNotPlatformSurfaceable()).containsExactly("Schema");
+    }
+}
diff --git a/core/tests/coretests/src/android/app/appsearch/external/app/cts/AppSearchSchemaCtsTest.java b/core/tests/coretests/src/android/app/appsearch/external/app/cts/AppSearchSchemaCtsTest.java
index 2eaebd6..7072a81 100644
--- a/core/tests/coretests/src/android/app/appsearch/external/app/cts/AppSearchSchemaCtsTest.java
+++ b/core/tests/coretests/src/android/app/appsearch/external/app/cts/AppSearchSchemaCtsTest.java
@@ -78,4 +78,125 @@
                                                 .build()));
         assertThat(e).hasMessageThat().contains("Property defined more than once: subject");
     }
+
+    @Test
+    public void testEquals_identical() {
+        AppSearchSchema schema1 =
+                new AppSearchSchema.Builder("Email")
+                        .addProperty(
+                                new PropertyConfig.Builder("subject")
+                                        .setDataType(PropertyConfig.DATA_TYPE_STRING)
+                                        .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL)
+                                        .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES)
+                                        .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN)
+                                        .build())
+                        .build();
+        AppSearchSchema schema2 =
+                new AppSearchSchema.Builder("Email")
+                        .addProperty(
+                                new PropertyConfig.Builder("subject")
+                                        .setDataType(PropertyConfig.DATA_TYPE_STRING)
+                                        .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL)
+                                        .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES)
+                                        .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN)
+                                        .build())
+                        .build();
+        assertThat(schema1).isEqualTo(schema2);
+        assertThat(schema1.hashCode()).isEqualTo(schema2.hashCode());
+    }
+
+    @Test
+    public void testEquals_differentOrder() {
+        AppSearchSchema schema1 =
+                new AppSearchSchema.Builder("Email")
+                        .addProperty(
+                                new PropertyConfig.Builder("subject")
+                                        .setDataType(PropertyConfig.DATA_TYPE_STRING)
+                                        .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL)
+                                        .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES)
+                                        .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN)
+                                        .build())
+                        .build();
+        AppSearchSchema schema2 =
+                new AppSearchSchema.Builder("Email")
+                        .addProperty(
+                                new PropertyConfig.Builder("subject")
+                                        .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN)
+                                        .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES)
+                                        .setDataType(PropertyConfig.DATA_TYPE_STRING)
+                                        .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL)
+                                        .build())
+                        .build();
+        assertThat(schema1).isEqualTo(schema2);
+        assertThat(schema1.hashCode()).isEqualTo(schema2.hashCode());
+    }
+
+    @Test
+    public void testEquals_failure() {
+        AppSearchSchema schema1 =
+                new AppSearchSchema.Builder("Email")
+                        .addProperty(
+                                new PropertyConfig.Builder("subject")
+                                        .setDataType(PropertyConfig.DATA_TYPE_STRING)
+                                        .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL)
+                                        .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES)
+                                        .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN)
+                                        .build())
+                        .build();
+        AppSearchSchema schema2 =
+                new AppSearchSchema.Builder("Email")
+                        .addProperty(
+                                new PropertyConfig.Builder("subject")
+                                        .setDataType(PropertyConfig.DATA_TYPE_STRING)
+                                        .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL)
+                                        .setIndexingType(
+                                                PropertyConfig
+                                                        .INDEXING_TYPE_EXACT_TERMS) // Different
+                                        .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN)
+                                        .build())
+                        .build();
+        assertThat(schema1).isNotEqualTo(schema2);
+        assertThat(schema1.hashCode()).isNotEqualTo(schema2.hashCode());
+    }
+
+    @Test
+    public void testEquals_failure_differentOrder() {
+        AppSearchSchema schema1 =
+                new AppSearchSchema.Builder("Email")
+                        .addProperty(
+                                new PropertyConfig.Builder("subject")
+                                        .setDataType(PropertyConfig.DATA_TYPE_STRING)
+                                        .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL)
+                                        .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES)
+                                        .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN)
+                                        .build())
+                        .addProperty(
+                                new PropertyConfig.Builder("body")
+                                        .setDataType(PropertyConfig.DATA_TYPE_STRING)
+                                        .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL)
+                                        .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES)
+                                        .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN)
+                                        .build())
+                        .build();
+        // Order of 'body' and 'subject' has been switched
+        AppSearchSchema schema2 =
+                new AppSearchSchema.Builder("Email")
+                        .addProperty(
+                                new PropertyConfig.Builder("body")
+                                        .setDataType(PropertyConfig.DATA_TYPE_STRING)
+                                        .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL)
+                                        .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES)
+                                        .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN)
+                                        .build())
+                        .addProperty(
+                                new PropertyConfig.Builder("subject")
+                                        .setDataType(PropertyConfig.DATA_TYPE_STRING)
+                                        .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL)
+                                        .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES)
+                                        .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN)
+                                        .build())
+                        .build();
+        assertThat(schema1).isNotEqualTo(schema2);
+        assertThat(schema1.hashCode()).isNotEqualTo(schema2.hashCode());
+    }
 }
diff --git a/core/tests/coretests/src/android/app/appsearch/external/util/BundleUtilTest.java b/core/tests/coretests/src/android/app/appsearch/external/util/BundleUtilTest.java
new file mode 100644
index 0000000..cfcfcc8
--- /dev/null
+++ b/core/tests/coretests/src/android/app/appsearch/external/util/BundleUtilTest.java
@@ -0,0 +1,254 @@
+/*
+ * 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.
+ */
+
+package android.app.appsearch.util;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.os.Build;
+import android.os.Bundle;
+import android.os.ParcelUuid;
+import android.os.Parcelable;
+import android.util.Size;
+import android.util.SizeF;
+import android.util.SparseArray;
+
+import com.google.common.collect.ImmutableList;
+
+import org.junit.Test;
+
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.UUID;
+
+public class BundleUtilTest {
+    @Test
+    public void testDeepEquals_self() {
+        Bundle one = new Bundle();
+        one.putString("a", "a");
+        assertThat(BundleUtil.deepEquals(one, one)).isTrue();
+    }
+
+    @Test
+    public void testDeepEquals_simple() {
+        Bundle one = new Bundle();
+        one.putString("a", "a");
+
+        Bundle two = new Bundle();
+        two.putString("a", "a");
+
+        assertThat(one).isNotEqualTo(two);
+        assertThat(BundleUtil.deepEquals(one, two)).isTrue();
+    }
+
+    @Test
+    public void testDeepEquals_keyMismatch() {
+        Bundle one = new Bundle();
+        one.putString("a", "a");
+
+        Bundle two = new Bundle();
+        two.putString("a", "a");
+        two.putString("b", "b");
+        assertThat(BundleUtil.deepEquals(one, two)).isFalse();
+    }
+
+    @Test
+    public void testDeepEquals_thorough_equal() {
+        Bundle[] inputs = new Bundle[2];
+        for (int i = 0; i < 2; i++) {
+            inputs[i] = createThoroughBundle();
+        }
+        assertThat(inputs[0]).isNotEqualTo(inputs[1]);
+        assertThat(BundleUtil.deepEquals(inputs[0], inputs[1])).isTrue();
+    }
+
+    @Test
+    public void testDeepEquals_thorough_notEqual() {
+        Bundle[] inputs = new Bundle[2];
+        for (int i = 0; i < 2; i++) {
+            Bundle b = createThoroughBundle();
+            // Create a difference
+            assertThat(b.containsKey("doubleArray")).isTrue();
+            b.putDoubleArray("doubleArray", new double[] {18., i});
+            inputs[i] = b;
+        }
+        assertThat(inputs[0]).isNotEqualTo(inputs[1]);
+        assertThat(BundleUtil.deepEquals(inputs[0], inputs[1])).isFalse();
+    }
+
+    @Test
+    public void testDeepEquals_nestedNotEquals() {
+        Bundle one = new Bundle();
+        one.putString("a", "a");
+        Bundle two = new Bundle();
+        two.putBundle("b", one);
+        Bundle twoClone = new Bundle();
+        twoClone.putBundle("b", one);
+        Bundle three = new Bundle();
+        three.putBundle("b", two);
+
+        ArrayList<Bundle> listOne = new ArrayList<>(ImmutableList.of(one, two, three));
+        ArrayList<Bundle> listOneClone = new ArrayList<>(ImmutableList.of(one, twoClone, three));
+        ArrayList<Bundle> listTwo = new ArrayList<>(ImmutableList.of(one, three, two));
+        Bundle b1 = new Bundle();
+        b1.putParcelableArrayList("key", listOne);
+        Bundle b1Clone = new Bundle();
+        b1Clone.putParcelableArrayList("key", listOneClone);
+        Bundle b2 = new Bundle();
+        b2.putParcelableArrayList("key", listTwo);
+
+        assertThat(b1).isNotEqualTo(b1Clone);
+        assertThat(BundleUtil.deepEquals(b1, b1Clone)).isTrue();
+        assertThat(BundleUtil.deepEquals(b1, b2)).isFalse();
+        assertThat(BundleUtil.deepEquals(b1Clone, b2)).isFalse();
+    }
+
+    @Test
+    public void testDeepEquals_sparseArray() {
+        Parcelable parcelable1 = new ParcelUuid(UUID.randomUUID());
+        Parcelable parcelable2 = new ParcelUuid(UUID.randomUUID());
+        Parcelable parcelable3 = new ParcelUuid(UUID.randomUUID());
+
+        SparseArray<Parcelable> array1 = new SparseArray<>();
+        array1.put(1, parcelable1);
+        array1.put(10, parcelable2);
+
+        SparseArray<Parcelable> array1Clone = new SparseArray<>();
+        array1Clone.put(1, parcelable1);
+        array1Clone.put(10, parcelable2);
+
+        SparseArray<Parcelable> array2 = new SparseArray<>();
+        array2.put(1, parcelable1);
+        array2.put(10, parcelable3); // Different
+
+        Bundle b1 = new Bundle();
+        b1.putSparseParcelableArray("array1", array1);
+        Bundle b1Clone = new Bundle();
+        b1Clone.putSparseParcelableArray("array1", array1Clone);
+        Bundle b2 = new Bundle();
+        b2.putSparseParcelableArray("array1", array2);
+
+        assertThat(b1).isNotEqualTo(b1Clone);
+        assertThat(BundleUtil.deepEquals(b1, b1Clone)).isTrue();
+        assertThat(BundleUtil.deepEquals(b1, b2)).isFalse();
+        assertThat(BundleUtil.deepEquals(b1Clone, b2)).isFalse();
+    }
+
+    @Test
+    public void testDeepHashCode_same() {
+        Bundle[] inputs = new Bundle[2];
+        for (int i = 0; i < 2; i++) {
+            inputs[i] = createThoroughBundle();
+        }
+        assertThat(BundleUtil.deepHashCode(inputs[0]))
+                .isEqualTo(BundleUtil.deepHashCode(inputs[1]));
+    }
+
+    @Test
+    public void testDeepHashCode_different() {
+        Bundle[] inputs = new Bundle[2];
+        for (int i = 0; i < 2; i++) {
+            Bundle b = createThoroughBundle();
+            // Create a difference
+            assertThat(b.containsKey("doubleArray")).isTrue();
+            b.putDoubleArray("doubleArray", new double[] {18., i});
+            inputs[i] = b;
+        }
+        assertThat(BundleUtil.deepHashCode(inputs[0]))
+                .isNotEqualTo(BundleUtil.deepHashCode(inputs[1]));
+    }
+
+    @Test
+    public void testHashCode_sparseArray() {
+        Parcelable parcelable1 = new ParcelUuid(UUID.randomUUID());
+        Parcelable parcelable2 = new ParcelUuid(UUID.randomUUID());
+        Parcelable parcelable3 = new ParcelUuid(UUID.randomUUID());
+
+        SparseArray<Parcelable> array1 = new SparseArray<>();
+        array1.put(1, parcelable1);
+        array1.put(10, parcelable2);
+
+        SparseArray<Parcelable> array1Clone = new SparseArray<>();
+        array1Clone.put(1, parcelable1);
+        array1Clone.put(10, parcelable2);
+
+        SparseArray<Parcelable> array2 = new SparseArray<>();
+        array2.put(1, parcelable1);
+        array2.put(10, parcelable3); // Different
+
+        Bundle b1 = new Bundle();
+        b1.putSparseParcelableArray("array1", array1);
+        Bundle b1Clone = new Bundle();
+        b1Clone.putSparseParcelableArray("array1", array1Clone);
+        Bundle b2 = new Bundle();
+        b2.putSparseParcelableArray("array1", array2);
+
+        assertThat(b1.hashCode()).isNotEqualTo(b1Clone.hashCode());
+        assertThat(BundleUtil.deepHashCode(b1)).isEqualTo(BundleUtil.deepHashCode(b1Clone));
+        assertThat(BundleUtil.deepHashCode(b1)).isNotEqualTo(BundleUtil.deepHashCode(b2));
+    }
+
+    private static Bundle createThoroughBundle() {
+        Bundle toy1 = new Bundle();
+        toy1.putString("a", "a");
+        Bundle toy2 = new Bundle();
+        toy2.putInt("b", 2);
+
+        Bundle b = new Bundle();
+        // BaseBundle stuff
+        b.putBoolean("boolean", true);
+        b.putByte("byte", (byte) 1);
+        b.putChar("char", 'a');
+        b.putShort("short", (short) 2);
+        b.putInt("int", 3);
+        b.putLong("long", 4L);
+        b.putFloat("float", 5f);
+        b.putDouble("double", 6f);
+        b.putString("string", "b");
+        b.putCharSequence("charSequence", "c");
+        b.putIntegerArrayList("integerArrayList", new ArrayList<>(ImmutableList.of(7, 8)));
+        b.putStringArrayList("stringArrayList", new ArrayList<>(ImmutableList.of("d", "e")));
+        b.putCharSequenceArrayList(
+                "charSequenceArrayList", new ArrayList<>(ImmutableList.of("f", "g")));
+        b.putSerializable("serializable", new BigDecimal(9));
+        b.putBooleanArray("booleanArray", new boolean[] {true, false, true});
+        b.putByteArray("byteArray", new byte[] {(byte) 10, (byte) 11});
+        b.putShortArray("shortArray", new short[] {(short) 12, (short) 13});
+        b.putCharArray("charArray", new char[] {'h', 'i'});
+        b.putLongArray("longArray", new long[] {14L, 15L});
+        b.putFloatArray("floatArray", new float[] {16f, 17f});
+        b.putDoubleArray("doubleArray", new double[] {18., 19.});
+        b.putStringArray("stringArray", new String[] {"j", "k"});
+        b.putCharSequenceArray("charSequenceArrayList", new CharSequence[] {"l", "m"});
+
+        // Bundle stuff
+        b.putParcelable("parcelable", toy1);
+        if (Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
+            b.putSize("size", new Size(20, 21));
+            b.putSizeF("sizeF", new SizeF(22f, 23f));
+        }
+        b.putParcelableArray("parcelableArray", new Parcelable[] {toy1, toy2});
+        b.putParcelableArrayList(
+                "parcelableArrayList", new ArrayList<>(ImmutableList.of(toy1, toy2)));
+        SparseArray<Parcelable> sparseArray = new SparseArray<>();
+        sparseArray.put(24, toy1);
+        sparseArray.put(1025, toy2);
+        b.putSparseParcelableArray("sparceParcelableArray", sparseArray);
+        b.putBundle("bundle", toy1);
+
+        return b;
+    }
+}
diff --git a/core/tests/coretests/src/android/database/OWNERS b/core/tests/coretests/src/android/database/OWNERS
new file mode 100644
index 0000000..bb9a2ca
--- /dev/null
+++ b/core/tests/coretests/src/android/database/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/database/OWNERS
diff --git a/core/tests/coretests/src/android/net/OWNERS b/core/tests/coretests/src/android/net/OWNERS
new file mode 100644
index 0000000..aa87958
--- /dev/null
+++ b/core/tests/coretests/src/android/net/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/net/OWNERS
diff --git a/core/tests/coretests/src/com/android/internal/accessibility/OWNERS b/core/tests/coretests/src/com/android/internal/accessibility/OWNERS
new file mode 100644
index 0000000..b74281e
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/accessibility/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/view/accessibility/OWNERS
diff --git a/core/tests/coretests/src/com/android/internal/inputmethod/OWNERS b/core/tests/coretests/src/com/android/internal/inputmethod/OWNERS
new file mode 100644
index 0000000..5deb2ce
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/inputmethod/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/view/inputmethod/OWNERS
diff --git a/core/tests/coretests/src/com/android/internal/policy/OWNERS b/core/tests/coretests/src/com/android/internal/policy/OWNERS
new file mode 100644
index 0000000..0862c05
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/policy/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/wm/OWNERS
diff --git a/core/tests/coretests/src/com/android/internal/power/OWNERS b/core/tests/coretests/src/com/android/internal/power/OWNERS
new file mode 100644
index 0000000..d68066b
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/power/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/power/OWNERS
diff --git a/core/tests/coretests/src/com/android/internal/statusbar/OWNERS b/core/tests/coretests/src/com/android/internal/statusbar/OWNERS
new file mode 100644
index 0000000..2e96c97
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/statusbar/OWNERS
@@ -0,0 +1 @@
+include /packages/SystemUI/OWNERS
diff --git a/core/tests/devicestatetests/src/android/hardware/devicestate/OWNERS b/core/tests/devicestatetests/src/android/hardware/devicestate/OWNERS
new file mode 100644
index 0000000..d9b0e2e
--- /dev/null
+++ b/core/tests/devicestatetests/src/android/hardware/devicestate/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/devicestate/OWNERS
diff --git a/core/tests/hdmitests/OWNERS b/core/tests/hdmitests/OWNERS
new file mode 100644
index 0000000..c3c47ed
--- /dev/null
+++ b/core/tests/hdmitests/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/hardware/hdmi/OWNERS
diff --git a/core/tests/hosttests/test-apps/OWNERS b/core/tests/hosttests/test-apps/OWNERS
new file mode 100644
index 0000000..d825dfd
--- /dev/null
+++ b/core/tests/hosttests/test-apps/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/pm/OWNERS
diff --git a/core/tests/notificationtests/OWNERS b/core/tests/notificationtests/OWNERS
new file mode 100644
index 0000000..396fd12
--- /dev/null
+++ b/core/tests/notificationtests/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/notification/OWNERS
diff --git a/core/tests/overlaytests/OWNERS b/core/tests/overlaytests/OWNERS
new file mode 100644
index 0000000..afb98d4
--- /dev/null
+++ b/core/tests/overlaytests/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/content/om/OWNERS
diff --git a/core/tests/overlaytests/remount/TEST_MAPPING b/core/tests/overlaytests/remount/TEST_MAPPING
index 54dd431..22b28b5 100644
--- a/core/tests/overlaytests/remount/TEST_MAPPING
+++ b/core/tests/overlaytests/remount/TEST_MAPPING
@@ -1,7 +1,7 @@
 {
-  "presubmit": [
+  "presubmit-large": [
     {
       "name" : "OverlayRemountedTest"
     }
   ]
-}
\ No newline at end of file
+}
diff --git a/core/tests/packagemanagertests/OWNERS b/core/tests/packagemanagertests/OWNERS
new file mode 100644
index 0000000..d825dfd
--- /dev/null
+++ b/core/tests/packagemanagertests/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/pm/OWNERS
diff --git a/core/tests/powertests/OWNERS b/core/tests/powertests/OWNERS
new file mode 100644
index 0000000..d68066b
--- /dev/null
+++ b/core/tests/powertests/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/power/OWNERS
diff --git a/data/etc/OWNERS b/data/etc/OWNERS
index 70d4678..5efd0bd 100644
--- a/data/etc/OWNERS
+++ b/data/etc/OWNERS
@@ -1 +1,13 @@
-per-file privapp-permissions-platform.xml = [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
diff --git a/data/etc/car/OWNERS b/data/etc/car/OWNERS
new file mode 100644
index 0000000..09e257c
--- /dev/null
+++ b/data/etc/car/OWNERS
@@ -0,0 +1 @@
+include platform/packages/services/Car:/OWNERS
diff --git a/data/fonts/OWNERS b/data/fonts/OWNERS
new file mode 100644
index 0000000..a538331
--- /dev/null
+++ b/data/fonts/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/graphics/fonts/OWNERS
diff --git a/drm/java/android/drm/OWNERS b/drm/java/android/drm/OWNERS
new file mode 100644
index 0000000..4387100
--- /dev/null
+++ b/drm/java/android/drm/OWNERS
@@ -0,0 +1,4 @@
+# Bug component: 49079
+
[email protected]
[email protected]
diff --git a/errorprone/OWNERS b/errorprone/OWNERS
new file mode 100644
index 0000000..bddbdb3
--- /dev/null
+++ b/errorprone/OWNERS
@@ -0,0 +1,2 @@
[email protected]
[email protected]
diff --git a/graphics/OWNERS b/graphics/OWNERS
new file mode 100644
index 0000000..a6d1bc3
--- /dev/null
+++ b/graphics/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/graphics/OWNERS
diff --git a/graphics/java/android/graphics/OWNERS b/graphics/java/android/graphics/OWNERS
new file mode 100644
index 0000000..6196889
--- /dev/null
+++ b/graphics/java/android/graphics/OWNERS
@@ -0,0 +1,6 @@
+# Bug component: 24939
+
[email protected]
[email protected]
[email protected]
[email protected]
diff --git a/graphics/java/android/graphics/drawable/OWNERS b/graphics/java/android/graphics/drawable/OWNERS
new file mode 100644
index 0000000..6196889
--- /dev/null
+++ b/graphics/java/android/graphics/drawable/OWNERS
@@ -0,0 +1,6 @@
+# Bug component: 24939
+
[email protected]
[email protected]
[email protected]
[email protected]
diff --git a/graphics/java/android/graphics/drawable/shapes/OWNERS b/graphics/java/android/graphics/drawable/shapes/OWNERS
new file mode 100644
index 0000000..6196889
--- /dev/null
+++ b/graphics/java/android/graphics/drawable/shapes/OWNERS
@@ -0,0 +1,6 @@
+# Bug component: 24939
+
[email protected]
[email protected]
[email protected]
[email protected]
diff --git a/graphics/java/android/graphics/fonts/OWNERS b/graphics/java/android/graphics/fonts/OWNERS
new file mode 100644
index 0000000..e0a354e
--- /dev/null
+++ b/graphics/java/android/graphics/fonts/OWNERS
@@ -0,0 +1,5 @@
+# Bug component: 24939
+
[email protected]
[email protected]
[email protected]
diff --git a/graphics/java/android/graphics/pdf/OWNERS b/graphics/java/android/graphics/pdf/OWNERS
new file mode 100644
index 0000000..f04e200
--- /dev/null
+++ b/graphics/java/android/graphics/pdf/OWNERS
@@ -0,0 +1,8 @@
+# Bug component: 24939
+
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
diff --git a/graphics/java/android/graphics/text/OWNERS b/graphics/java/android/graphics/text/OWNERS
new file mode 100644
index 0000000..e0a354e
--- /dev/null
+++ b/graphics/java/android/graphics/text/OWNERS
@@ -0,0 +1,5 @@
+# Bug component: 24939
+
[email protected]
[email protected]
[email protected]
diff --git a/keystore/java/android/security/IKeyChainService.aidl b/keystore/java/android/security/IKeyChainService.aidl
index add52fa..a9d4094 100644
--- a/keystore/java/android/security/IKeyChainService.aidl
+++ b/keystore/java/android/security/IKeyChainService.aidl
@@ -49,6 +49,7 @@
         in byte[] privateKey, in byte[] userCert, in byte[] certChain, String alias, int uid);
     boolean removeKeyPair(String alias);
     boolean containsKeyPair(String alias);
+    int[] getGrants(String alias);
 
     // APIs used by Settings
     boolean deleteCaCertificate(String alias);
diff --git a/libs/WindowManager/OWNERS b/libs/WindowManager/OWNERS
index 063d459..2c61df9 100644
--- a/libs/WindowManager/OWNERS
+++ b/libs/WindowManager/OWNERS
@@ -1,3 +1,3 @@
 set noparent
 
-include ../../services/core/java/com/android/server/wm/OWNERS
\ No newline at end of file
+include /services/core/java/com/android/server/wm/OWNERS
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitWindowManager.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitWindowManager.java
index 542867d..e412198 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitWindowManager.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitWindowManager.java
@@ -22,6 +22,7 @@
 import static android.view.WindowManager.LayoutParams.FLAG_SPLIT_TOUCH;
 import static android.view.WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY;
 import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
 
 import android.content.Context;
@@ -89,7 +90,7 @@
                 PixelFormat.TRANSLUCENT);
         lp.token = new Binder();
         lp.setTitle(DIVIDER_WINDOW_TITLE);
-        lp.privateFlags |= PRIVATE_FLAG_NO_MOVE_ANIMATION;
+        lp.privateFlags |= PRIVATE_FLAG_NO_MOVE_ANIMATION | PRIVATE_FLAG_TRUSTED_OVERLAY;
         mViewHost.setView(dividerView, lp);
         dividerView.setup(splitLayout, mViewHost, null /* dragListener */);
     }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java
index 625c0a7..a89c8bb 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java
@@ -54,7 +54,6 @@
 import com.android.wm.shell.protolog.ShellProtoLogGroup;
 import com.android.wm.shell.splitscreen.SplitScreen;
 
-import java.util.Objects;
 import java.util.Optional;
 
 /**
@@ -108,16 +107,22 @@
         DragLayout dragLayout = new DragLayout(context, mSplitScreen);
         rootView.addView(dragLayout,
                 new FrameLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT));
-        wm.addView(rootView, layoutParams);
-
-        mDisplayDropTargets.put(displayId,
-                new PerDisplay(displayId, context, wm, rootView, dragLayout));
+        try {
+            wm.addView(rootView, layoutParams);
+            mDisplayDropTargets.put(displayId,
+                    new PerDisplay(displayId, context, wm, rootView, dragLayout));
+        } catch (WindowManager.InvalidDisplayException e) {
+            Slog.w(TAG, "Unable to add view for display id: " + displayId);
+        }
     }
 
     @Override
     public void onDisplayConfigurationChanged(int displayId, Configuration newConfig) {
         ProtoLog.v(ShellProtoLogGroup.WM_SHELL_DRAG_AND_DROP, "Display changed: %d", displayId);
         final PerDisplay pd = mDisplayDropTargets.get(displayId);
+        if (pd == null) {
+            return;
+        }
         pd.rootView.requestApplyInsets();
     }
 
@@ -125,6 +130,9 @@
     public void onDisplayRemoved(int displayId) {
         ProtoLog.v(ShellProtoLogGroup.WM_SHELL_DRAG_AND_DROP, "Display removed: %d", displayId);
         final PerDisplay pd = mDisplayDropTargets.get(displayId);
+        if (pd == null) {
+            return;
+        }
         pd.wm.removeViewImmediate(pd.rootView);
         mDisplayDropTargets.remove(displayId);
     }
@@ -139,6 +147,10 @@
         final PerDisplay pd = mDisplayDropTargets.get(displayId);
         final ClipDescription description = event.getClipDescription();
 
+        if (pd == null) {
+            return false;
+        }
+
         if (event.getAction() == ACTION_DRAG_STARTED) {
             final boolean hasValidClipData = event.getClipData().getItemCount() > 0
                     && (description.hasMimeType(MIMETYPE_APPLICATION_ACTIVITY)
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PinnedStackListenerForwarder.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PinnedStackListenerForwarder.java
index 5593268..d59aec2 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PinnedStackListenerForwarder.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PinnedStackListenerForwarder.java
@@ -20,7 +20,6 @@
 import android.content.ComponentName;
 import android.content.pm.ParceledListSlice;
 import android.os.RemoteException;
-import android.view.DisplayInfo;
 import android.view.IPinnedStackListener;
 import android.view.WindowManagerGlobal;
 
@@ -85,18 +84,6 @@
         }
     }
 
-    private void onDisplayInfoChanged(DisplayInfo displayInfo) {
-        for (PinnedStackListener listener : mListeners) {
-            listener.onDisplayInfoChanged(displayInfo);
-        }
-    }
-
-    private void onConfigurationChanged() {
-        for (PinnedStackListener listener : mListeners) {
-            listener.onConfigurationChanged();
-        }
-    }
-
     private void onAspectRatioChanged(float aspectRatio) {
         for (PinnedStackListener listener : mListeners) {
             listener.onAspectRatioChanged(aspectRatio);
@@ -134,20 +121,6 @@
         }
 
         @Override
-        public void onDisplayInfoChanged(DisplayInfo displayInfo) {
-            mShellMainExecutor.execute(() -> {
-                PinnedStackListenerForwarder.this.onDisplayInfoChanged(displayInfo);
-            });
-        }
-
-        @Override
-        public void onConfigurationChanged() {
-            mShellMainExecutor.execute(() -> {
-                PinnedStackListenerForwarder.this.onConfigurationChanged();
-            });
-        }
-
-        @Override
         public void onAspectRatioChanged(float aspectRatio) {
             mShellMainExecutor.execute(() -> {
                 PinnedStackListenerForwarder.this.onAspectRatioChanged(aspectRatio);
@@ -168,10 +141,6 @@
 
         public void onActivityHidden(ComponentName componentName) {}
 
-        public void onDisplayInfoChanged(DisplayInfo displayInfo) {}
-
-        public void onConfigurationChanged() {}
-
         public void onAspectRatioChanged(float aspectRatio) {}
     }
 }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/Pip.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/Pip.java
index da9ce0a..1f07542 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/Pip.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/Pip.java
@@ -20,6 +20,7 @@
 import android.app.PictureInPictureParams;
 import android.content.ComponentName;
 import android.content.pm.ActivityInfo;
+import android.content.res.Configuration;
 import android.graphics.Rect;
 
 import com.android.wm.shell.common.annotations.ExternalThread;
@@ -82,6 +83,12 @@
     }
 
     /**
+     * Called when configuration is changed.
+     */
+    default void onConfigurationChanged(Configuration newConfig) {
+    }
+
+    /**
      * Called when display size or font size of settings changed
      */
     default void onDensityOrFontScaleChanged() {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java
index d829462..fe01811 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java
@@ -54,6 +54,7 @@
     public static final int TRANSITION_DIRECTION_LEAVE_PIP = 3;
     public static final int TRANSITION_DIRECTION_LEAVE_PIP_TO_SPLIT_SCREEN = 4;
     public static final int TRANSITION_DIRECTION_REMOVE_STACK = 5;
+    public static final int TRANSITION_DIRECTION_SNAP_AFTER_RESIZE = 6;
 
     @IntDef(prefix = { "TRANSITION_DIRECTION_" }, value = {
             TRANSITION_DIRECTION_NONE,
@@ -61,7 +62,8 @@
             TRANSITION_DIRECTION_TO_PIP,
             TRANSITION_DIRECTION_LEAVE_PIP,
             TRANSITION_DIRECTION_LEAVE_PIP_TO_SPLIT_SCREEN,
-            TRANSITION_DIRECTION_REMOVE_STACK
+            TRANSITION_DIRECTION_REMOVE_STACK,
+            TRANSITION_DIRECTION_SNAP_AFTER_RESIZE
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface TransitionDirection {}
@@ -109,13 +111,27 @@
     }
 
     @SuppressWarnings("unchecked")
+    /**
+     * Construct and return an animator that animates from the {@param startBounds} to the
+     * {@param endBounds} with the given {@param direction}. If {@param direction} is type
+     * {@link ANIM_TYPE_BOUNDS}, then {@param sourceHintRect} will be used to animate
+     * in a better, more smooth manner.
+     *
+     * In the case where one wants to start animation during an intermediate animation (for example,
+     * if the user is currently doing a pinch-resize, and upon letting go now PiP needs to animate
+     * to the correct snap fraction region), then provide the base bounds, which is current PiP
+     * leash bounds before transformation/any animation. This is so when we try to construct
+     * the different transformation matrices for the animation, we are constructing this based off
+     * the PiP original bounds, rather than the {@param startBounds}, which is post-transformed.
+     */
     @VisibleForTesting
-    public PipTransitionAnimator getAnimator(SurfaceControl leash, Rect startBounds, Rect endBounds,
-            Rect sourceHintRect, @PipAnimationController.TransitionDirection int direction) {
+    public PipTransitionAnimator getAnimator(SurfaceControl leash, Rect baseBounds,
+            Rect startBounds, Rect endBounds, Rect sourceHintRect,
+            @PipAnimationController.TransitionDirection int direction) {
         if (mCurrentAnimator == null) {
             mCurrentAnimator = setupPipTransitionAnimator(
-                    PipTransitionAnimator.ofBounds(leash, startBounds, endBounds, sourceHintRect,
-                            direction));
+                    PipTransitionAnimator.ofBounds(leash, startBounds, startBounds, endBounds,
+                            sourceHintRect, direction));
         } else if (mCurrentAnimator.getAnimationType() == ANIM_TYPE_ALPHA
                 && mCurrentAnimator.isRunning()) {
             // If we are still animating the fade into pip, then just move the surface and ensure
@@ -130,8 +146,8 @@
         } else {
             mCurrentAnimator.cancel();
             mCurrentAnimator = setupPipTransitionAnimator(
-                    PipTransitionAnimator.ofBounds(leash, startBounds, endBounds, sourceHintRect,
-                            direction));
+                    PipTransitionAnimator.ofBounds(leash, baseBounds, startBounds, endBounds,
+                            sourceHintRect, direction));
         }
         return mCurrentAnimator;
     }
@@ -180,6 +196,7 @@
         private final @AnimationType int mAnimationType;
         private final Rect mDestinationBounds = new Rect();
 
+        private T mBaseValue;
         protected T mCurrentValue;
         protected T mStartValue;
         private T mEndValue;
@@ -190,10 +207,11 @@
         private @TransitionDirection int mTransitionDirection;
 
         private PipTransitionAnimator(SurfaceControl leash, @AnimationType int animationType,
-                Rect destinationBounds, T startValue, T endValue) {
+                Rect destinationBounds, T baseValue, T startValue, T endValue) {
             mLeash = leash;
             mAnimationType = animationType;
             mDestinationBounds.set(destinationBounds);
+            mBaseValue = baseValue;
             mStartValue = startValue;
             mEndValue = endValue;
             addListener(this);
@@ -263,6 +281,10 @@
             return mStartValue;
         }
 
+        T getBaseValue() {
+            return mBaseValue;
+        }
+
         @VisibleForTesting
         public T getEndValue() {
             return mEndValue;
@@ -334,7 +356,7 @@
         static PipTransitionAnimator<Float> ofAlpha(SurfaceControl leash,
                 Rect destinationBounds, float startValue, float endValue) {
             return new PipTransitionAnimator<Float>(leash, ANIM_TYPE_ALPHA,
-                    destinationBounds, startValue, endValue) {
+                    destinationBounds, startValue, startValue, endValue) {
                 @Override
                 void applySurfaceControlTransaction(SurfaceControl leash,
                         SurfaceControl.Transaction tx, float fraction) {
@@ -367,7 +389,7 @@
         }
 
         static PipTransitionAnimator<Rect> ofBounds(SurfaceControl leash,
-                Rect startValue, Rect endValue, Rect sourceHintRect,
+                Rect baseValue, Rect startValue, Rect endValue, Rect sourceHintRect,
                 @PipAnimationController.TransitionDirection int direction) {
             // Just for simplicity we'll interpolate between the source rect hint insets and empty
             // insets to calculate the window crop
@@ -375,7 +397,7 @@
             if (isOutPipDirection(direction)) {
                 initialSourceValue = new Rect(endValue);
             } else {
-                initialSourceValue = new Rect(startValue);
+                initialSourceValue = new Rect(baseValue);
             }
 
             final Rect sourceHintRectInsets;
@@ -391,22 +413,24 @@
 
             // construct new Rect instances in case they are recycled
             return new PipTransitionAnimator<Rect>(leash, ANIM_TYPE_BOUNDS,
-                    endValue, new Rect(startValue), new Rect(endValue)) {
+                    endValue, new Rect(baseValue), new Rect(startValue), new Rect(endValue)) {
                 private final RectEvaluator mRectEvaluator = new RectEvaluator(new Rect());
                 private final RectEvaluator mInsetsEvaluator = new RectEvaluator(new Rect());
 
                 @Override
                 void applySurfaceControlTransaction(SurfaceControl leash,
                         SurfaceControl.Transaction tx, float fraction) {
+                    final Rect base = getBaseValue();
                     final Rect start = getStartValue();
                     final Rect end = getEndValue();
                     Rect bounds = mRectEvaluator.evaluate(fraction, start, end);
                     setCurrentValue(bounds);
                     if (inScaleTransition() || sourceHintRect == null) {
+
                         if (isOutPipDirection(direction)) {
                             getSurfaceTransactionHelper().scale(tx, leash, end, bounds);
                         } else {
-                            getSurfaceTransactionHelper().scale(tx, leash, start, bounds);
+                            getSurfaceTransactionHelper().scale(tx, leash, base, bounds);
                         }
                     } else {
                         final Rect insets;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsAlgorithm.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsAlgorithm.java
index 1bb5eda..22d8ed5 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsAlgorithm.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsAlgorithm.java
@@ -102,9 +102,7 @@
         return mSnapAlgorithm;
     }
 
-    /**
-     * Responds to IPinnedStackListener on configuration change.
-     */
+    /** Responds to configuration change. */
     public void onConfigurationChanged(Context context) {
         reloadResources(context);
     }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
index 98ed822..9081783 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
@@ -30,6 +30,7 @@
 import static com.android.wm.shell.pip.PipAnimationController.TRANSITION_DIRECTION_NONE;
 import static com.android.wm.shell.pip.PipAnimationController.TRANSITION_DIRECTION_REMOVE_STACK;
 import static com.android.wm.shell.pip.PipAnimationController.TRANSITION_DIRECTION_SAME;
+import static com.android.wm.shell.pip.PipAnimationController.TRANSITION_DIRECTION_SNAP_AFTER_RESIZE;
 import static com.android.wm.shell.pip.PipAnimationController.TRANSITION_DIRECTION_TO_PIP;
 import static com.android.wm.shell.pip.PipAnimationController.isInPipDirection;
 import static com.android.wm.shell.pip.PipAnimationController.isOutPipDirection;
@@ -501,7 +502,6 @@
 
         mPipMenuController.attach(leash);
 
-
         if (mShouldIgnoreEnteringPipTransition) {
             final Rect destinationBounds = mPipBoundsState.getBounds();
             // animation is finished in the Launcher and here we directly apply the final touch.
@@ -814,6 +814,20 @@
                 TRANSITION_DIRECTION_NONE, duration, updateBoundsCallback);
     }
 
+    /**
+     * Animates resizing of the pinned stack given the duration and start bounds.
+     * This is used when the starting bounds is not the current PiP bounds.
+     */
+    public void scheduleAnimateResizePip(Rect fromBounds, Rect toBounds, int duration,
+            Consumer<Rect> updateBoundsCallback) {
+        if (mShouldDeferEnteringPip) {
+            Log.d(TAG, "skip scheduleAnimateResizePip, entering pip deferred");
+            return;
+        }
+        scheduleAnimateResizePip(fromBounds, toBounds, null /* sourceHintRect */,
+                TRANSITION_DIRECTION_SNAP_AFTER_RESIZE, duration, updateBoundsCallback);
+    }
+
     private void scheduleAnimateResizePip(Rect currentBounds, Rect destinationBounds,
             Rect sourceHintRect, @PipAnimationController.TransitionDirection int direction,
             int durationMs, Consumer<Rect> updateBoundsCallback) {
@@ -1073,8 +1087,11 @@
             Log.w(TAG, "Abort animation, invalid leash");
             return;
         }
+        Rect baseBounds = direction == TRANSITION_DIRECTION_SNAP_AFTER_RESIZE
+                ? mPipBoundsState.getBounds() : currentBounds;
         mPipAnimationController
-                .getAnimator(mLeash, currentBounds, destinationBounds, sourceHintRect, direction)
+                .getAnimator(mLeash, baseBounds, currentBounds, destinationBounds, sourceHintRect,
+                        direction)
                 .setTransitionDirection(direction)
                 .setPipAnimationCallback(mPipAnimationCallback)
                 .setDuration(durationMs)
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java
index 3234ef6..46fff85 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java
@@ -33,6 +33,7 @@
 import android.content.Context;
 import android.content.pm.ActivityInfo;
 import android.content.pm.ParceledListSlice;
+import android.content.res.Configuration;
 import android.graphics.Rect;
 import android.os.RemoteException;
 import android.os.UserHandle;
@@ -104,6 +105,9 @@
             // Skip if we aren't in PIP or haven't actually entered PIP yet. We still need to update
             // the display layout in the bounds handler in this case.
             onDisplayRotationChangedNotInPip(mContext, toRotation);
+            // do not forget to update the movement bounds as well.
+            updateMovementBounds(mPipBoundsState.getNormalBounds(), true /* fromRotation */,
+                    false /* fromImeAdjustment */, false /* fromShelfAdjustment */, t);
             return;
         }
         // If there is an animation running (ie. from a shelf offset), then ensure that we calculate
@@ -136,7 +140,7 @@
         }
     };
 
-    private DisplayController.OnDisplaysChangedListener mFixedRotationListener =
+    private final DisplayController.OnDisplaysChangedListener mFixedRotationListener =
             new DisplayController.OnDisplaysChangedListener() {
                 @Override
                 public void onFixedRotationStarted(int displayId, int newRotation) {
@@ -188,18 +192,6 @@
         }
 
         @Override
-        public void onDisplayInfoChanged(DisplayInfo displayInfo) {
-            mPipBoundsState.setDisplayInfo(displayInfo);
-        }
-
-        @Override
-        public void onConfigurationChanged() {
-            mPipBoundsAlgorithm.onConfigurationChanged(mContext);
-            mTouchHandler.onConfigurationChanged();
-            mPipBoundsState.onConfigurationChanged();
-        }
-
-        @Override
         public void onAspectRatioChanged(float aspectRatio) {
             // TODO(b/169373982): Remove this callback as it is redundant with PipTaskOrg params
             // change.
@@ -334,6 +326,15 @@
     }
 
     @Override
+    public void onConfigurationChanged(Configuration newConfig) {
+        mMainExecutor.execute(() -> {
+            mPipBoundsAlgorithm.onConfigurationChanged(mContext);
+            mTouchHandler.onConfigurationChanged();
+            mPipBoundsState.onConfigurationChanged();
+        });
+    }
+
+    @Override
     public void onDensityOrFontScaleChanged() {
         mMainExecutor.execute(() -> {
             mPipTaskOrganizer.onDensityOrFontScaleChanged(mContext);
@@ -532,7 +533,7 @@
      *
      * @return {@code true} if internal {@link DisplayInfo} is rotated, {@code false} otherwise.
      */
-    public boolean onDisplayRotationChanged(Context context, Rect outBounds, Rect oldBounds,
+    private boolean onDisplayRotationChanged(Context context, Rect outBounds, Rect oldBounds,
             Rect outInsetBounds,
             int displayId, int fromRotation, int toRotation, WindowContainerTransaction t) {
         // Bail early if the event is not sent to current {@link #mDisplayInfo}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipPinchResizingAlgorithm.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipPinchResizingAlgorithm.java
new file mode 100644
index 0000000..28cbe35
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipPinchResizingAlgorithm.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.wm.shell.pip.phone;
+
+import android.graphics.Point;
+import android.graphics.Rect;
+
+/**
+ * Helper class to calculate the new size given two-fingers pinch to resize.
+ */
+public class PipPinchResizingAlgorithm {
+    private static final Rect TMP_RECT = new Rect();
+    /**
+     * Given inputs and requirements and current PiP bounds, return the new size.
+     *
+     * @param x0 x-coordinate of the primary input.
+     * @param y0 y-coordinate of the primary input.
+     * @param x1 x-coordinate of the secondary input.
+     * @param y1 y-coordinate of the secondary input.
+     * @param downx0 x-coordinate of the original down point of the primary input.
+     * @param downy0 y-coordinate of the original down ponit of the primary input.
+     * @param downx1 x-coordinate of the original down point of the secondary input.
+     * @param downy1 y-coordinate of the original down point of the secondary input.
+     * @param currentPipBounds current PiP bounds.
+     * @param minVisibleWidth minimum visible width.
+     * @param minVisibleHeight minimum visible height.
+     * @param maxSize max size.
+     * @return The new resized PiP bounds, sharing the same center.
+     */
+    public static Rect pinchResize(float x0, float y0, float x1, float y1,
+            float downx0, float downy0, float downx1, float downy1, Rect currentPipBounds,
+            int minVisibleWidth, int minVisibleHeight, Point maxSize) {
+
+        int width = currentPipBounds.width();
+        int height = currentPipBounds.height();
+        int left = currentPipBounds.left;
+        int top = currentPipBounds.top;
+        int right = currentPipBounds.right;
+        int bottom = currentPipBounds.bottom;
+        final float aspect = (float) width / (float) height;
+        final int widthDelta = Math.round(Math.abs(x0 - x1) - Math.abs(downx0 - downx1));
+        final int heightDelta = Math.round(Math.abs(y0 - y1) - Math.abs(downy0 - downy1));
+
+        width = Math.max(minVisibleWidth, Math.min(width + widthDelta, maxSize.x));
+        height = Math.max(minVisibleHeight, Math.min(height + heightDelta, maxSize.y));
+
+        // Calculate 2 rectangles fulfilling all requirements for either X or Y being the major
+        // drag axis. What ever is producing the bigger rectangle will be chosen.
+        int width1;
+        int width2;
+        int height1;
+        int height2;
+        if (aspect > 1.0f) {
+            // Assuming that the width is our target we calculate the height.
+            width1 = Math.max(minVisibleWidth, Math.min(maxSize.x, width));
+            height1 = Math.round((float) width1 / aspect);
+            if (height1 < minVisibleHeight) {
+                // If the resulting height is too small we adjust to the minimal size.
+                height1 = minVisibleHeight;
+                width1 = Math.max(minVisibleWidth,
+                        Math.min(maxSize.x, Math.round((float) height1 * aspect)));
+            }
+            // Assuming that the height is our target we calculate the width.
+            height2 = Math.max(minVisibleHeight, Math.min(maxSize.y, height));
+            width2 = Math.round((float) height2 * aspect);
+            if (width2 < minVisibleWidth) {
+                // If the resulting width is too small we adjust to the minimal size.
+                width2 = minVisibleWidth;
+                height2 = Math.max(minVisibleHeight,
+                        Math.min(maxSize.y, Math.round((float) width2 / aspect)));
+            }
+        } else {
+            // Assuming that the width is our target we calculate the height.
+            width1 = Math.max(minVisibleWidth, Math.min(maxSize.x, width));
+            height1 = Math.round((float) width1 * aspect);
+            if (height1 < minVisibleHeight) {
+                // If the resulting height is too small we adjust to the minimal size.
+                height1 = minVisibleHeight;
+                width1 = Math.max(minVisibleWidth,
+                        Math.min(maxSize.x, Math.round((float) height1 / aspect)));
+            }
+            // Assuming that the height is our target we calculate the width.
+            height2 = Math.max(minVisibleHeight, Math.min(maxSize.y, height));
+            width2 = Math.round((float) height2 / aspect);
+            if (width2 < minVisibleWidth) {
+                // If the resulting width is too small we adjust to the minimal size.
+                width2 = minVisibleWidth;
+                height2 = Math.max(minVisibleHeight,
+                        Math.min(maxSize.y, Math.round((float) width2 * aspect)));
+            }
+        }
+
+        // Use the bigger of the two rectangles if the major change was positive, otherwise
+        // do the opposite.
+        final boolean grows = width > (right - left) || height > (bottom - top);
+        if (grows == (width1 * height1 > width2 * height2)) {
+            width = width1;
+            height = height1;
+        } else {
+            width = width2;
+            height = height2;
+        }
+
+        TMP_RECT.set(currentPipBounds.centerX() - width / 2,
+                currentPipBounds.centerY() - height / 2,
+                currentPipBounds.centerX() + width / 2,
+                currentPipBounds.centerY() + height / 2);
+        return TMP_RECT;
+    }
+}
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 bb545bd..2f5219c 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
@@ -39,7 +39,6 @@
 import android.view.InputEventReceiver;
 import android.view.InputMonitor;
 import android.view.MotionEvent;
-import android.view.ScaleGestureDetector;
 import android.view.ViewConfiguration;
 
 import androidx.annotation.VisibleForTesting;
@@ -62,19 +61,21 @@
 public class PipResizeGestureHandler {
 
     private static final String TAG = "PipResizeGestureHandler";
-    private static final float PINCH_THRESHOLD = 0.05f;
-    private static final float STARTING_SCALE_FACTOR = 1.0f;
+    private static final int PINCH_RESIZE_SNAP_DURATION = 250;
 
     private final Context mContext;
     private final PipBoundsAlgorithm mPipBoundsAlgorithm;
     private final PipMotionHelper mMotionHelper;
     private final PipBoundsState mPipBoundsState;
+    private final PipTaskOrganizer mPipTaskOrganizer;
+    private final PhonePipMenuController mPhonePipMenuController;
+    private final PipUiEventLogger mPipUiEventLogger;
     private final int mDisplayId;
     private final Executor mMainExecutor;
-    private final ScaleGestureDetector mScaleGestureDetector;
     private final Region mTmpRegion = new Region();
 
     private final PointF mDownPoint = new PointF();
+    private final PointF mDownSecondaryPoint = new PointF();
     private final Point mMaxSize = new Point();
     private final Point mMinSize = new Point();
     private final Rect mLastResizeBounds = new Rect();
@@ -88,23 +89,27 @@
     private final Rect mDisplayBounds = new Rect();
     private final Function<Rect, Rect> mMovementBoundsSupplier;
     private final Runnable mUpdateMovementBoundsRunnable;
+    private final Handler mHandler;
 
     private int mDelta;
     private float mTouchSlop;
+
     private boolean mAllowGesture;
     private boolean mIsAttached;
     private boolean mIsEnabled;
     private boolean mEnablePinchResize;
     private boolean mIsSysUiStateValid;
+    // For drag-resize
     private boolean mThresholdCrossed;
+    // For pinch-resize
+    private boolean mThresholdCrossed0;
+    private boolean mThresholdCrossed1;
     private boolean mUsingPinchToZoom = false;
-    private float mScaleFactor = STARTING_SCALE_FACTOR;
+    int mFirstIndex = -1;
+    int mSecondIndex = -1;
 
     private InputMonitor mInputMonitor;
     private InputEventReceiver mInputEventReceiver;
-    private PipTaskOrganizer mPipTaskOrganizer;
-    private PhonePipMenuController mPhonePipMenuController;
-    private PipUiEventLogger mPipUiEventLogger;
 
     private int mCtrlType;
 
@@ -124,66 +129,11 @@
         mUpdateMovementBoundsRunnable = updateMovementBoundsRunnable;
         mPhonePipMenuController = menuActivityController;
         mPipUiEventLogger = pipUiEventLogger;
+        mHandler = new Handler(Looper.getMainLooper());
 
         context.getDisplay().getRealSize(mMaxSize);
         reloadResources();
 
-        mScaleGestureDetector = new ScaleGestureDetector(context,
-                new ScaleGestureDetector.OnScaleGestureListener() {
-                    @Override
-                    public boolean onScale(ScaleGestureDetector detector) {
-                        mScaleFactor *= detector.getScaleFactor();
-
-                        if (!mThresholdCrossed
-                                && (mScaleFactor > (STARTING_SCALE_FACTOR + PINCH_THRESHOLD)
-                                || mScaleFactor < (STARTING_SCALE_FACTOR - PINCH_THRESHOLD))) {
-                            mThresholdCrossed = true;
-                            mInputMonitor.pilferPointers();
-                        }
-                        if (mThresholdCrossed) {
-                            int height = Math.min(mMaxSize.y, Math.max(mMinSize.y,
-                                    (int) (mScaleFactor * mLastDownBounds.height())));
-                            int width = Math.min(mMaxSize.x, Math.max(mMinSize.x,
-                                    (int) (mScaleFactor * mLastDownBounds.width())));
-                            int top, bottom, left, right;
-
-                            if ((mCtrlType & CTRL_TOP) != 0) {
-                                top = mLastDownBounds.bottom - height;
-                                bottom = mLastDownBounds.bottom;
-                            } else {
-                                top = mLastDownBounds.top;
-                                bottom = mLastDownBounds.top + height;
-                            }
-
-                            if ((mCtrlType & CTRL_LEFT) != 0) {
-                                left = mLastDownBounds.right - width;
-                                right = mLastDownBounds.right;
-                            } else {
-                                left = mLastDownBounds.left;
-                                right = mLastDownBounds.left + width;
-                            }
-
-                            mLastResizeBounds.set(left, top, right, bottom);
-                            mPipTaskOrganizer.scheduleUserResizePip(mLastDownBounds,
-                                    mLastResizeBounds,
-                                    null);
-                        }
-                        return true;
-                    }
-
-                    @Override
-                    public boolean onScaleBegin(ScaleGestureDetector detector) {
-                        setCtrlTypeForPinchToZoom();
-                        return true;
-                    }
-
-                    @Override
-                    public void onScaleEnd(ScaleGestureDetector detector) {
-                        mScaleFactor = STARTING_SCALE_FACTOR;
-                        finishResize();
-                    }
-                });
-
         mEnablePinchResize = DeviceConfig.getBoolean(
                 DeviceConfig.NAMESPACE_SYSTEMUI,
                 PIP_PINCH_RESIZE,
@@ -274,7 +224,7 @@
 
         if (ev instanceof MotionEvent) {
             if (mUsingPinchToZoom) {
-                mScaleGestureDetector.onTouchEvent((MotionEvent) ev);
+                onPinchResize((MotionEvent) ev);
             } else {
                 onDragCornerResize((MotionEvent) ev);
             }
@@ -282,6 +232,13 @@
     }
 
     /**
+     * Checks if there is currently an on-going gesture, either drag-resize or pinch-resize.
+     */
+    public boolean hasOngoingGesture() {
+        return mCtrlType != CTRL_NONE || mUsingPinchToZoom;
+    }
+
+    /**
      * Check whether the current x,y coordinate is within the region in which drag-resize should
      * start.
      * This consists of 4 small squares on the 4 corners of the PIP window, a quarter of which
@@ -295,7 +252,7 @@
      * |_|_|_________|_|_|
      * |_|_|         |_|_|
      */
-    public boolean isWithinTouchRegion(int x, int y) {
+    public boolean isWithinDragResizeRegion(int x, int y) {
         final Rect currentPipBounds = mPipBoundsState.getBounds();
         if (currentPipBounds == null) {
             return false;
@@ -327,15 +284,14 @@
         if (isInValidSysUiState()) {
             switch (ev.getActionMasked()) {
                 case MotionEvent.ACTION_DOWN:
-                    // Always pass the DOWN event to the ScaleGestureDetector
-                    mScaleGestureDetector.onTouchEvent(ev);
-                    if (isWithinTouchRegion((int) ev.getRawX(), (int) ev.getRawY())) {
+                    if (isWithinDragResizeRegion((int) ev.getRawX(), (int) ev.getRawY())) {
                         return true;
                     }
                     break;
 
                 case MotionEvent.ACTION_POINTER_DOWN:
                     if (mEnablePinchResize && ev.getPointerCount() == 2) {
+                        onPinchResize(ev);
                         mUsingPinchToZoom = true;
                         return true;
                     }
@@ -348,33 +304,11 @@
         return false;
     }
 
-    private void setCtrlTypeForPinchToZoom() {
-        final Rect currentPipBounds = mPipBoundsState.getBounds();
-        mLastDownBounds.set(mPipBoundsState.getBounds());
-
-        Rect movementBounds = mMovementBoundsSupplier.apply(currentPipBounds);
-        mDisplayBounds.set(movementBounds.left,
-                movementBounds.top,
-                movementBounds.right + currentPipBounds.width(),
-                movementBounds.bottom + currentPipBounds.height());
-
-        if (currentPipBounds.left == mDisplayBounds.left) {
-            mCtrlType |= CTRL_RIGHT;
-        } else {
-            mCtrlType |= CTRL_LEFT;
-        }
-
-        if (currentPipBounds.top > mDisplayBounds.top + mDisplayBounds.height()) {
-            mCtrlType |= CTRL_TOP;
-        } else {
-            mCtrlType |= CTRL_BOTTOM;
-        }
-    }
-
     private void setCtrlType(int x, int y) {
         final Rect currentPipBounds = mPipBoundsState.getBounds();
 
         Rect movementBounds = mMovementBoundsSupplier.apply(currentPipBounds);
+
         mDisplayBounds.set(movementBounds.left,
                 movementBounds.top,
                 movementBounds.right + currentPipBounds.width(),
@@ -408,6 +342,78 @@
         return mIsSysUiStateValid;
     }
 
+    private void onPinchResize(MotionEvent ev) {
+        int action = ev.getActionMasked();
+
+        if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
+            mFirstIndex = -1;
+            mSecondIndex = -1;
+            finishResize();
+        }
+
+        if (ev.getPointerCount() != 2) {
+            return;
+        }
+
+        if (action == MotionEvent.ACTION_POINTER_DOWN) {
+            if (mFirstIndex == -1 && mSecondIndex == -1) {
+                mFirstIndex = 0;
+                mSecondIndex = 1;
+                mLastResizeBounds.setEmpty();
+                mDownPoint.set(ev.getRawX(mFirstIndex), ev.getRawY(mFirstIndex));
+                mDownSecondaryPoint.set(ev.getRawX(mSecondIndex), ev.getRawY(mSecondIndex));
+
+                mLastResizeBounds.setEmpty();
+                mLastDownBounds.set(mPipBoundsState.getBounds());
+            }
+        }
+
+        if (action == MotionEvent.ACTION_MOVE) {
+            if (mFirstIndex == -1 || mSecondIndex == -1) {
+                return;
+            }
+
+            float x0 = ev.getRawX(mFirstIndex);
+            float y0 = ev.getRawY(mFirstIndex);
+            float x1 = ev.getRawX(mSecondIndex);
+            float y1 = ev.getRawY(mSecondIndex);
+
+            double hypot0 = Math.hypot(x0 - mDownPoint.x, y0 - mDownPoint.y);
+            double hypot1 = Math.hypot(x1 - mDownSecondaryPoint.x, y1 - mDownSecondaryPoint.y);
+            // Capture inputs
+            if (hypot0 > mTouchSlop && !mThresholdCrossed0) {
+                mInputMonitor.pilferPointers();
+                mThresholdCrossed0 = true;
+                // Reset the down to begin resizing from this point
+                mDownPoint.set(x0, y0);
+            }
+            if (hypot1 > mTouchSlop && !mThresholdCrossed1) {
+                mInputMonitor.pilferPointers();
+                mThresholdCrossed1 = true;
+                // Reset the down to begin resizing from this point
+                mDownSecondaryPoint.set(x1, y1);
+            }
+            if (mThresholdCrossed0 || mThresholdCrossed1) {
+                if (mPhonePipMenuController.isMenuVisible()) {
+                    mPhonePipMenuController.hideMenu();
+                }
+
+                x0 = mThresholdCrossed0 ? x0 : mDownPoint.x;
+                y0 = mThresholdCrossed0 ? y0 : mDownPoint.y;
+                x1 = mThresholdCrossed1 ? x1 : mDownSecondaryPoint.x;
+                y1 = mThresholdCrossed1 ? y1 : mDownSecondaryPoint.y;
+
+                final Rect currentPipBounds = mPipBoundsState.getBounds();
+                mLastResizeBounds.set(PipPinchResizingAlgorithm.pinchResize(x0, y0, x1, y1,
+                        mDownPoint.x, mDownPoint.y, mDownSecondaryPoint.x, mDownSecondaryPoint.y,
+                        currentPipBounds, mMinSize.x, mMinSize.y, mMaxSize));
+
+                mPipTaskOrganizer.scheduleUserResizePip(mLastDownBounds, mLastResizeBounds,
+                        null);
+            }
+        }
+    }
+
     private void onDragCornerResize(MotionEvent ev) {
         int action = ev.getActionMasked();
         float x = ev.getX();
@@ -415,7 +421,7 @@
         if (action == MotionEvent.ACTION_DOWN) {
             final Rect currentPipBounds = mPipBoundsState.getBounds();
             mLastResizeBounds.setEmpty();
-            mAllowGesture = isInValidSysUiState() && isWithinTouchRegion((int) x, (int) y);
+            mAllowGesture = isInValidSysUiState() && isWithinDragResizeRegion((int) x, (int) y);
             if (mAllowGesture) {
                 setCtrlType((int) x, (int) y);
                 mDownPoint.set(x, y);
@@ -468,15 +474,30 @@
 
     private void finishResize() {
         if (!mLastResizeBounds.isEmpty()) {
-            mUserResizeBounds.set(mLastResizeBounds);
-            mPipTaskOrganizer.scheduleFinishResizePip(mLastResizeBounds,
-                    (Rect bounds) -> {
-                        new Handler(Looper.getMainLooper()).post(() -> {
-                            mMotionHelper.synchronizePinnedStackBounds();
-                            mUpdateMovementBoundsRunnable.run();
-                            resetState();
+            final Runnable callback = () -> {
+                mUserResizeBounds.set(mLastResizeBounds);
+                mMotionHelper.synchronizePinnedStackBounds();
+                mUpdateMovementBoundsRunnable.run();
+                resetState();
+            };
+
+            // Pinch-to-resize needs to re-calculate snap fraction and animate to the snapped
+            // position correctly. Drag-resize does not need to move, so just finalize resize.
+            if (mUsingPinchToZoom) {
+                final Rect startBounds = new Rect(mLastResizeBounds);
+                mPipBoundsAlgorithm.applySnapFraction(mLastResizeBounds,
+                        mPipBoundsAlgorithm.getSnapFraction(mPipBoundsState.getBounds()));
+                mPipTaskOrganizer.scheduleAnimateResizePip(startBounds, mLastResizeBounds,
+                        PINCH_RESIZE_SNAP_DURATION,
+                        (Rect rect) -> {
+                            mHandler.post(callback);
                         });
-                    });
+            } else {
+                mPipTaskOrganizer.scheduleFinishResizePip(mLastResizeBounds,
+                        (Rect bounds) -> {
+                            mHandler.post(callback);
+                        });
+            }
             mPipUiEventLogger.log(
                     PipUiEventLogger.PipUiEventEnum.PICTURE_IN_PICTURE_RESIZE);
         } else {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java
index b7cfad9..33439a4 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java
@@ -86,7 +86,7 @@
     private boolean mEnableStash = true;
 
     // The reference inset bounds, used to determine the dismiss fraction
-    private Rect mInsetBounds = new Rect();
+    private final Rect mInsetBounds = new Rect();
     private int mExpandedShortestEdgeSize;
 
     // Used to workaround an issue where the WM rotation happens before we are notified, allowing
@@ -94,7 +94,8 @@
     private int mDeferResizeToNormalBoundsUntilRotation = -1;
     private int mDisplayRotation;
 
-    private Handler mHandler = new Handler();
+    private final Handler mHandler = new Handler();
+    private final PipAccessibilityInteractionConnection mConnection;
 
     // Behaviour states
     private int mMenuState = MENU_STATE_NONE;
@@ -108,7 +109,6 @@
     private float mSavedSnapFraction = -1f;
     private boolean mSendingHoverAccessibilityEvents;
     private boolean mMovementWithinDismiss;
-    private PipAccessibilityInteractionConnection mConnection;
 
     // Touch state
     private final PipTouchState mTouchState;
@@ -470,6 +470,11 @@
             return true;
         }
 
+        if (mPipResizeGestureHandler.hasOngoingGesture()) {
+            mPipDismissTargetHandler.hideDismissTargetMaybe();
+            return true;
+        }
+
         if ((ev.getAction() == MotionEvent.ACTION_DOWN || mTouchState.isUserInteracting())
                 && mPipDismissTargetHandler.maybeConsumeMotionEvent(ev)) {
             // If the first touch event occurs within the magnetic field, pass the ACTION_DOWN event
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/PipController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/PipController.java
index 763370b..0955056 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/PipController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/PipController.java
@@ -37,7 +37,6 @@
 import android.content.pm.ParceledListSlice;
 import android.content.res.Configuration;
 import android.graphics.Rect;
-import android.os.Debug;
 import android.os.Handler;
 import android.os.RemoteException;
 import android.os.UserHandle;
@@ -56,8 +55,6 @@
 import com.android.wm.shell.pip.PipMediaController;
 import com.android.wm.shell.pip.PipTaskOrganizer;
 
-import java.util.ArrayList;
-import java.util.List;
 import java.util.Objects;
 
 /**
@@ -87,42 +84,21 @@
     private static final int TASK_ID_NO_PIP = -1;
     private static final int INVALID_RESOURCE_TYPE = -1;
 
-    public static final int SUSPEND_PIP_RESIZE_REASON_WAITING_FOR_MENU_ACTIVITY_FINISH = 0x1;
-
-    /**
-     * PIPed activity is playing a media and it can be paused.
-     */
-    static final int PLAYBACK_STATE_PLAYING = 0;
-    /**
-     * PIPed activity has a paused media and it can be played.
-     */
-    static final int PLAYBACK_STATE_PAUSED = 1;
-    /**
-     * Users are unable to control PIPed activity's media playback.
-     */
-    static final int PLAYBACK_STATE_UNAVAILABLE = 2;
-
-    private static final int CLOSE_PIP_WHEN_MEDIA_SESSION_GONE_TIMEOUT_MS = 3000;
-
-    private int mSuspendPipResizingReason;
-
     private final Context mContext;
     private final PipBoundsState mPipBoundsState;
     private final PipBoundsAlgorithm mPipBoundsAlgorithm;
     private final PipTaskOrganizer mPipTaskOrganizer;
     private final PipMediaController mPipMediaController;
     private final TvPipMenuController mTvPipMenuController;
+    private final PipNotification mPipNotification;
 
     private IActivityTaskManager mActivityTaskManager;
     private int mState = STATE_NO_PIP;
-    private int mResumeResizePinnedStackRunnableState = STATE_NO_PIP;
     private final Handler mHandler = new Handler();
-    private List<Listener> mListeners = new ArrayList<>();
     private int mLastOrientation = Configuration.ORIENTATION_UNDEFINED;
     private int mPipTaskId = TASK_ID_NO_PIP;
     private int mPinnedStackId = INVALID_STACK_ID;
     private String[] mLastPackagesResourceGranted;
-    private PipNotification mPipNotification;
     private ParceledListSlice<RemoteAction> mCustomActions;
     private WindowManagerShellWrapper mWindowManagerShellWrapper;
     private int mResizeAnimationDuration;
@@ -135,9 +111,7 @@
     private boolean mImeVisible;
     private int mImeHeightAdjustment;
 
-    private final Runnable mResizePinnedStackRunnable =
-            () -> resizePinnedStack(mResumeResizePinnedStackRunnableState);
-    private final Runnable mClosePipRunnable = () -> closePip();
+    private final Runnable mClosePipRunnable = this::closePip;
     private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
@@ -237,8 +211,6 @@
         mPipTaskOrganizer.registerPipTransitionCallback(this);
         mActivityTaskManager = ActivityTaskManager.getService();
 
-        addListener(mPipNotification);
-
         final IntentFilter intentFilter = new IntentFilter();
         intentFilter.addAction(ACTION_CLOSE);
         intentFilter.addAction(ACTION_MENU);
@@ -297,6 +269,7 @@
     /**
      * Updates the PIP per configuration changed.
      */
+    @Override
     public void onConfigurationChanged(Configuration newConfig) {
         loadConfigurationsAndApply(newConfig);
         mPipNotification.onConfigurationChanged(mContext);
@@ -340,9 +313,8 @@
                 mPinnedStackId = INVALID_STACK_ID;
             }
         }
-        for (int i = mListeners.size() - 1; i >= 0; --i) {
-            mListeners.get(i).onPipActivityClosed();
-        }
+        mPipNotification.dismiss();
+        mTvPipMenuController.hideMenu();
         mHandler.removeCallbacks(mClosePipRunnable);
     }
 
@@ -353,9 +325,9 @@
         if (DEBUG) Log.d(TAG, "movePipToFullscreen(), current state=" + getStateDescription());
 
         mPipTaskId = TASK_ID_NO_PIP;
-        for (int i = mListeners.size() - 1; i >= 0; --i) {
-            mListeners.get(i).onMoveToFullscreen();
-        }
+        mTvPipMenuController.hideMenu();
+        mPipNotification.dismiss();
+
         resizePinnedStack(STATE_NO_PIP);
     }
 
@@ -379,9 +351,7 @@
         // Set state to STATE_PIP so we show it when the pinned stack animation ends.
         mState = STATE_PIP;
         mPipMediaController.onActivityPinned();
-        for (int i = mListeners.size() - 1; i >= 0; i--) {
-            mListeners.get(i).onPipEntered(packageName);
-        }
+        mPipNotification.show(packageName);
     }
 
     private void onActivityRestartAttempt(ActivityManager.RunningTaskInfo task,
@@ -428,61 +398,17 @@
     }
 
     /**
-     * Suspends resizing operation on the Pip until {@link #resumePipResizing} is called
-     *
-     * @param reason The reason for suspending resizing operations on the Pip.
-     */
-    public void suspendPipResizing(int reason) {
-        if (DEBUG) {
-            Log.d(TAG,
-                    "suspendPipResizing() reason=" + reason + " callers=" + Debug.getCallers(2));
-        }
-        mSuspendPipResizingReason |= reason;
-    }
-
-    /**
-     * Resumes resizing operation on the Pip that was previously suspended.
-     *
-     * @param reason The reason resizing operations on the Pip was suspended.
-     */
-    public void resumePipResizing(int reason) {
-        if ((mSuspendPipResizingReason & reason) == 0) {
-            return;
-        }
-        if (DEBUG) {
-            Log.d(TAG,
-                    "resumePipResizing() reason=" + reason + " callers=" + Debug.getCallers(2));
-        }
-        mSuspendPipResizingReason &= ~reason;
-        mHandler.post(mResizePinnedStackRunnable);
-    }
-
-    /**
      * Resize the Pip to the appropriate size for the input state.
      *
      * @param state In Pip state also used to determine the new size for the Pip.
      */
     public void resizePinnedStack(int state) {
-
         if (DEBUG) {
             Log.d(TAG, "resizePinnedStack() state=" + stateToName(state) + ", current state="
                     + getStateDescription(), new Exception());
         }
-
-        boolean wasStateNoPip = (mState == STATE_NO_PIP);
-        for (int i = mListeners.size() - 1; i >= 0; --i) {
-            mListeners.get(i).onPipResizeAboutToStart();
-        }
-        if (mSuspendPipResizingReason != 0) {
-            mResumeResizePinnedStackRunnableState = state;
-            if (DEBUG) {
-                Log.d(TAG, "resizePinnedStack() deferring"
-                        + " mSuspendPipResizingReason=" + mSuspendPipResizingReason
-                        + " mResumeResizePinnedStackRunnableState="
-                        + stateToName(mResumeResizePinnedStackRunnableState));
-            }
-            return;
-        }
+        final boolean wasStateNoPip = (mState == STATE_NO_PIP);
+        mTvPipMenuController.hideMenu();
         mState = state;
         final Rect newBounds;
         switch (mState) {
@@ -510,45 +436,20 @@
     }
 
     /**
-     * @return the current state, or the pending state if the state change was previously suspended.
+     * @return the current state.
      */
     private int getState() {
-        if (mSuspendPipResizingReason != 0) {
-            return mResumeResizePinnedStackRunnableState;
-        }
         return mState;
     }
 
-    /**
-     * Shows PIP menu UI by launching {@link PipMenuActivity}. It also locates the pinned
-     * stack to the centered PIP bound {@link R.config_centeredPictureInPictureBounds}.
-     */
     private void showPipMenu() {
         if (DEBUG) Log.d(TAG, "showPipMenu(), current state=" + getStateDescription());
 
         mState = STATE_PIP_MENU;
-        for (int i = mListeners.size() - 1; i >= 0; --i) {
-            mListeners.get(i).onShowPipMenu();
-        }
-
         mTvPipMenuController.showMenu();
     }
 
     /**
-     * Adds a {@link Listener} to PipController.
-     */
-    void addListener(Listener listener) {
-        mListeners.add(listener);
-    }
-
-    /**
-     * Removes a {@link Listener} from PipController.
-     */
-    void removeListener(Listener listener) {
-        mListeners.remove(listener);
-    }
-
-    /**
      * Returns {@code true} if PIP is shown.
      */
     public boolean isPipShown() {
@@ -619,33 +520,8 @@
         }
     }
 
-    /**
-     * A listener interface to receive notification on changes in PIP.
-     */
-    public interface Listener {
-        /**
-         * Invoked when an activity is pinned and PIP manager is set corresponding information.
-         * Classes must use this instead of {@link android.app.ITaskStackListener.onActivityPinned}
-         * because there's no guarantee for the PIP manager be return relavent information
-         * correctly. (e.g. {@link Pip.isPipShown}).
-         */
-        void onPipEntered(String packageName);
-        /** Invoked when a PIPed activity is closed. */
-        void onPipActivityClosed();
-        /** Invoked when the PIP menu gets shown. */
-        void onShowPipMenu();
-        /** Invoked when the PIPed activity is about to return back to the fullscreen. */
-        void onMoveToFullscreen();
-        /** Invoked when we are above to start resizing the Pip. */
-        void onPipResizeAboutToStart();
-    }
-
     private String getStateDescription() {
-        if (mSuspendPipResizingReason == 0) {
-            return stateToName(mState);
-        }
-        return stateToName(mResumeResizePinnedStackRunnableState) + " (while " + stateToName(mState)
-                + " is suspended)";
+        return stateToName(mState);
     }
 
     private static String stateToName(int state) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/PipMenuView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/PipMenuView.java
index 689c3ed..83cb7ce 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/PipMenuView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/PipMenuView.java
@@ -16,6 +16,9 @@
 
 package com.android.wm.shell.pip.tv;
 
+import static android.view.KeyEvent.ACTION_UP;
+import static android.view.KeyEvent.KEYCODE_BACK;
+
 import android.animation.Animator;
 import android.animation.AnimatorInflater;
 import android.annotation.Nullable;
@@ -36,25 +39,22 @@
 /**
  * The Menu View that shows controls of the PiP. Always fullscreen.
  */
-public class PipMenuView extends FrameLayout implements PipController.Listener {
+public class PipMenuView extends FrameLayout {
     private static final String TAG = "PipMenuView";
     private static final boolean DEBUG = PipController.DEBUG;
 
-    private final PipController mPipController;
     private final Animator mFadeInAnimation;
     private final Animator mFadeOutAnimation;
     private final PipControlsViewController mPipControlsViewController;
-    private boolean mRestorePipSizeWhenClose;
+    @Nullable
+    private OnBackPressListener mOnBackPressListener;
 
     public PipMenuView(Context context, PipController pipController) {
         super(context, null, 0);
-        mPipController = pipController;
-
         inflate(context, R.layout.tv_pip_menu, this);
 
         mPipControlsViewController = new PipControlsViewController(
-                findViewById(R.id.pip_controls), mPipController);
-        mRestorePipSizeWhenClose = true;
+                findViewById(R.id.pip_controls), pipController);
         mFadeInAnimation = AnimatorInflater.loadAnimator(
                 mContext, R.anim.tv_pip_menu_fade_in_animation);
         mFadeInAnimation.setTarget(mPipControlsViewController.getView());
@@ -63,16 +63,6 @@
         mFadeOutAnimation.setTarget(mPipControlsViewController.getView());
     }
 
-    @Override
-    public boolean dispatchKeyEvent(KeyEvent event) {
-        if (event.getKeyCode() == KeyEvent.KEYCODE_BACK
-                && event.getAction() == KeyEvent.ACTION_UP) {
-            restorePipAndFinish();
-            return true;
-        }
-        return super.dispatchKeyEvent(event);
-    }
-
     @Nullable
     SurfaceControl getWindowSurfaceControl() {
         final ViewRootImpl root = getViewRootImpl();
@@ -87,53 +77,39 @@
     }
 
     void showMenu() {
-        mPipController.addListener(this);
         mFadeInAnimation.start();
         setAlpha(1.0f);
-        try {
-            WindowManagerGlobal.getWindowSession().grantEmbeddedWindowFocus(null /* window */,
-                    getViewRootImpl().getInputToken(), true /* grantFocus */);
-        } catch (Exception e) {
-            Log.e(TAG, "Unable to update focus as menu appears", e);
-        }
+        grantWindowFocus(true);
     }
 
     void hideMenu() {
-        mPipController.removeListener(this);
-        mPipController.resumePipResizing(
-                PipController.SUSPEND_PIP_RESIZE_REASON_WAITING_FOR_MENU_ACTIVITY_FINISH);
         mFadeOutAnimation.start();
         setAlpha(0.0f);
+        grantWindowFocus(false);
+    }
+
+    private void grantWindowFocus(boolean grantFocus) {
         try {
             WindowManagerGlobal.getWindowSession().grantEmbeddedWindowFocus(null /* window */,
-                    getViewRootImpl().getInputToken(), false /* grantFocus */);
+                    getViewRootImpl().getInputToken(), grantFocus);
         } catch (Exception e) {
             Log.e(TAG, "Unable to update focus as menu disappears", e);
         }
     }
 
-    private void restorePipAndFinish() {
-        if (DEBUG) Log.d(TAG, "restorePipAndFinish()");
+    void setOnBackPressListener(OnBackPressListener onBackPressListener) {
+        mOnBackPressListener = onBackPressListener;
+    }
 
-        if (mRestorePipSizeWhenClose) {
-            if (DEBUG) Log.d(TAG, "   > restoring to the default position");
-
-            // When PIP menu activity is closed, restore to the default position.
-            mPipController.resizePinnedStack(PipController.STATE_PIP);
+    @Override
+    public boolean dispatchKeyEvent(KeyEvent event) {
+        if (event.getKeyCode() == KEYCODE_BACK && event.getAction() == ACTION_UP
+                && mOnBackPressListener != null) {
+            mOnBackPressListener.onBackPress();
+            return true;
+        } else {
+            return super.dispatchKeyEvent(event);
         }
-        hideMenu();
-    }
-
-    @Override
-    public void onPipEntered(String packageName) {
-        if (DEBUG) Log.d(TAG, "onPipEntered(), packageName=" + packageName);
-    }
-
-    @Override
-    public void onPipActivityClosed() {
-        if (DEBUG) Log.d(TAG, "onPipActivityClosed()");
-
-        hideMenu();
     }
 
     void setAppActions(ParceledListSlice<RemoteAction> actions) {
@@ -144,27 +120,7 @@
                 hasCustomActions ? actions.getList() : Collections.emptyList());
     }
 
-    @Override
-    public void onShowPipMenu() {
-        if (DEBUG) Log.d(TAG, "onShowPipMenu()");
-    }
-
-    @Override
-    public void onMoveToFullscreen() {
-        if (DEBUG) Log.d(TAG, "onMoveToFullscreen()");
-
-        // Moving PIP to fullscreen is implemented by resizing PINNED_STACK with null bounds.
-        // This conflicts with restoring PIP position, so disable it.
-        mRestorePipSizeWhenClose = false;
-        hideMenu();
-    }
-
-    @Override
-    public void onPipResizeAboutToStart() {
-        if (DEBUG) Log.d(TAG, "onPipResizeAboutToStart()");
-
-        hideMenu();
-        mPipController.suspendPipResizing(
-                PipController.SUSPEND_PIP_RESIZE_REASON_WAITING_FOR_MENU_ACTIVITY_FINISH);
+    interface OnBackPressListener {
+        void onBackPress();
     }
 }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/PipNotification.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/PipNotification.java
index d56a888..4e0ab66 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/PipNotification.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/PipNotification.java
@@ -39,7 +39,7 @@
  * <p>Once it's created, it will manage the PIP notification UI by itself except for handling
  * configuration changes.
  */
-public class PipNotification implements PipController.Listener {
+public class PipNotification {
     private static final boolean DEBUG = PipController.DEBUG;
     private static final String TAG = "PipNotification";
 
@@ -79,38 +79,21 @@
         onConfigurationChanged(context);
     }
 
-    @Override
-    public void onPipEntered(String packageName) {
+    void show(String packageName) {
         mPackageName = packageName;
-        notifyPipNotification();
+        update();
     }
 
-    @Override
-    public void onPipActivityClosed() {
-        dismissPipNotification();
+    void dismiss() {
+        mNotificationManager.cancel(NOTIFICATION_TAG, SystemMessage.NOTE_TV_PIP);
+        mNotified = false;
         mPackageName = null;
     }
 
-    @Override
-    public void onShowPipMenu() {
-        // no-op.
-    }
-
-    @Override
-    public void onMoveToFullscreen() {
-        dismissPipNotification();
-        mPackageName = null;
-    }
-
-    @Override
-    public void onPipResizeAboutToStart() {
-        // no-op.
-    }
-
     private void onMediaMetadataChanged(MediaMetadata metadata) {
         if (updateMediaControllerMetadata(metadata) && mNotified) {
             // update notification
-            notifyPipNotification();
+            update();
         }
     }
 
@@ -123,11 +106,11 @@
         mDefaultIconResId = R.drawable.pip_icon;
         if (mNotified) {
             // update notification
-            notifyPipNotification();
+            update();
         }
     }
 
-    private void notifyPipNotification() {
+    private void update() {
         mNotified = true;
         mNotificationBuilder
                 .setShowWhen(true)
@@ -144,11 +127,6 @@
                 mNotificationBuilder.build());
     }
 
-    private void dismissPipNotification() {
-        mNotified = false;
-        mNotificationManager.cancel(NOTIFICATION_TAG, SystemMessage.NOTE_TV_PIP);
-    }
-
     private boolean updateMediaControllerMetadata(MediaMetadata metadata) {
         String title = null;
         Bitmap art = null;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuController.java
index 91aef67..5d0d761 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuController.java
@@ -21,6 +21,7 @@
 import android.app.RemoteAction;
 import android.content.Context;
 import android.content.pm.ParceledListSlice;
+import android.util.Log;
 import android.view.SurfaceControl;
 
 import com.android.wm.shell.common.SystemWindows;
@@ -31,6 +32,8 @@
  * Manages the visibility of the PiP Menu as user interacts with PiP.
  */
 public class TvPipMenuController implements PipMenuController {
+    private static final String TAG = "TvPipMenuController";
+    private static final boolean DEBUG = PipController.DEBUG;
 
     private final Context mContext;
     private final SystemWindows mSystemWindows;
@@ -52,6 +55,8 @@
 
     @Override
     public void showMenu() {
+        if (DEBUG) Log.d(TAG, "showMenu()");
+
         if (mMenuView != null) {
             mSystemWindows.updateViewLayout(mMenuView, getPipMenuLayoutParams(MENU_WINDOW_TITLE,
                     mPipBoundsState.getDisplayBounds().width(),
@@ -68,27 +73,62 @@
         }
     }
 
-    @Override
-    public void attach(SurfaceControl leash) {
-        if (mMenuView == null) {
-            mMenuView = new PipMenuView(mContext, mPipController);
-            mSystemWindows.addView(mMenuView,
-                    getPipMenuLayoutParams(MENU_WINDOW_TITLE, 0 /* width */, 0 /* height */),
-                    0, SHELL_ROOT_LAYER_PIP);
-            mLeash = leash;
+    void hideMenu() {
+        if (DEBUG) Log.d(TAG, "hideMenu()");
+
+        if (isMenuVisible()) {
+            mMenuView.hideMenu();
+            mPipController.resizePinnedStack(PipController.STATE_PIP);
         }
     }
 
     @Override
+    public void attach(SurfaceControl leash) {
+        mLeash = leash;
+        attachPipMenuView();
+    }
+
+    @Override
     public void detach() {
+        hideMenu();
+        detachPipMenuView();
+        mLeash = null;
+    }
+
+    private void attachPipMenuView() {
+        if (DEBUG) Log.d(TAG, "attachPipMenuView()");
+
+        if (mMenuView != null) {
+            detachPipMenuView();
+        }
+
+        mMenuView = new PipMenuView(mContext, mPipController);
+        mMenuView.setOnBackPressListener(this::hideMenu);
+        mSystemWindows.addView(mMenuView,
+                getPipMenuLayoutParams(MENU_WINDOW_TITLE, 0 /* width */, 0 /* height */),
+                0, SHELL_ROOT_LAYER_PIP);
+    }
+
+    private void detachPipMenuView() {
+        if (DEBUG) Log.d(TAG, "detachPipMenuView()");
+
+        if (mMenuView == null) {
+            return;
+        }
+
         mSystemWindows.removeView(mMenuView);
         mMenuView = null;
-        mLeash = null;
     }
 
     @Override
     public void setAppActions(ParceledListSlice<RemoteAction> appActions) {
-        mMenuView.setAppActions(appActions);
+        if (DEBUG) Log.d(TAG, "setAppActions(), actions=" + appActions);
+
+        if (mMenuView != null) {
+            mMenuView.setAppActions(appActions);
+        } else {
+            Log.w(TAG, "Cannot set remote actions, there is no View");
+        }
     }
 
     @Override
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerWindowManager.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerWindowManager.java
index f2becc9..5078371 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerWindowManager.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerWindowManager.java
@@ -24,6 +24,7 @@
 import static android.view.WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
 import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY;
 import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
 import static android.view.WindowManager.SHELL_ROOT_LAYER_DIVIDER;
 
@@ -59,7 +60,7 @@
                 PixelFormat.TRANSLUCENT);
         mLp.token = new Binder();
         mLp.setTitle(WINDOW_TITLE);
-        mLp.privateFlags |= PRIVATE_FLAG_NO_MOVE_ANIMATION;
+        mLp.privateFlags |= PRIVATE_FLAG_NO_MOVE_ANIMATION | PRIVATE_FLAG_TRUSTED_OVERLAY;
         mLp.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
         view.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                 | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipAnimationControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipAnimationControllerTest.java
index 55e7a35..7f280cd 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipAnimationControllerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipAnimationControllerTest.java
@@ -79,7 +79,8 @@
     @Test
     public void getAnimator_withBounds_returnBoundsAnimator() {
         final PipAnimationController.PipTransitionAnimator animator = mPipAnimationController
-                .getAnimator(mLeash, new Rect(), new Rect(), null, TRANSITION_DIRECTION_TO_PIP);
+                .getAnimator(mLeash, new Rect(), new Rect(), new Rect(), null,
+                        TRANSITION_DIRECTION_TO_PIP);
 
         assertEquals("Expect ANIM_TYPE_BOUNDS animation",
                 animator.getAnimationType(), PipAnimationController.ANIM_TYPE_BOUNDS);
@@ -87,16 +88,19 @@
 
     @Test
     public void getAnimator_whenSameTypeRunning_updateExistingAnimator() {
+        final Rect baseValue = new Rect(0, 0, 100, 100);
         final Rect startValue = new Rect(0, 0, 100, 100);
         final Rect endValue1 = new Rect(100, 100, 200, 200);
         final Rect endValue2 = new Rect(200, 200, 300, 300);
         final PipAnimationController.PipTransitionAnimator oldAnimator = mPipAnimationController
-                .getAnimator(mLeash, startValue, endValue1, null, TRANSITION_DIRECTION_TO_PIP);
+                .getAnimator(mLeash, baseValue, startValue, endValue1, null,
+                        TRANSITION_DIRECTION_TO_PIP);
         oldAnimator.setSurfaceControlTransactionFactory(DummySurfaceControlTx::new);
         oldAnimator.start();
 
         final PipAnimationController.PipTransitionAnimator newAnimator = mPipAnimationController
-                .getAnimator(mLeash, startValue, endValue2, null, TRANSITION_DIRECTION_TO_PIP);
+                .getAnimator(mLeash, baseValue, startValue, endValue2, null,
+                        TRANSITION_DIRECTION_TO_PIP);
 
         assertEquals("getAnimator with same type returns same animator",
                 oldAnimator, newAnimator);
@@ -122,11 +126,13 @@
     @Test
     @SuppressWarnings("unchecked")
     public void pipTransitionAnimator_updateEndValue() {
+        final Rect baseValue = new Rect(0, 0, 100, 100);
         final Rect startValue = new Rect(0, 0, 100, 100);
         final Rect endValue1 = new Rect(100, 100, 200, 200);
         final Rect endValue2 = new Rect(200, 200, 300, 300);
         final PipAnimationController.PipTransitionAnimator animator = mPipAnimationController
-                .getAnimator(mLeash, startValue, endValue1, null, TRANSITION_DIRECTION_TO_PIP);
+                .getAnimator(mLeash, baseValue, startValue, endValue1, null,
+                        TRANSITION_DIRECTION_TO_PIP);
 
         animator.updateEndValue(endValue2);
 
@@ -135,10 +141,12 @@
 
     @Test
     public void pipTransitionAnimator_setPipAnimationCallback() {
+        final Rect baseValue = new Rect(0, 0, 100, 100);
         final Rect startValue = new Rect(0, 0, 100, 100);
         final Rect endValue = new Rect(100, 100, 200, 200);
         final PipAnimationController.PipTransitionAnimator animator = mPipAnimationController
-                .getAnimator(mLeash, startValue, endValue, null, TRANSITION_DIRECTION_TO_PIP);
+                .getAnimator(mLeash, baseValue, startValue, endValue, null,
+                        TRANSITION_DIRECTION_TO_PIP);
         animator.setSurfaceControlTransactionFactory(DummySurfaceControlTx::new);
 
         animator.setPipAnimationCallback(mPipAnimationCallback);
diff --git a/libs/hwui/FrameInfo.h b/libs/hwui/FrameInfo.h
index 738246d..ee7d15a 100644
--- a/libs/hwui/FrameInfo.h
+++ b/libs/hwui/FrameInfo.h
@@ -159,7 +159,7 @@
         // GPU start time is approximated to the moment before swapBuffer is invoked.
         // We could add an EGLSyncKHR fence at the beginning of the frame, but that is an overhead.
         int64_t endTime = get(FrameInfoIndex::GpuCompleted);
-        return endTime > 0 ? endTime - get(FrameInfoIndex::SwapBuffers) : 0;
+        return endTime > 0 ? endTime - get(FrameInfoIndex::SwapBuffers) : -1;
     }
 
     inline int64_t& set(FrameInfoIndex index) { return mFrameInfo[static_cast<int>(index)]; }
diff --git a/libs/hwui/canvas/CanvasOpTypes.h b/libs/hwui/canvas/CanvasOpTypes.h
index 2dfddac..f0aa777 100644
--- a/libs/hwui/canvas/CanvasOpTypes.h
+++ b/libs/hwui/canvas/CanvasOpTypes.h
@@ -47,8 +47,10 @@
     DrawArc,
     DrawPaint,
     DrawPoint,
+    DrawPoints,
     DrawPath,
     DrawLine,
+    DrawLines,
     DrawVertices,
     DrawImage,
     DrawImageRect,
diff --git a/libs/hwui/canvas/CanvasOps.h b/libs/hwui/canvas/CanvasOps.h
index b499733..242dbdb 100644
--- a/libs/hwui/canvas/CanvasOps.h
+++ b/libs/hwui/canvas/CanvasOps.h
@@ -26,6 +26,7 @@
 #include <hwui/Bitmap.h>
 #include <log/log.h>
 #include "CanvasProperty.h"
+#include "Points.h"
 
 #include "CanvasOpTypes.h"
 #include "Layer.h"
@@ -166,6 +167,22 @@
 };
 
 template <>
+struct CanvasOp<CanvasOpType::DrawPoints> {
+    size_t count;
+    SkPaint paint;
+    sk_sp<Points> points;
+    void draw(SkCanvas* canvas) const {
+        canvas->drawPoints(
+            SkCanvas::kPoints_PointMode,
+            count,
+            points->data(),
+            paint
+        );
+    }
+    ASSERT_DRAWABLE()
+};
+
+template <>
 struct CanvasOp<CanvasOpType::DrawRect> {
     SkRect rect;
     SkPaint paint;
@@ -264,6 +281,22 @@
 };
 
 template<>
+struct CanvasOp<CanvasOpType::DrawLines> {
+    size_t count;
+    SkPaint paint;
+    sk_sp<Points> points;
+    void draw(SkCanvas* canvas) const {
+        canvas->drawPoints(
+            SkCanvas::kLines_PointMode,
+            count,
+            points->data(),
+            paint
+        );
+    }
+    ASSERT_DRAWABLE()
+};
+
+template<>
 struct CanvasOp<CanvasOpType::DrawVertices> {
     sk_sp<SkVertices> vertices;
     SkBlendMode mode;
diff --git a/libs/hwui/canvas/Points.h b/libs/hwui/canvas/Points.h
new file mode 100644
index 0000000..05e6a7d
--- /dev/null
+++ b/libs/hwui/canvas/Points.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <ui/FatVector.h>
+#include "SkPoint.h"
+#include "SkRefCnt.h"
+
+/**
+ * Collection of points that are ref counted and to be used with
+ * various drawing calls that consume SkPoint as inputs like
+ * drawLines/drawPoints
+ */
+class Points: public SkNVRefCnt<SkPoint> {
+public:
+  Points(int size){
+      skPoints.resize(size);
+  }
+
+  Points(std::initializer_list<SkPoint> init): skPoints(init) { }
+
+  SkPoint& operator[](int index) {
+      return skPoints[index];
+  }
+
+  const SkPoint* data() const {
+      return skPoints.data();
+  }
+
+  size_t size() const {
+      return skPoints.size();
+  }
+private:
+  // Initialize the size to contain 2 SkPoints on the stack for optimized
+  // drawLine calls that require 2 SkPoints for start/end points of the line
+  android::FatVector<SkPoint, 2> skPoints;
+};
diff --git a/libs/hwui/tests/unit/CanvasOpTests.cpp b/libs/hwui/tests/unit/CanvasOpTests.cpp
index f186e55..033a587 100644
--- a/libs/hwui/tests/unit/CanvasOpTests.cpp
+++ b/libs/hwui/tests/unit/CanvasOpTests.cpp
@@ -245,6 +245,31 @@
     EXPECT_EQ(1, canvas.sumTotalDrawCalls());
 }
 
+TEST(CanvasOp, simpleDrawPoints) {
+    CanvasOpBuffer buffer;
+    EXPECT_EQ(buffer.size(), 0);
+    size_t numPts = 3;
+    auto pts = sk_ref_sp(
+          new Points({
+              {32, 16},
+              {48, 48},
+              {16, 32}
+          })
+    );
+
+    buffer.push(CanvasOp<Op::DrawPoints> {
+        .count = numPts,
+        .paint = SkPaint{},
+        .points = pts
+    });
+
+    CallCountingCanvas canvas;
+    EXPECT_EQ(0, canvas.sumTotalDrawCalls());
+    rasterizeCanvasBuffer(buffer, &canvas);
+    EXPECT_EQ(1, canvas.drawPoints);
+    EXPECT_EQ(1, canvas.sumTotalDrawCalls());
+}
+
 TEST(CanvasOp, simpleDrawLine) {
     CanvasOpBuffer buffer;
     EXPECT_EQ(buffer.size(), 0);
@@ -263,6 +288,30 @@
     EXPECT_EQ(1, canvas.sumTotalDrawCalls());
 }
 
+TEST(CanvasOp, simpleDrawLines) {
+    CanvasOpBuffer buffer;
+    EXPECT_EQ(buffer.size(), 0);
+    size_t numPts = 3;
+    auto pts = sk_ref_sp(
+        new Points({
+               {32, 16},
+               {48, 48},
+               {16, 32}
+          })
+        );
+    buffer.push(CanvasOp<Op::DrawLines> {
+        .count = numPts,
+        .paint = SkPaint{},
+        .points = pts
+    });
+
+    CallCountingCanvas canvas;
+    EXPECT_EQ(0, canvas.sumTotalDrawCalls());
+    rasterizeCanvasBuffer(buffer, &canvas);
+    EXPECT_EQ(1, canvas.drawPoints);
+    EXPECT_EQ(1, canvas.sumTotalDrawCalls());
+}
+
 TEST(CanvasOp, simpleDrawRect) {
     CanvasOpBuffer buffer;
     EXPECT_EQ(buffer.size(), 0);
diff --git a/libs/incident/OWNERS b/libs/incident/OWNERS
new file mode 100644
index 0000000..f766115
--- /dev/null
+++ b/libs/incident/OWNERS
@@ -0,0 +1 @@
+include /cmds/incidentd/OWNERS
diff --git a/libs/input/OWNERS b/libs/input/OWNERS
new file mode 100644
index 0000000..d701f23
--- /dev/null
+++ b/libs/input/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/hardware/input/OWNERS
diff --git a/libs/storage/OWNERS b/libs/storage/OWNERS
new file mode 100644
index 0000000..6f9dbea
--- /dev/null
+++ b/libs/storage/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/os/storage/OWNERS
diff --git a/libs/usb/OWNERS b/libs/usb/OWNERS
new file mode 100644
index 0000000..f7b2a37
--- /dev/null
+++ b/libs/usb/OWNERS
@@ -0,0 +1 @@
+include /services/usb/OWNERS
diff --git a/location/OWNERS b/location/OWNERS
new file mode 100644
index 0000000..5ac60284
--- /dev/null
+++ b/location/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/location/OWNERS
diff --git a/location/java/android/location/ILocationManager.aidl b/location/java/android/location/ILocationManager.aidl
index d3dc3b3..92e2136 100644
--- a/location/java/android/location/ILocationManager.aidl
+++ b/location/java/android/location/ILocationManager.aidl
@@ -30,6 +30,7 @@
 import android.location.IGnssNavigationMessageListener;
 import android.location.ILocationCallback;
 import android.location.ILocationListener;
+import android.location.LastLocationRequest;
 import android.location.Location;
 import android.location.LocationRequest;
 import android.location.LocationTime;
@@ -45,7 +46,7 @@
  */
 interface ILocationManager
 {
-    @nullable Location getLastLocation(String provider, String packageName, String attributionTag);
+    @nullable Location getLastLocation(String provider, in LastLocationRequest request, String packageName, String attributionTag);
     @nullable ICancellationSignal getCurrentLocation(String provider, in LocationRequest request, in ILocationCallback callback, String packageName, String attributionTag, String listenerId);
 
     void registerLocationListener(String provider, in LocationRequest request, in ILocationListener listener, String packageName, String attributionTag, String listenerId);
diff --git a/location/java/android/location/LastLocationRequest.aidl b/location/java/android/location/LastLocationRequest.aidl
new file mode 100644
index 0000000..30c90a9
--- /dev/null
+++ b/location/java/android/location/LastLocationRequest.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2012, 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.location;
+
+parcelable LastLocationRequest;
diff --git a/location/java/android/location/LastLocationRequest.java b/location/java/android/location/LastLocationRequest.java
new file mode 100644
index 0000000..9ea8048
--- /dev/null
+++ b/location/java/android/location/LastLocationRequest.java
@@ -0,0 +1,192 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.location;
+
+import android.Manifest;
+import android.annotation.NonNull;
+import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Objects;
+
+/**
+ * An encapsulation of various parameters for requesting last location via {@link LocationManager}.
+ *
+ * @hide
+ */
+@SystemApi
+public final class LastLocationRequest implements Parcelable {
+
+    private final boolean mHiddenFromAppOps;
+    private final boolean mLocationSettingsIgnored;
+
+    private LastLocationRequest(
+            boolean hiddenFromAppOps,
+            boolean locationSettingsIgnored) {
+        mHiddenFromAppOps = hiddenFromAppOps;
+        mLocationSettingsIgnored = locationSettingsIgnored;
+    }
+
+    /**
+     * Returns true if this last location request should be ignored while updating app ops with
+     * location usage. This implies that someone else (usually the creator of the last location
+     * request) is responsible for updating app ops.
+     *
+     * @return true if this request should be ignored while updating app ops with location usage
+     *
+     */
+    public boolean isHiddenFromAppOps() {
+        return mHiddenFromAppOps;
+    }
+
+    /**
+     * Returns true if location settings, throttling, background location limits, and any other
+     * possible limiting factors will be ignored in order to satisfy this last location request.
+     *
+     * @return true if all limiting factors will be ignored to satisfy this request
+     */
+    public boolean isLocationSettingsIgnored() {
+        return mLocationSettingsIgnored;
+    }
+
+    public static final @NonNull Parcelable.Creator<LastLocationRequest> CREATOR =
+            new Parcelable.Creator<LastLocationRequest>() {
+                @Override
+                public LastLocationRequest createFromParcel(Parcel in) {
+                    return new LastLocationRequest(
+                            /* hiddenFromAppOps= */ in.readBoolean(),
+                            /* locationSettingsIgnored= */ in.readBoolean());
+                }
+                @Override
+                public LastLocationRequest[] newArray(int size) {
+                    return new LastLocationRequest[size];
+                }
+            };
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(@NonNull Parcel parcel, int flags) {
+        parcel.writeBoolean(mHiddenFromAppOps);
+        parcel.writeBoolean(mLocationSettingsIgnored);
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+        LastLocationRequest that = (LastLocationRequest) o;
+        return mHiddenFromAppOps == that.mHiddenFromAppOps
+                && mLocationSettingsIgnored == that.mLocationSettingsIgnored;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(mHiddenFromAppOps, mLocationSettingsIgnored);
+    }
+
+    @NonNull
+    @Override
+    public String toString() {
+        StringBuilder s = new StringBuilder();
+        s.append("LastLocationRequest[");
+        if (mHiddenFromAppOps) {
+            s.append("hiddenFromAppOps, ");
+        }
+        if (mLocationSettingsIgnored) {
+            s.append("locationSettingsIgnored, ");
+        }
+        if (s.length() > "LastLocationRequest[".length()) {
+            s.setLength(s.length() - 2);
+        }
+        s.append(']');
+        return s.toString();
+    }
+
+    /**
+     * A builder class for {@link LastLocationRequest}.
+     */
+    public static final class Builder {
+
+        private boolean mHiddenFromAppOps;
+        private boolean mLocationSettingsIgnored;
+
+        /**
+         * Creates a new Builder.
+         */
+        public Builder() {
+            mHiddenFromAppOps = false;
+            mLocationSettingsIgnored = false;
+        }
+
+        /**
+         * Creates a new Builder with all parameters copied from the given last location request.
+         */
+        public Builder(@NonNull LastLocationRequest lastLocationRequest) {
+            mHiddenFromAppOps = lastLocationRequest.mHiddenFromAppOps;
+            mLocationSettingsIgnored = lastLocationRequest.mLocationSettingsIgnored;
+        }
+
+        /**
+         * If set to true, indicates that app ops should not be updated with location usage due to
+         * this request. This implies that someone else (usually the creator of the last location
+         * request) is responsible for updating app ops as appropriate. Defaults to false.
+         *
+         * <p>Permissions enforcement occurs when resulting last location request is actually used,
+         * not when this method is invoked.
+         */
+        @RequiresPermission(Manifest.permission.UPDATE_APP_OPS_STATS)
+        public @NonNull Builder setHiddenFromAppOps(boolean hiddenFromAppOps) {
+            mHiddenFromAppOps = hiddenFromAppOps;
+            return this;
+        }
+
+        /**
+         * If set to true, indicates that location settings, throttling, background location limits,
+         * and any other possible limiting factors should be ignored in order to satisfy this
+         * last location request. This is only intended for use in user initiated emergency
+         * situations, and should be used extremely cautiously. Defaults to false.
+         *
+         * <p>Permissions enforcement occurs when resulting last location request is actually used,
+         * not when this method is invoked.
+         */
+        @RequiresPermission(Manifest.permission.WRITE_SECURE_SETTINGS)
+        public @NonNull Builder setLocationSettingsIgnored(boolean locationSettingsIgnored) {
+            mLocationSettingsIgnored = locationSettingsIgnored;
+            return this;
+        }
+
+        /**
+         * Builds a last location request from this builder.
+         *
+         * @return a new last location request
+         */
+        public @NonNull LastLocationRequest build() {
+            return new LastLocationRequest(
+                    mHiddenFromAppOps,
+                    mLocationSettingsIgnored);
+        }
+    }
+}
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index 604c4a1..7085a75 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -683,6 +683,7 @@
      * location should always be checked.
      *
      * @return the last known location, or null if not available
+     *
      * @throws SecurityException if no suitable location permission is present
      *
      * @hide
@@ -706,18 +707,50 @@
      * in the course of the attempt as compared to this method.
      *
      * @param provider a provider listed by {@link #getAllProviders()}
+     *
      * @return the last known location for the given provider, or null if not available
+     *
      * @throws SecurityException if no suitable permission is present
      * @throws IllegalArgumentException if provider is null or doesn't exist
      */
     @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
     @Nullable
     public Location getLastKnownLocation(@NonNull String provider) {
+        return getLastKnownLocation(provider, new LastLocationRequest.Builder().build());
+    }
+
+    /**
+     * Gets the last known location from the given provider, or null if there is no last known
+     * location.
+     *
+     * <p>See {@link LastLocationRequest} documentation for an explanation of various request
+     * parameters and how they can affect the returned location.
+     *
+     * <p>See {@link #getLastKnownLocation(String)} for more detail on how this method works.
+     *
+     * @param provider            a provider listed by {@link #getAllProviders()}
+     * @param lastLocationRequest the last location request containing location parameters
+     *
+     * @return the last known location for the given provider, or null if not available
+     *
+     * @throws SecurityException if no suitable permission is present
+     * @throws IllegalArgumentException if provider is null or doesn't exist
+     * @throws IllegalArgumentException if lastLocationRequest is null
+     *
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
+    @Nullable
+    public Location getLastKnownLocation(@NonNull String provider,
+            @NonNull LastLocationRequest lastLocationRequest) {
         Preconditions.checkArgument(provider != null, "invalid null provider");
+        Preconditions.checkArgument(lastLocationRequest != null,
+                "invalid null last location request");
 
         try {
-            return mService.getLastLocation(provider, mContext.getPackageName(),
-                    mContext.getAttributionTag());
+            return mService.getLastLocation(provider, lastLocationRequest,
+                    mContext.getPackageName(), mContext.getAttributionTag());
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
diff --git a/location/java/android/location/OWNERS b/location/java/android/location/OWNERS
new file mode 100644
index 0000000..383321b
--- /dev/null
+++ b/location/java/android/location/OWNERS
@@ -0,0 +1,6 @@
+# Bug component: 880425
+
[email protected]
[email protected]
[email protected]
[email protected]
diff --git a/media/OWNERS b/media/OWNERS
index e741490..b2875e7 100644
--- a/media/OWNERS
+++ b/media/OWNERS
@@ -10,7 +10,7 @@
 [email protected]
 [email protected]
 [email protected]
[email protected]
[email protected]
 [email protected]
 [email protected]
 [email protected]
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 4578883..c67d90a 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -2881,7 +2881,12 @@
      * @return true if any music tracks are active.
      */
     public boolean isMusicActive() {
-        return AudioSystem.isStreamActive(STREAM_MUSIC, 0);
+        final IAudioService service = getService();
+        try {
+            return service.isMusicActive();
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
     }
 
     /**
diff --git a/media/java/android/media/AudioPlaybackConfiguration.java b/media/java/android/media/AudioPlaybackConfiguration.java
index 515e9d0..17305a5 100644
--- a/media/java/android/media/AudioPlaybackConfiguration.java
+++ b/media/java/android/media/AudioPlaybackConfiguration.java
@@ -89,9 +89,8 @@
     /**
      * @hide
      * Player backed an AAudio player.
-     * Note this type is not in System API so it will not be returned in public API calls
      */
-    // TODO unhide for SystemApi, update getPlayerType()
+    @SystemApi
     public static final int PLAYER_TYPE_AAUDIO = 13;
 
     /**
@@ -280,10 +279,7 @@
 
     /**
      * @hide
-     * Return the type of player linked to this configuration. The return value is one of
-     * {@link #PLAYER_TYPE_JAM_AUDIOTRACK}, {@link #PLAYER_TYPE_JAM_MEDIAPLAYER},
-     * {@link #PLAYER_TYPE_JAM_SOUNDPOOL}, {@link #PLAYER_TYPE_SLES_AUDIOPLAYER_BUFFERQUEUE},
-     * {@link #PLAYER_TYPE_SLES_AUDIOPLAYER_URI_FD}, or {@link #PLAYER_TYPE_UNKNOWN}.
+     * Return the type of player linked to this configuration.
      * <br>Note that player types not exposed in the system API will be represented as
      * {@link #PLAYER_TYPE_UNKNOWN}.
      * @return the type of the player.
@@ -291,7 +287,6 @@
     @SystemApi
     public @PlayerType int getPlayerType() {
         switch (mPlayerType) {
-            case PLAYER_TYPE_AAUDIO:
             case PLAYER_TYPE_HW_SOURCE:
             case PLAYER_TYPE_EXTERNAL_PROXY:
                 return PLAYER_TYPE_UNKNOWN;
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index 5c012be..2ac5b50 100755
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -334,4 +334,6 @@
     oneway void setStreamVolumeForUid(int streamType, int direction, int flags,
             in String packageName, int uid, int pid, in UserHandle userHandle,
             int targetSdkVersion);
+
+    boolean isMusicActive();
 }
diff --git a/media/java/android/media/MediaHTTPConnection.java b/media/java/android/media/MediaHTTPConnection.java
index a17ff82..babc1d5 100644
--- a/media/java/android/media/MediaHTTPConnection.java
+++ b/media/java/android/media/MediaHTTPConnection.java
@@ -19,7 +19,7 @@
 import static android.media.MediaPlayer.MEDIA_ERROR_UNSUPPORTED;
 
 import android.compat.annotation.UnsupportedAppUsage;
-import android.net.NetworkUtils;
+import android.net.InetAddresses;
 import android.os.IBinder;
 import android.os.StrictMode;
 import android.util.Log;
@@ -214,7 +214,7 @@
             if (host.equalsIgnoreCase("localhost")) {
                 return true;
             }
-            if (NetworkUtils.numericToInetAddress(host).isLoopbackAddress()) {
+            if (InetAddresses.parseNumericAddress(host).isLoopbackAddress()) {
                 return true;
             }
         } catch (IllegalArgumentException iex) {
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index 4b11e32..f8311cd 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -4232,8 +4232,10 @@
      * @see OnRtpRxNoticeListener
      *
      * @param listener the listener called after a notice from RTP Rx
-     * @param handler the {@link Handler} that receives RTP Tx events
-     *
+     * @param handler the {@link Handler} that receives RTP Tx events. If null is passed,
+     *                notifications will be posted on the thread that created this MediaPlayer
+     *                instance. If the creating thread does not have a {@link Looper}, then
+     *                notifications will be posted on the main thread.
      * @hide
      */
     @SystemApi
diff --git a/media/java/android/media/OWNERS b/media/java/android/media/OWNERS
new file mode 100644
index 0000000..cbc9ab7
--- /dev/null
+++ b/media/java/android/media/OWNERS
@@ -0,0 +1,8 @@
+# Bug component: 1344
+
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
diff --git a/media/java/android/media/audiofx/OWNERS b/media/java/android/media/audiofx/OWNERS
new file mode 100644
index 0000000..189fe0f
--- /dev/null
+++ b/media/java/android/media/audiofx/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 48436
+
[email protected]
diff --git a/media/java/android/media/audiopolicy/OWNERS b/media/java/android/media/audiopolicy/OWNERS
new file mode 100644
index 0000000..189fe0f
--- /dev/null
+++ b/media/java/android/media/audiopolicy/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 48436
+
[email protected]
diff --git a/media/java/android/media/browse/OWNERS b/media/java/android/media/browse/OWNERS
new file mode 100644
index 0000000..916fc36
--- /dev/null
+++ b/media/java/android/media/browse/OWNERS
@@ -0,0 +1,8 @@
+# Bug component: 137631
+
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
diff --git a/media/java/android/media/midi/OWNERS b/media/java/android/media/midi/OWNERS
new file mode 100644
index 0000000..6a351d3
--- /dev/null
+++ b/media/java/android/media/midi/OWNERS
@@ -0,0 +1 @@
[email protected]
diff --git a/media/java/android/media/session/OWNERS b/media/java/android/media/session/OWNERS
new file mode 100644
index 0000000..916fc36
--- /dev/null
+++ b/media/java/android/media/session/OWNERS
@@ -0,0 +1,8 @@
+# Bug component: 137631
+
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
diff --git a/media/java/android/media/soundtrigger/OWNERS b/media/java/android/media/soundtrigger/OWNERS
new file mode 100644
index 0000000..6a351d3
--- /dev/null
+++ b/media/java/android/media/soundtrigger/OWNERS
@@ -0,0 +1 @@
[email protected]
diff --git a/media/java/android/media/tv/OWNERS b/media/java/android/media/tv/OWNERS
index a891154..8bccc9a 100644
--- a/media/java/android/media/tv/OWNERS
+++ b/media/java/android/media/tv/OWNERS
@@ -1,9 +1,6 @@
[email protected]
 [email protected]
[email protected]
 [email protected]
 
 # For android remote service
 per-file ITvRemoteServiceInput.aidl = file:/media/lib/tvremote/OWNERS
 per-file ITvRemoteProvider.aidl = file:/media/lib/tvremote/OWNERS
-
diff --git a/media/java/android/media/tv/tuner/Descrambler.java b/media/java/android/media/tv/tuner/Descrambler.java
index 2217eb3..700e7be 100644
--- a/media/java/android/media/tv/tuner/Descrambler.java
+++ b/media/java/android/media/tv/tuner/Descrambler.java
@@ -110,14 +110,16 @@
     }
 
     /**
-     * Set a key token to link descrambler to a key slot
+     * Set a key token to link descrambler to a key slot. Use {@link isValidKeyToken(byte[])} to
+     * validate the key token format. Invalid key token would cause no-op and return
+     * {@link Tuner.RESULT_INVALID_ARGUMENT}.
      *
      * <p>A descrambler instance can have only one key slot to link, but a key slot can hold a few
-     * keys for different purposes.
+     * keys for different purposes. {@link Tuner.VOID_KEYTOKEN} is considered valid.
      *
-     * @param keyToken the token to be used to link the key slot. Use {@link Tuner.INVALID_KEYTOKEN}
+     * @param keyToken the token to be used to link the key slot. Use {@link Tuner.VOID_KEYTOKEN}
      *        to remove the current key from descrambler. If the current keyToken comes from a
-     *        MediaCas session, use {@link Tuner.INVALID_KEYTOKEN} to remove current key before
+     *        MediaCas session, use {@link Tuner.VOID_KEYTOKEN} to remove current key before
      *        closing the MediaCas session.
      * @return result status of the operation.
      */
@@ -134,6 +136,22 @@
     }
 
     /**
+     * Validate the key token format as the parameter of {@link setKeyToken(byte[])}.
+     *
+     * <p>The key token is expected to be less than 128 bits.
+     *
+     * @param keyToken the token to be validated.
+     * @return true if the given key token is a valid one.
+     */
+    public static boolean isValidKeyToken(@NonNull byte[] keyToken) {
+        if (keyToken.length == 0 || keyToken.length > 16) {
+            Log.d(TAG, "Invalid key token size: " + (keyToken.length * 8) + " bit.");
+            return false;
+        }
+        return true;
+    }
+
+    /**
      * Release the descrambler instance.
      */
     @Override
@@ -150,18 +168,4 @@
             }
         }
     }
-
-    private boolean isValidKeyToken(byte[] keyToken) {
-        if (keyToken.length == 0 || keyToken.length > 16) {
-            Log.d(TAG, "Invalid key token size: " + (keyToken.length * 8) + " bit.");
-            return false;
-        }
-        for (int i = 0; i < keyToken.length; i++) {
-            if (keyToken[i] < 0) {
-                Log.d(TAG, "Invalid key token.");
-                return false;
-            }
-        }
-        return true;
-    }
 }
diff --git a/media/java/android/media/tv/tuner/Tuner.java b/media/java/android/media/tv/tuner/Tuner.java
index da14ee1..d094c2c 100644
--- a/media/java/android/media/tv/tuner/Tuner.java
+++ b/media/java/android/media/tv/tuner/Tuner.java
@@ -167,13 +167,13 @@
     public static final int INVALID_LNB_ID =
             android.hardware.tv.tuner.V1_1.Constants.Constant.INVALID_LNB_ID;
     /**
-     * Invalid key token. It is used to remove the current key from descrambler.
+     * A void key token. It is used to remove the current key from descrambler.
      *
      * <p>If the current keyToken comes from a MediaCas session, App is recommended to
      * to use this constant to remove current key before closing MediaCas session.
      */
     @NonNull
-    public static final byte[] INVALID_KEYTOKEN =
+    public static final byte[] VOID_KEYTOKEN =
             {android.hardware.tv.tuner.V1_1.Constants.Constant.INVALID_KEYTOKEN};
 
     /** @hide */
diff --git a/media/java/android/media/tv/tuner/frontend/DvbsFrontendSettings.java b/media/java/android/media/tv/tuner/frontend/DvbsFrontendSettings.java
index 98f8096..a2a602a 100644
--- a/media/java/android/media/tv/tuner/frontend/DvbsFrontendSettings.java
+++ b/media/java/android/media/tv/tuner/frontend/DvbsFrontendSettings.java
@@ -341,13 +341,13 @@
         return mScanType;
     }
     /**
-     * Get if the client could handle the Diseqc Rx Message or not. Default value is false.
+     * Get if the client can handle the Diseqc Rx Message or not. Default value is false.
      *
-     * The setter {@link Builder#setCouldHandleDiseqcRxMessage(boolean)} is only supported with
+     * The setter {@link Builder#setCanHandleDiseqcRxMessage(boolean)} is only supported with
      * Tuner HAL 1.1 or higher. Use {@link TunerVersionChecker.getTunerVersion()} to check the
      * version.
      */
-    public boolean getCouldHandleDiseqcRxMessage() {
+    public boolean canHandleDiseqcRxMessage() {
         return mIsDiseqcRxMessage;
     }
 
@@ -409,7 +409,7 @@
         }
 
         /**
-         * Set true to indicate the client could handle the Diseqc Messages. Note that it's still
+         * Set true to indicate the client can handle the Diseqc Messages. Note that it's still
          * possible that the client won't receive the messages when HAL is not able to setup Rx
          * channel in the hardware layer.
          *
@@ -417,10 +417,10 @@
          * no-op. Use {@link TunerVersionChecker.getTunerVersion()} to check the version.
          */
         @NonNull
-        public Builder setCouldHandleDiseqcRxMessage(boolean couldReceiveDiseqcMessage) {
+        public Builder setCanHandleDiseqcRxMessage(boolean canHandleDiseqcMessage) {
             if (TunerVersionChecker.checkHigherOrEqualVersionTo(
-                        TunerVersionChecker.TUNER_VERSION_1_1, "setCouldHandleDiseqcRxMessage")) {
-                mIsDiseqcRxMessage = couldReceiveDiseqcMessage;
+                        TunerVersionChecker.TUNER_VERSION_1_1, "setCanHandleDiseqcRxMessage")) {
+                mIsDiseqcRxMessage = canHandleDiseqcMessage;
             }
             return this;
         }
diff --git a/media/java/android/mtp/OWNERS b/media/java/android/mtp/OWNERS
index 1928ba8..e27d06f 100644
--- a/media/java/android/mtp/OWNERS
+++ b/media/java/android/mtp/OWNERS
@@ -1,7 +1,7 @@
 set noparent
 
 [email protected]
[email protected]
[email protected]
 [email protected]
 [email protected]
 
diff --git a/media/jni/OWNERS b/media/jni/OWNERS
index f1b0237..e6e4f86 100644
--- a/media/jni/OWNERS
+++ b/media/jni/OWNERS
@@ -1,5 +1,5 @@
 # extra for MTP related files
-per-file android_mtp_*[email protected],[email protected],[email protected],[email protected]
+per-file android_mtp_*[email protected],[email protected],[email protected],[email protected]
 
 # extra for TV related files
 per-file android_media_tv_*[email protected],[email protected]
diff --git a/media/jni/android_media_MediaCodecLinearBlock.h b/media/jni/android_media_MediaCodecLinearBlock.h
index 8f1d2fa..ae2d3a2 100644
--- a/media/jni/android_media_MediaCodecLinearBlock.h
+++ b/media/jni/android_media_MediaCodecLinearBlock.h
@@ -49,7 +49,14 @@
             if (offset == 0 && size == block.capacity()) {
                 return mBuffer;
             }
-            return C2Buffer::CreateLinearBuffer(block.subBlock(offset, size));
+
+            std::shared_ptr<C2Buffer> buffer =
+                C2Buffer::CreateLinearBuffer(block.subBlock(offset, size));
+            for (const std::shared_ptr<const C2Info> &info : mBuffer->info()) {
+                std::shared_ptr<C2Param> param = std::move(C2Param::Copy(*info));
+                buffer->setInfo(std::static_pointer_cast<C2Info>(param));
+            }
+            return buffer;
         }
         if (mBlock) {
             return C2Buffer::CreateLinearBuffer(mBlock->share(offset, size, C2Fence{}));
diff --git a/media/mca/effect/java/android/media/effect/OWNERS b/media/mca/effect/java/android/media/effect/OWNERS
new file mode 100644
index 0000000..6a351d3
--- /dev/null
+++ b/media/mca/effect/java/android/media/effect/OWNERS
@@ -0,0 +1 @@
[email protected]
diff --git a/media/mca/effect/java/android/media/effect/effects/OWNERS b/media/mca/effect/java/android/media/effect/effects/OWNERS
new file mode 100644
index 0000000..6a351d3
--- /dev/null
+++ b/media/mca/effect/java/android/media/effect/effects/OWNERS
@@ -0,0 +1 @@
[email protected]
diff --git a/media/mca/filterfw/java/android/filterfw/OWNERS b/media/mca/filterfw/java/android/filterfw/OWNERS
new file mode 100644
index 0000000..5d351ef
--- /dev/null
+++ b/media/mca/filterfw/java/android/filterfw/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 50018
+
[email protected]
diff --git a/media/mca/filterfw/java/android/filterfw/samples/OWNERS b/media/mca/filterfw/java/android/filterfw/samples/OWNERS
new file mode 100644
index 0000000..5d351ef
--- /dev/null
+++ b/media/mca/filterfw/java/android/filterfw/samples/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 50018
+
[email protected]
diff --git a/media/tests/MtpTests/OWNERS b/media/tests/MtpTests/OWNERS
index 1928ba8..e27d06f 100644
--- a/media/tests/MtpTests/OWNERS
+++ b/media/tests/MtpTests/OWNERS
@@ -1,7 +1,7 @@
 set noparent
 
 [email protected]
[email protected]
[email protected]
 [email protected]
 [email protected]
 
diff --git a/mime/OWNERS b/mime/OWNERS
new file mode 100644
index 0000000..6f9dbea
--- /dev/null
+++ b/mime/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/os/storage/OWNERS
diff --git a/mime/java-res/android.mime.types b/mime/java-res/android.mime.types
index e5273a9..92365d1 100644
--- a/mime/java-res/android.mime.types
+++ b/mime/java-res/android.mime.types
@@ -63,6 +63,7 @@
 ?application/x-android-drm-fl fl
 ?application/x-flac flac
 ?application/x-font pcf
+?application/x-mobipocket-ebook prc mobi
 ?application/x-mpegurl m3u m3u8
 ?application/x-pem-file pem
 ?application/x-pkcs12 p12 pfx
diff --git a/native/android/aidl/com/android/internal/compat/OWNERS b/native/android/aidl/com/android/internal/compat/OWNERS
new file mode 100644
index 0000000..f8c3520
--- /dev/null
+++ b/native/android/aidl/com/android/internal/compat/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/compat/OWNERS
diff --git a/native/graphics/OWNERS b/native/graphics/OWNERS
new file mode 100644
index 0000000..a6d1bc3
--- /dev/null
+++ b/native/graphics/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/graphics/OWNERS
diff --git a/opengl/java/android/opengl/OWNERS b/opengl/java/android/opengl/OWNERS
new file mode 100644
index 0000000..9c6c610
--- /dev/null
+++ b/opengl/java/android/opengl/OWNERS
@@ -0,0 +1,4 @@
+# Bug component: 25421
+
[email protected]
[email protected]
diff --git a/packages/AppPredictionLib/OWNERS b/packages/AppPredictionLib/OWNERS
new file mode 100644
index 0000000..3a5d23d
--- /dev/null
+++ b/packages/AppPredictionLib/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/service/appprediction/OWNERS
diff --git a/packages/Backup/OWNERS b/packages/Backup/OWNERS
new file mode 100644
index 0000000..d99779e
--- /dev/null
+++ b/packages/Backup/OWNERS
@@ -0,0 +1 @@
+include /services/backup/OWNERS
diff --git a/packages/BackupEncryption/OWNERS b/packages/BackupEncryption/OWNERS
new file mode 100644
index 0000000..d99779e
--- /dev/null
+++ b/packages/BackupEncryption/OWNERS
@@ -0,0 +1 @@
+include /services/backup/OWNERS
diff --git a/packages/BackupRestoreConfirmation/OWNERS b/packages/BackupRestoreConfirmation/OWNERS
new file mode 100644
index 0000000..d99779e
--- /dev/null
+++ b/packages/BackupRestoreConfirmation/OWNERS
@@ -0,0 +1 @@
+include /services/backup/OWNERS
diff --git a/packages/CompanionDeviceManager/AndroidManifest.xml b/packages/CompanionDeviceManager/AndroidManifest.xml
index 5247ac9..91bad7b 100644
--- a/packages/CompanionDeviceManager/AndroidManifest.xml
+++ b/packages/CompanionDeviceManager/AndroidManifest.xml
@@ -31,6 +31,7 @@
     <uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
     <uses-permission android:name="android.permission.RADIO_SCAN_WITHOUT_LOCATION"/>
     <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"/>
+    <uses-permission android:name="android.permission.HIDE_NON_SYSTEM_OVERLAY_WINDOWS"/>
 
     <application
         android:allowClearUserData="true"
diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java
index 2fe351e..fd71670 100644
--- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java
+++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java
@@ -321,7 +321,8 @@
     }
 
     void onDeviceSelected(String callingPackage, String deviceAddress) {
-        mServiceCallback.complete(new Association(getUserId(), deviceAddress, callingPackage));
+        mServiceCallback.complete(new Association(
+                getUserId(), deviceAddress, callingPackage, mRequest.getDeviceProfile(), false));
     }
 
     void onCancel() {
diff --git a/packages/EasterEgg/OWNERS b/packages/EasterEgg/OWNERS
new file mode 100644
index 0000000..2e96c97
--- /dev/null
+++ b/packages/EasterEgg/OWNERS
@@ -0,0 +1 @@
+include /packages/SystemUI/OWNERS
diff --git a/packages/ExternalStorageProvider/OWNERS b/packages/ExternalStorageProvider/OWNERS
new file mode 100644
index 0000000..6f9dbea
--- /dev/null
+++ b/packages/ExternalStorageProvider/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/os/storage/OWNERS
diff --git a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
index 11d1b0a..087275e 100644
--- a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
+++ b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
@@ -322,6 +322,11 @@
                 return true;
             }
 
+            if (TextUtils.equals(Environment.DIRECTORY_ANDROID.toLowerCase(),
+                    path.toLowerCase())) {
+                return true;
+            }
+
             return false;
         } catch (IOException e) {
             throw new IllegalArgumentException(
diff --git a/packages/FusedLocation/OWNERS b/packages/FusedLocation/OWNERS
new file mode 100644
index 0000000..5ac60284
--- /dev/null
+++ b/packages/FusedLocation/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/location/OWNERS
diff --git a/packages/MtpDocumentsProvider/OWNERS b/packages/MtpDocumentsProvider/OWNERS
new file mode 100644
index 0000000..6f9dbea
--- /dev/null
+++ b/packages/MtpDocumentsProvider/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/os/storage/OWNERS
diff --git a/packages/PrintRecommendationService/OWNERS b/packages/PrintRecommendationService/OWNERS
new file mode 100644
index 0000000..2c7b881
--- /dev/null
+++ b/packages/PrintRecommendationService/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/print/OWNERS
diff --git a/packages/PrintSpooler/OWNERS b/packages/PrintSpooler/OWNERS
new file mode 100644
index 0000000..2c7b881
--- /dev/null
+++ b/packages/PrintSpooler/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/print/OWNERS
diff --git a/packages/SettingsLib/Android.bp b/packages/SettingsLib/Android.bp
index e6492aa..23cb36f 100644
--- a/packages/SettingsLib/Android.bp
+++ b/packages/SettingsLib/Android.bp
@@ -54,6 +54,7 @@
         "SettingsLibEmergencyNumber",
         "SettingsLibTopIntroPreference",
         "SettingsLibBannerMessagePreference",
+        "SettingsLibFooterPreference",
     ],
 }
 
diff --git a/packages/SettingsLib/EmergencyNumber/src/com/android/settingslib/emergencynumber/EmergencyNumberUtils.java b/packages/SettingsLib/EmergencyNumber/src/com/android/settingslib/emergencynumber/EmergencyNumberUtils.java
index 12d21ca..1c0e718 100644
--- a/packages/SettingsLib/EmergencyNumber/src/com/android/settingslib/emergencynumber/EmergencyNumberUtils.java
+++ b/packages/SettingsLib/EmergencyNumber/src/com/android/settingslib/emergencynumber/EmergencyNumberUtils.java
@@ -84,8 +84,9 @@
     }
 
     private List<EmergencyNumber> getPromotedEmergencyNumbers(int categories) {
-        Map<Integer, List<EmergencyNumber>> allLists = mTelephonyManager.getEmergencyNumberList(
-                categories);
+        // TODO(b/171542607): Use platform API when its bug is fixed.
+        Map<Integer, List<EmergencyNumber>> allLists = filterEmergencyNumbersByCategories(
+                mTelephonyManager.getEmergencyNumberList(), categories);
         if (allLists == null || allLists.isEmpty()) {
             Log.w(TAG, "Unable to retrieve emergency number lists!");
             return new ArrayList<>();
@@ -130,4 +131,28 @@
         }
         return promotedEmergencyNumberLists.get(SubscriptionManager.getDefaultSubscriptionId());
     }
+
+    /**
+     * Filter emergency numbers with categories.
+     */
+    private Map<Integer, List<EmergencyNumber>> filterEmergencyNumbersByCategories(
+            Map<Integer, List<EmergencyNumber>> emergencyNumberList, int categories) {
+        Map<Integer, List<EmergencyNumber>> filteredMap = new ArrayMap<>();
+        if (emergencyNumberList == null) {
+            return filteredMap;
+        }
+        for (Integer subscriptionId : emergencyNumberList.keySet()) {
+            List<EmergencyNumber> allNumbersForSub = emergencyNumberList.get(
+                    subscriptionId);
+            List<EmergencyNumber> numbersForCategoriesPerSub = new ArrayList<>();
+            for (EmergencyNumber number : allNumbersForSub) {
+                if (number.isInEmergencyServiceCategories(categories)) {
+                    numbersForCategoriesPerSub.add(number);
+                }
+            }
+            filteredMap.put(
+                    subscriptionId, numbersForCategoriesPerSub);
+        }
+        return filteredMap;
+    }
 }
diff --git a/packages/SettingsLib/FooterPreference/Android.bp b/packages/SettingsLib/FooterPreference/Android.bp
new file mode 100644
index 0000000..30d9bd2
--- /dev/null
+++ b/packages/SettingsLib/FooterPreference/Android.bp
@@ -0,0 +1,13 @@
+android_library {
+    name: "SettingsLibFooterPreference",
+
+    srcs: ["src/**/*.java"],
+    resource_dirs: ["res"],
+
+    static_libs: [
+        "androidx.annotation_annotation",
+        "androidx.preference_preference",
+    ],
+    sdk_version: "system_current",
+    min_sdk_version: "21",
+}
diff --git a/packages/SettingsLib/FooterPreference/AndroidManifest.xml b/packages/SettingsLib/FooterPreference/AndroidManifest.xml
new file mode 100644
index 0000000..96d9e51
--- /dev/null
+++ b/packages/SettingsLib/FooterPreference/AndroidManifest.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2020 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="com.android.settingslib.widget">
+
+    <uses-sdk android:minSdkVersion="21" />
+
+</manifest>
diff --git a/packages/SettingsLib/FooterPreference/res/drawable/ic_info_outline_24.xml b/packages/SettingsLib/FooterPreference/res/drawable/ic_info_outline_24.xml
new file mode 100644
index 0000000..d9afeb0
--- /dev/null
+++ b/packages/SettingsLib/FooterPreference/res/drawable/ic_info_outline_24.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2020 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0"
+        android:tint="?android:attr/colorControlNormal">
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M11,17h2v-6h-2v6zM12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8zM11,9h2L13,7h-2v2z"/>
+</vector>
diff --git a/packages/SettingsLib/FooterPreference/res/values/attrs.xml b/packages/SettingsLib/FooterPreference/res/values/attrs.xml
new file mode 100644
index 0000000..deba3af
--- /dev/null
+++ b/packages/SettingsLib/FooterPreference/res/values/attrs.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources>
+    <attr name="footerPreferenceStyle" format="reference" />
+</resources>
\ No newline at end of file
diff --git a/packages/SettingsLib/FooterPreference/src/com/android/settingslib/widget/FooterPreference.java b/packages/SettingsLib/FooterPreference/src/com/android/settingslib/widget/FooterPreference.java
new file mode 100644
index 0000000..15301f6
--- /dev/null
+++ b/packages/SettingsLib/FooterPreference/src/com/android/settingslib/widget/FooterPreference.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.widget;
+
+import android.content.Context;
+import android.text.TextUtils;
+import android.text.method.LinkMovementMethod;
+import android.util.AttributeSet;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.StringRes;
+import androidx.core.content.res.TypedArrayUtils;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceViewHolder;
+
+/**
+ * A custom preference acting as "footer" of a page. It has a field for icon and text. It is added
+ * to screen as the last preference.
+ */
+public class FooterPreference extends Preference {
+
+    public static final String KEY_FOOTER = "footer_preference";
+    static final int ORDER_FOOTER = Integer.MAX_VALUE - 1;
+
+    public FooterPreference(Context context, AttributeSet attrs) {
+        super(context, attrs, TypedArrayUtils.getAttr(
+                context, R.attr.footerPreferenceStyle, android.R.attr.preferenceStyle));
+        init();
+    }
+
+    public FooterPreference(Context context) {
+        this(context, null);
+    }
+
+    @Override
+    public void onBindViewHolder(PreferenceViewHolder holder) {
+        super.onBindViewHolder(holder);
+        TextView title = holder.itemView.findViewById(android.R.id.title);
+        title.setMovementMethod(new LinkMovementMethod());
+        title.setClickable(false);
+        title.setLongClickable(false);
+    }
+
+    @Override
+    public void setSummary(CharSequence summary) {
+        setTitle(summary);
+    }
+
+    @Override
+    public void setSummary(int summaryResId) {
+        setTitle(summaryResId);
+    }
+
+    @Override
+    public CharSequence getSummary() {
+        return getTitle();
+    }
+
+    private void init() {
+        if (getIcon() == null) {
+            setIcon(R.drawable.ic_info_outline_24);
+        }
+        setOrder(ORDER_FOOTER);
+        if (TextUtils.isEmpty(getKey())) {
+            setKey(KEY_FOOTER);
+        }
+    }
+
+    /**
+     * The builder is convenient to creat a dynamic FooterPreference.
+     */
+    public static class Builder {
+        private Context mContext;
+        private String mKey;
+        private CharSequence mTitle;
+
+        public Builder(@NonNull Context context) {
+            mContext = context;
+        }
+
+        /**
+         * To set the key value of the {@link FooterPreference}.
+         * @param key The key value.
+         */
+        public Builder setKey(@NonNull String key) {
+            mKey = key;
+            return this;
+        }
+
+        /**
+         * To set the title of the {@link FooterPreference}.
+         * @param title The title.
+         */
+        public Builder setTitle(CharSequence title) {
+            mTitle = title;
+            return this;
+        }
+
+        /**
+         * To set the title of the {@link FooterPreference}.
+         * @param titleResId The resource id of the title.
+         */
+        public Builder setTitle(@StringRes int titleResId) {
+            mTitle = mContext.getText(titleResId);
+            return this;
+        }
+
+        /**
+         * To generate the {@link FooterPreference}.
+         */
+        public FooterPreference build() {
+            final FooterPreference footerPreference = new FooterPreference(mContext);
+            footerPreference.setSelectable(false);
+            if (TextUtils.isEmpty(mTitle)) {
+                throw new IllegalArgumentException("Footer title cannot be empty!");
+            }
+            footerPreference.setTitle(mTitle);
+            if (!TextUtils.isEmpty(mKey)) {
+                footerPreference.setKey(mKey);
+            }
+            return footerPreference;
+        }
+    }
+}
diff --git a/packages/SettingsLib/OWNERS b/packages/SettingsLib/OWNERS
index 8eafbdf..30c10d3 100644
--- a/packages/SettingsLib/OWNERS
+++ b/packages/SettingsLib/OWNERS
@@ -1,5 +1,5 @@
 # People who can approve changes for submission
[email protected]
[email protected]
 [email protected]
 [email protected]
 [email protected]
diff --git a/packages/SettingsLib/res/drawable/ic_info_outline_24.xml b/packages/SettingsLib/res/drawable/ic_info_outline_24.xml
deleted file mode 100644
index 317e43b..0000000
--- a/packages/SettingsLib/res/drawable/ic_info_outline_24.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  Copyright (C) 2019 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.
-  -->
-
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="24dp"
-        android:height="24dp"
-        android:viewportWidth="24.0"
-        android:viewportHeight="24.0"
-        android:tint="?android:attr/colorControlNormal">
-    <path
-        android:fillColor="#FF000000"
-        android:pathData="M11,17h2v-6h-2v6zM12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8zM11,9h2L13,7h-2v2z"/>
-</vector>
diff --git a/packages/SettingsLib/res/values/attrs.xml b/packages/SettingsLib/res/values/attrs.xml
index 9aed54e..1e6cb33 100644
--- a/packages/SettingsLib/res/values/attrs.xml
+++ b/packages/SettingsLib/res/values/attrs.xml
@@ -46,8 +46,6 @@
     <attr name="wifi_signal" format="reference" />
     <attr name="wifi_friction" format="reference" />
 
-    <attr name="footerPreferenceStyle" format="reference" />
-
     <!-- Workaround for b/74248169. These are duplicates of attrs in AndroidX preferences. -->
     <attr name="preferenceStyle" format="reference" />
     <attr name="switchPreferenceStyle" format="reference" />
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index 810a5ac..22213cb 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -995,8 +995,14 @@
     <!-- Settings item title for media transcoding settings. [CHAR LIMIT=85] -->
     <string name="transcode_settings_title">Media transcoding settings</string>
 
-    <!-- Settings item title to disable transcoding globally. [CHAR LIMIT=85] -->
-    <string name="transcode_enable_all">Disable transcoding</string>
+    <!-- Settings item title to enable user's control over further transcoding preferences. [CHAR LIMIT=85] -->
+    <string name="transcode_user_control">Override transcoding defaults</string>
+
+    <!-- Settings item title to enable transcoding globally. [CHAR LIMIT=85] -->
+    <string name="transcode_enable_all">Enable transcoding</string>
+
+    <!-- Settings item title to select the default behavior for transcoding if an encodig is not supported by an app. [CHAR LIMIT=85] -->
+    <string name="transcode_default">Assume apps support modern formats</string>
 
     <!-- Settings category title for selecting apps to be enabled for transcoding. [CHAR LIMIT=85] -->
     <string name="transcode_skip_apps">Enable transcoding for apps</string>
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/MediaDevice.java b/packages/SettingsLib/src/com/android/settingslib/media/MediaDevice.java
index 41d6afc..f21c359 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/MediaDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/MediaDevice.java
@@ -38,6 +38,7 @@
 import android.media.MediaRoute2Info;
 import android.media.MediaRouter2Manager;
 import android.text.TextUtils;
+import android.util.Log;
 
 import androidx.annotation.IntDef;
 import androidx.annotation.VisibleForTesting;
@@ -46,6 +47,7 @@
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -199,6 +201,10 @@
      */
 
     public void requestSetVolume(int volume) {
+        if (mRouteInfo == null) {
+            Log.w(TAG, "Unable to set volume. RouteInfo is empty");
+            return;
+        }
         mRouterManager.setRouteVolume(mRouteInfo, volume);
     }
 
@@ -208,6 +214,10 @@
      * @return max volume.
      */
     public int getMaxVolume() {
+        if (mRouteInfo == null) {
+            Log.w(TAG, "Unable to get max volume. RouteInfo is empty");
+            return 0;
+        }
         return mRouteInfo.getVolumeMax();
     }
 
@@ -217,6 +227,10 @@
      * @return current volume.
      */
     public int getCurrentVolume() {
+        if (mRouteInfo == null) {
+            Log.w(TAG, "Unable to get current volume. RouteInfo is empty");
+            return 0;
+        }
         return mRouteInfo.getVolume();
     }
 
@@ -226,6 +240,10 @@
      * @return package name.
      */
     public String getClientPackageName() {
+        if (mRouteInfo == null) {
+            Log.w(TAG, "Unable to get client package name. RouteInfo is empty");
+            return null;
+        }
         return mRouteInfo.getClientPackageName();
     }
 
@@ -244,6 +262,10 @@
      * @return result of transfer media
      */
     public boolean connect() {
+        if (mRouteInfo == null) {
+            Log.w(TAG, "Unable to connect. RouteInfo is empty");
+            return false;
+        }
         setConnectedRecord();
         mRouterManager.selectRoute(mPackageName, mRouteInfo);
         return true;
@@ -358,6 +380,10 @@
      * Gets the supported features of the route.
      */
     public List<String> getFeatures() {
+        if (mRouteInfo == null) {
+            Log.w(TAG, "Unable to get features. RouteInfo is empty");
+            return new ArrayList<>();
+        }
         return mRouteInfo.getFeatures();
     }
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/widget/FooterPreference.java b/packages/SettingsLib/src/com/android/settingslib/widget/FooterPreference.java
deleted file mode 100644
index 1557618..0000000
--- a/packages/SettingsLib/src/com/android/settingslib/widget/FooterPreference.java
+++ /dev/null
@@ -1,141 +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.settingslib.widget;
-
-import android.annotation.StringRes;
-import android.content.Context;
-import android.text.TextUtils;
-import android.text.method.LinkMovementMethod;
-import android.util.AttributeSet;
-import android.widget.TextView;
-
-import androidx.annotation.NonNull;
-import androidx.core.content.res.TypedArrayUtils;
-import androidx.preference.Preference;
-import androidx.preference.PreferenceViewHolder;
-
-import com.android.settingslib.R;
-
-/**
- * A custom preference acting as "footer" of a page. It has a field for icon and text. It is added
- * to screen as the last preference.
- */
-public class FooterPreference extends Preference {
-
-    static final int ORDER_FOOTER = Integer.MAX_VALUE - 1;
-    public static final String KEY_FOOTER = "footer_preference";
-
-    public FooterPreference(Context context, AttributeSet attrs) {
-        super(context, attrs, TypedArrayUtils.getAttr(
-                context, R.attr.footerPreferenceStyle, android.R.attr.preferenceStyle));
-        init();
-    }
-
-    public FooterPreference(Context context) {
-        this(context, null);
-    }
-
-    @Override
-    public void onBindViewHolder(PreferenceViewHolder holder) {
-        super.onBindViewHolder(holder);
-        TextView title = holder.itemView.findViewById(android.R.id.title);
-        title.setMovementMethod(new LinkMovementMethod());
-        title.setClickable(false);
-        title.setLongClickable(false);
-    }
-
-    @Override
-    public void setSummary(CharSequence summary) {
-        setTitle(summary);
-    }
-
-    @Override
-    public void setSummary(int summaryResId) {
-        setTitle(summaryResId);
-    }
-
-    @Override
-    public CharSequence getSummary() {
-        return getTitle();
-    }
-
-    private void init() {
-        if (getIcon() == null) {
-            setIcon(R.drawable.ic_info_outline_24);
-        }
-        setOrder(ORDER_FOOTER);
-        if (TextUtils.isEmpty(getKey())) {
-            setKey(KEY_FOOTER);
-        }
-    }
-
-    /**
-     * The builder is convenient to creat a dynamic FooterPreference.
-     */
-    public static class Builder {
-        private Context mContext;
-        private String mKey;
-        private CharSequence mTitle;
-
-        public Builder(@NonNull Context context) {
-            mContext = context;
-        }
-
-        /**
-         * To set the key value of the {@link FooterPreference}.
-         * @param key The key value.
-         */
-        public Builder setKey(@NonNull String key) {
-            mKey = key;
-            return this;
-        }
-
-        /**
-         * To set the title of the {@link FooterPreference}.
-         * @param title The title.
-         */
-        public Builder setTitle(CharSequence title) {
-            mTitle = title;
-            return this;
-        }
-
-        /**
-         * To set the title of the {@link FooterPreference}.
-         * @param titleResId The resource id of the title.
-         */
-        public Builder setTitle(@StringRes int titleResId) {
-            mTitle = mContext.getText(titleResId);
-            return this;
-        }
-
-        /**
-         * To generate the {@link FooterPreference}.
-         */
-        public FooterPreference build() {
-            final FooterPreference footerPreference = new FooterPreference(mContext);
-            footerPreference.setSelectable(false);
-            if (TextUtils.isEmpty(mTitle)) {
-                throw new IllegalArgumentException("Footer title cannot be empty!");
-            }
-            footerPreference.setTitle(mTitle);
-            if (!TextUtils.isEmpty(mKey)) {
-                footerPreference.setKey(mKey);
-            }
-            return footerPreference;
-        }
-    }
-}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/MediaDeviceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/MediaDeviceTest.java
index 47d4beb..6f7f73a 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/MediaDeviceTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/MediaDeviceTest.java
@@ -465,4 +465,12 @@
         assertThat(mInfoMediaDevice1.getState()).isEqualTo(
                 LocalMediaManager.MediaDeviceState.STATE_CONNECTING_FAILED);
     }
+
+    @Test
+    public void getFeatures_noRouteInfo_returnEmptyList() {
+        mBluetoothMediaDevice1 = new BluetoothMediaDevice(mContext, mCachedDevice1,
+                mMediaRouter2Manager, null /* MediaRoute2Info */, TEST_PACKAGE_NAME);
+
+        assertThat(mBluetoothMediaDevice1.getFeatures().size()).isEqualTo(0);
+    }
 }
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index a61e3cd..c9e3b6f 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -3342,7 +3342,7 @@
         }
 
         private final class UpgradeController {
-            private static final int SETTINGS_VERSION = 195;
+            private static final int SETTINGS_VERSION = 196;
 
             private final int mUserId;
 
@@ -4777,6 +4777,15 @@
                     currentVersion = 195;
                 }
 
+                if (currentVersion == 195) {
+                    // Version 195: delete obsolete manged services settings
+                    getSecureSettingsLocked(userId).deleteSettingLocked(
+                            Secure.ENABLED_NOTIFICATION_ASSISTANT);
+                    getSecureSettingsLocked(userId).deleteSettingLocked(
+                            Secure.ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES);
+                    currentVersion = 196;
+                }
+
                 // vXXX: Add new settings above this point.
 
                 if (currentVersion != newVersion) {
diff --git a/packages/SharedStorageBackup/OWNERS b/packages/SharedStorageBackup/OWNERS
new file mode 100644
index 0000000..d99779e
--- /dev/null
+++ b/packages/SharedStorageBackup/OWNERS
@@ -0,0 +1 @@
+include /services/backup/OWNERS
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 141b8cb..7b1257b0 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -281,6 +281,9 @@
     <uses-permission android:name="android.permission.MANAGE_NOTIFICATIONS"/>
     <uses-permission android:name="android.permission.ACCESS_LOCUS_ID_USAGE_STATS"/>
 
+    <!-- Permission needed for CTS test - MusicRecognitionManagerTest -->
+    <uses-permission android:name="android.permission.MANAGE_MUSIC_RECOGNITION" />
+
     <!-- Permissions required to test ambient display. -->
     <uses-permission android:name="android.permission.READ_DREAM_STATE"/>
     <uses-permission android:name="android.permission.WRITE_DREAM_STATE"/>
diff --git a/packages/Shell/OWNERS b/packages/Shell/OWNERS
index 6ba1fcb..2d7a3e6 100644
--- a/packages/Shell/OWNERS
+++ b/packages/Shell/OWNERS
@@ -1,6 +1,6 @@
 set noparent
 
[email protected]
[email protected]
 [email protected]
 [email protected]
 [email protected]
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 2da958f..285c4a1 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -576,6 +576,7 @@
             android:launchMode="singleInstance">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN"/>
+                <action android:name="android.appwidget.action.APPWIDGET_CONFIGURE"/>
                 <category android:name="android.intent.category.LAUNCHER"/>
             </intent-filter>
         </activity>
diff --git a/packages/SystemUI/OWNERS b/packages/SystemUI/OWNERS
index f884270..3bda710 100644
--- a/packages/SystemUI/OWNERS
+++ b/packages/SystemUI/OWNERS
@@ -1,6 +1,6 @@
 set noparent
 
[email protected]
[email protected]
 
 [email protected]
 [email protected]
diff --git a/packages/SystemUI/res/color/qs_background_dark.xml b/packages/SystemUI/res/color/qs_background_dark.xml
deleted file mode 100644
index c47959a..0000000
--- a/packages/SystemUI/res/color/qs_background_dark.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2017 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">
-    <item android:alpha="1"
-          android:color="?android:attr/colorBackground"/>
-</selector>
diff --git a/packages/SystemUI/res/drawable/brightness_mirror_background.xml b/packages/SystemUI/res/drawable/brightness_mirror_background.xml
index 43c9b73..02261b2 100644
--- a/packages/SystemUI/res/drawable/brightness_mirror_background.xml
+++ b/packages/SystemUI/res/drawable/brightness_mirror_background.xml
@@ -15,6 +15,6 @@
   ~ limitations under the License
   -->
 <shape xmlns:android="http://schemas.android.com/apk/res/android">
-    <solid android:color="@color/qs_background_dark" />
+    <solid android:color="?android:attr/colorBackground" />
     <corners android:radius="8dp" />
 </shape>
diff --git a/packages/SystemUI/res/drawable/ic_open_in_new_fullscreen.xml b/packages/SystemUI/res/drawable/ic_open_in_new_fullscreen.xml
index 55116c6..9f66581d 100644
--- a/packages/SystemUI/res/drawable/ic_open_in_new_fullscreen.xml
+++ b/packages/SystemUI/res/drawable/ic_open_in_new_fullscreen.xml
@@ -19,8 +19,8 @@
         <shape android:shape="rectangle">
             <solid android:color="@color/magnification_switch_button_color" />
             <size
-                android:width="40dp"
-                android:height="40dp" />
+                android:width="48dp"
+                android:height="48dp" />
         </shape>
     </item>
 
diff --git a/packages/SystemUI/res/drawable/ic_open_in_new_window.xml b/packages/SystemUI/res/drawable/ic_open_in_new_window.xml
index 5f571cf..659b020 100644
--- a/packages/SystemUI/res/drawable/ic_open_in_new_window.xml
+++ b/packages/SystemUI/res/drawable/ic_open_in_new_window.xml
@@ -19,8 +19,8 @@
         <shape android:shape="rectangle">
             <solid android:color="@color/magnification_switch_button_color" />
             <size
-                android:width="40dp"
-                android:height="40dp" />
+                android:width="48dp"
+                android:height="48dp" />
         </shape>
     </item>
 
diff --git a/packages/SystemUI/res/drawable/people_space_activity_card.xml b/packages/SystemUI/res/drawable/people_space_activity_card.xml
new file mode 100644
index 0000000..81162d2
--- /dev/null
+++ b/packages/SystemUI/res/drawable/people_space_activity_card.xml
@@ -0,0 +1,19 @@
+<!--
+  ~ Copyright (C) 2020 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+    <solid android:color="?android:attr/colorAccent" />
+    <corners android:radius="@dimen/people_space_widget_radius" />
+</shape>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/people_space_content_background.xml b/packages/SystemUI/res/drawable/people_space_content_background.xml
new file mode 100644
index 0000000..53108409
--- /dev/null
+++ b/packages/SystemUI/res/drawable/people_space_content_background.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2020 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<shape xmlns:android="http://schemas.android.com/apk/res/android" >
+    <solid android:color="?android:attr/colorControlHighlight" />
+    <corners android:radius="@dimen/people_space_widget_radius" />
+</shape>
diff --git a/packages/SystemUI/res/drawable/people_space_round_tile_view_card.xml b/packages/SystemUI/res/drawable/people_space_round_tile_view_card.xml
new file mode 100644
index 0000000..59af775
--- /dev/null
+++ b/packages/SystemUI/res/drawable/people_space_round_tile_view_card.xml
@@ -0,0 +1,19 @@
+<!--
+  ~ Copyright (C) 2020 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+    <solid android:color="?android:attr/colorBackground" />
+    <corners android:radius="@dimen/people_space_widget_round_radius" />
+</shape>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/people_space_rounded_border.xml b/packages/SystemUI/res/drawable/people_space_rounded_border.xml
new file mode 100644
index 0000000..9956bc2
--- /dev/null
+++ b/packages/SystemUI/res/drawable/people_space_rounded_border.xml
@@ -0,0 +1,19 @@
+<!--
+  ~ Copyright (C) 2020 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="oval">
+    <solid android:color="?android:attr/colorBackground" />
+</shape>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/people_space_tile_view_card.xml b/packages/SystemUI/res/drawable/people_space_tile_view_card.xml
index 4772ae7..8fd4388 100644
--- a/packages/SystemUI/res/drawable/people_space_tile_view_card.xml
+++ b/packages/SystemUI/res/drawable/people_space_tile_view_card.xml
@@ -14,6 +14,6 @@
   ~ limitations under the License.
   -->
 <shape xmlns:android="http://schemas.android.com/apk/res/android">
-    <solid android:color="@android:color/white" />
+    <solid android:color="?android:attr/colorBackground" />
     <corners android:radius="@dimen/people_space_widget_radius" />
 </shape>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/people_space_widget_background.xml b/packages/SystemUI/res/drawable/people_space_widget_background.xml
index b929359..fa45718 100644
--- a/packages/SystemUI/res/drawable/people_space_widget_background.xml
+++ b/packages/SystemUI/res/drawable/people_space_widget_background.xml
@@ -18,7 +18,7 @@
     android:shape="rectangle" >
     <solid
         android:color="?android:attr/colorControlNormal" />
-    <corners android:radius="@dimen/people_space_widget_radius" />
+    <corners android:radius="@dimen/people_space_widget_background_padding" />
     <padding
         android:left="@dimen/people_space_widget_background_padding"
         android:top="@dimen/people_space_widget_background_padding"
diff --git a/packages/SystemUI/res/drawable/qs_background_primary.xml b/packages/SystemUI/res/drawable/qs_background_primary.xml
deleted file mode 100644
index dd74cadd..0000000
--- a/packages/SystemUI/res/drawable/qs_background_primary.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 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.
--->
-<inset xmlns:android="http://schemas.android.com/apk/res/android">
-    <shape>
-        <solid android:color="@color/qs_background_dark"/>
-        <corners android:radius="?android:attr/dialogCornerRadius" />
-    </shape>
-</inset>
diff --git a/packages/SystemUI/res/drawable/qs_footer_drag_handle.xml b/packages/SystemUI/res/drawable/qs_footer_drag_handle.xml
index 509cd1f..59dad0e 100644
--- a/packages/SystemUI/res/drawable/qs_footer_drag_handle.xml
+++ b/packages/SystemUI/res/drawable/qs_footer_drag_handle.xml
@@ -17,6 +17,6 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:shape="rectangle" >
     <solid
-        android:color="#e5e5e5" />
+        android:color="?android:attr/textColorPrimary" />
     <corners android:radius="2dp" />
 </shape>
diff --git a/packages/SystemUI/res/layout/feedback_info.xml b/packages/SystemUI/res/layout/feedback_info.xml
index 7047c1b..753f56a 100644
--- a/packages/SystemUI/res/layout/feedback_info.xml
+++ b/packages/SystemUI/res/layout/feedback_info.xml
@@ -109,24 +109,4 @@
             style="@style/TextAppearance.NotificationInfo.Button"/>
     </LinearLayout>
 
-    <!-- Done button -->
-    <LinearLayout
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_marginTop="@dimen/notification_guts_button_spacing"
-        android:layout_marginBottom="@dimen/notification_guts_button_spacing"
-        android:gravity="end"
-        android:orientation="horizontal">
-
-        <TextView
-            android:id="@+id/ok"
-            android:text="@string/feedback_ok"
-            android:layout_width="wrap_content"
-            android:layout_height="match_parent"
-            android:background="@drawable/ripple_drawable"
-            android:minWidth="48dp"
-            android:layout_marginStart="8dp"
-            android:layout_marginEnd="-8dp"
-            style="@style/TextAppearance.NotificationInfo.Button"/>
-    </LinearLayout>
 </com.android.systemui.statusbar.notification.row.FeedbackInfo>
diff --git a/packages/SystemUI/res/layout/people_space_activity.xml b/packages/SystemUI/res/layout/people_space_activity.xml
index 67ecdaa..07af01b 100644
--- a/packages/SystemUI/res/layout/people_space_activity.xml
+++ b/packages/SystemUI/res/layout/people_space_activity.xml
@@ -17,8 +17,7 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/scroll"
     android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:background="@android:color/holo_blue_light">
+    android:layout_height="match_parent">
 
     <LinearLayout
         android:id="@+id/people_space_layout"
@@ -30,16 +29,15 @@
         android:clipChildren="false"
         android:clipToPadding="false">
 
-        <ImageView
-            android:id="@+id/people_space_cloud"
-            android:layout_width="67dp"
-            android:layout_height="67dp"
+        <TextView
+            android:id="@+id/select_conversation"
+            android:text="@string/select_conversation_text"
+            android:layout_width="match_parent"
+            android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
+            android:textSize="24sp"
+            android:layout_height="wrap_content"
             android:layout_gravity="center_horizontal"
-            android:scaleType="fitCenter"
-            android:focusable="false"
-            android:paddingBottom="16dp"
-            android:tint="?android:attr/colorControlNormal"
-            android:src="@drawable/cloud" />
+            android:paddingBottom="16dp" />
 
     </LinearLayout>
 </androidx.core.widget.NestedScrollView>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/people_space_large_avatar_tile.xml b/packages/SystemUI/res/layout/people_space_large_avatar_tile.xml
new file mode 100644
index 0000000..e9f3424
--- /dev/null
+++ b/packages/SystemUI/res/layout/people_space_large_avatar_tile.xml
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2020 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical">
+    <LinearLayout
+        android:background="@drawable/people_space_round_tile_view_card"
+        android:id="@+id/item"
+        android:paddingVertical="6dp"
+        android:orientation="vertical"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent">
+
+        <LinearLayout
+            android:orientation="horizontal"
+            android:gravity="center_vertical"
+            android:paddingStart="12dp"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent">
+
+                <ImageView
+                    android:id="@+id/person_icon"
+                    android:layout_width="60dp"
+                    android:layout_height="60dp" />
+
+                <LinearLayout
+                    android:background="@drawable/people_space_rounded_border"
+                    android:layout_marginStart="-12dp"
+                    android:layout_marginTop="28dp"
+                    android:layout_marginBottom="14dp"
+                    android:layout_width="16dp"
+                    android:layout_height="16dp">
+
+                    <ImageView
+                        android:id="@+id/package_icon"
+                        android:layout_width="12dp"
+                        android:layout_marginStart="2dp"
+                        android:layout_marginEnd="2dp"
+                        android:layout_marginBottom="2dp"
+                        android:layout_marginTop="2dp"
+                        android:layout_height="12dp" />
+                </LinearLayout>
+
+            <LinearLayout
+                android:orientation="vertical"
+                android:paddingStart="8dp"
+                android:paddingEnd="12dp"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content">
+
+                <TextView
+                    android:id="@+id/name"
+                    android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
+                    android:textColor="?android:attr/textColorPrimary"
+                    android:textSize="16sp"
+                    android:maxLines="1"
+                    android:ellipsize="end"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content" />
+
+                <TextView
+                    android:id="@+id/status"
+                    android:textColor="?android:attr/textColorSecondary"
+                    android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
+                    android:paddingVertical="3dp"
+                    android:textSize="12sp"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:maxLines="3"
+                    android:ellipsize="end" />
+            </LinearLayout>
+        </LinearLayout>
+    </LinearLayout>
+</LinearLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/people_space_small_avatar_tile.xml b/packages/SystemUI/res/layout/people_space_small_avatar_tile.xml
new file mode 100644
index 0000000..f474830
--- /dev/null
+++ b/packages/SystemUI/res/layout/people_space_small_avatar_tile.xml
@@ -0,0 +1,97 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2020 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical">
+    <LinearLayout
+        android:background="@drawable/people_space_tile_view_card"
+        android:id="@+id/item"
+        android:orientation="vertical"
+        android:paddingTop="6dp"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent">
+        <LinearLayout
+            android:orientation="horizontal"
+            android:paddingHorizontal="12dp"
+            android:paddingBottom="4dp"
+            android:gravity="top"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content">
+
+            <ImageView
+                android:id="@+id/person_icon"
+                android:layout_width="34dp"
+                android:layout_height="34dp" />
+
+            <LinearLayout
+                android:background="@drawable/people_space_rounded_border"
+                android:layout_marginStart="-5dp"
+                android:layout_marginTop="18dp"
+                android:layout_width="8dp"
+                android:layout_height="8dp">
+
+                <ImageView
+                    android:id="@+id/package_icon"
+                    android:layout_width="6dp"
+                    android:layout_marginEnd="1dp"
+                    android:layout_marginStart="1dp"
+                    android:layout_marginBottom="1dp"
+                    android:layout_marginTop="1dp"
+                    android:layout_height="6dp" />
+            </LinearLayout>
+
+            <LinearLayout
+                android:orientation="vertical"
+                android:paddingStart="6dp"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content">
+
+                <TextView
+                    android:id="@+id/name"
+                    android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
+                    android:textColor="?android:attr/textColorPrimary"
+                    android:textSize="14sp"
+                    android:maxLines="1"
+                    android:ellipsize="end"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content" />
+
+                <TextView
+                    android:id="@+id/time"
+                    android:textColor="?android:attr/textColorSecondary"
+                    android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
+                    android:textSize="10sp"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:maxLines="1"
+                    android:ellipsize="end" />
+            </LinearLayout>
+        </LinearLayout>
+        <TextView
+            android:id="@+id/content"
+            android:paddingVertical="3dp"
+            android:paddingHorizontal="12dp"
+            android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
+            android:background="@drawable/people_space_content_background"
+            android:textSize="14sp"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:maxLines="2"
+            android:ellipsize="end" />
+    </LinearLayout>
+</LinearLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/people_space_tile_view.xml b/packages/SystemUI/res/layout/people_space_tile_view.xml
index 80bb070..c751e7d 100644
--- a/packages/SystemUI/res/layout/people_space_tile_view.xml
+++ b/packages/SystemUI/res/layout/people_space_tile_view.xml
@@ -20,46 +20,53 @@
     android:orientation="vertical">
 
     <LinearLayout
-        android:background="@drawable/people_space_tile_view_card"
         android:orientation="vertical"
-        android:padding="16dp"
-        android:layout_marginBottom="24dp"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
+        android:background="@drawable/people_space_activity_card"
+        android:padding="12dp"
         android:elevation="4dp"
-        android:gravity="start">
+        android:layout_marginBottom="12dp"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content">
 
-        <ImageView
-            android:id="@+id/tile_view_package_icon"
-            android:layout_width="32dp"
-            android:layout_height="32dp"
-            android:layout_gravity="end" />
-
-        <ImageView
-            android:id="@+id/tile_view_person_icon"
-            android:layout_width="32dp"
-            android:layout_height="32dp"
-            android:layout_gravity="start" />
-
-        <TextView
-            android:id="@+id/tile_view_name"
-            android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
-            android:paddingVertical="4dp"
-            android:textSize="22sp"
-            android:textColor="?android:attr/textColorPrimary"
-            android:layout_width="wrap_content"
+        <LinearLayout
+            android:orientation="horizontal"
+            android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:layout_gravity="start" />
+            android:gravity="start">
 
-        <TextView
-            android:id="@+id/tile_view_status"
-            android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
-            android:paddingVertical="4dp"
-            android:textSize="16sp"
-            android:textColor="?android:attr/textColorSecondary"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:ellipsize="end"
-            android:layout_gravity="start" />
+            <ImageView
+                android:id="@+id/tile_view_person_icon"
+                android:layout_width="48dp"
+                android:layout_height="48dp" />
+
+            <ImageView
+                android:id="@+id/tile_view_package_icon"
+                android:layout_width="16dp"
+                android:layout_marginStart="-8dp"
+                android:layout_height="16dp" />
+
+            <LinearLayout
+                android:orientation="vertical"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content">
+
+                <TextView
+                    android:id="@+id/tile_view_name"
+                    android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
+                    android:paddingHorizontal="16dp"
+                    android:textSize="22sp"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content" />
+
+                <TextView
+                    android:id="@+id/tile_view_status"
+                    android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
+                    android:paddingVertical="4dp"
+                    android:textSize="12sp"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:ellipsize="end" />
+            </LinearLayout>
+        </LinearLayout>
     </LinearLayout>
 </LinearLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/people_space_widget.xml b/packages/SystemUI/res/layout/people_space_widget.xml
index b417fcf..f4db321 100644
--- a/packages/SystemUI/res/layout/people_space_widget.xml
+++ b/packages/SystemUI/res/layout/people_space_widget.xml
@@ -22,6 +22,6 @@
     android:background="@drawable/people_space_widget_background"
     android:clipChildren="false"
     android:clipToPadding="false"
-    android:padding="5dp"
+    android:padding="2dp"
     android:divider="@null"
     android:dividerHeight="0dp"/>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/people_space_widget_item.xml b/packages/SystemUI/res/layout/people_space_widget_item.xml
index e4de6f9..170386f 100644
--- a/packages/SystemUI/res/layout/people_space_widget_item.xml
+++ b/packages/SystemUI/res/layout/people_space_widget_item.xml
@@ -16,44 +16,77 @@
   -->
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
+    android:padding="4dp"
     android:layout_height="wrap_content"
     android:orientation="vertical">
     <LinearLayout
         android:background="@drawable/people_space_tile_view_card"
         android:id="@+id/item"
         android:orientation="vertical"
-        android:padding="6dp"
-        android:layout_marginBottom="6dp"
+        android:padding="4dp"
+        android:layout_marginBottom="2dp"
         android:elevation="4dp"
         android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:gravity="start">
-        <ImageView
-            android:id="@+id/package_icon"
-            android:layout_width="30dp"
-            android:layout_height="30dp"
-            android:layout_gravity="end" />
-        <ImageView
-            android:id="@+id/person_icon"
-            android:layout_width="30dp"
-            android:layout_height="30dp"
-            android:layout_gravity="start" />
-        <TextView
-            android:id="@+id/name"
-            android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
-            android:textSize="18sp"
-            android:textColor="?android:attr/textColorPrimary"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_gravity="start" />
-        <TextView
-            android:id="@+id/status"
-            android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
-            android:paddingVertical="2dp"
-            android:textSize="14sp"
-            android:textColor="?android:attr/textColorSecondary"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_gravity="start" />
+        android:layout_height="wrap_content">
+
+        <LinearLayout
+            android:orientation="horizontal"
+            android:gravity="center_vertical"
+            android:paddingStart="12dp"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content">
+
+            <ImageView
+                android:id="@+id/person_icon"
+                android:layout_width="60dp"
+                android:layout_height="60dp" />
+
+            <LinearLayout
+                android:background="@drawable/people_space_rounded_border"
+                android:layout_marginStart="-12dp"
+                android:layout_marginTop="28dp"
+                android:layout_marginBottom="14dp"
+                android:layout_width="16dp"
+                android:layout_height="16dp">
+
+                <ImageView
+                    android:id="@+id/package_icon"
+                    android:layout_width="12dp"
+                    android:layout_marginStart="2dp"
+                    android:layout_marginEnd="2dp"
+                    android:layout_marginBottom="2dp"
+                    android:layout_marginTop="2dp"
+                    android:layout_height="12dp" />
+            </LinearLayout>
+
+            <LinearLayout
+                android:orientation="vertical"
+                android:paddingStart="8dp"
+                android:paddingEnd="12dp"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content">
+
+                <TextView
+                    android:id="@+id/name"
+                    android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
+                    android:textColor="?android:attr/textColorPrimary"
+                    android:textSize="16sp"
+                    android:maxLines="1"
+                    android:ellipsize="end"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content" />
+
+                <TextView
+                    android:id="@+id/status"
+                    android:textColor="?android:attr/textColorSecondary"
+                    android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
+                    android:paddingVertical="2dp"
+                    android:textSize="12sp"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:maxLines="3"
+                    android:ellipsize="end" />
+            </LinearLayout>
+        </LinearLayout>
     </LinearLayout>
 </LinearLayout>
diff --git a/packages/SystemUI/res/layout/qs_panel.xml b/packages/SystemUI/res/layout/qs_panel.xml
index 89bf12d..387f2f2 100644
--- a/packages/SystemUI/res/layout/qs_panel.xml
+++ b/packages/SystemUI/res/layout/qs_panel.xml
@@ -25,9 +25,7 @@
     <View
         android:id="@+id/quick_settings_background"
         android:layout_width="match_parent"
-        android:layout_height="0dp"
-        android:elevation="4dp"
-        android:background="@drawable/qs_background_primary" />
+        android:layout_height="0dp" />
 
     <com.android.systemui.qs.NonInterceptingScrollView
         android:id="@+id/expanded_qs_scroll_view"
diff --git a/packages/SystemUI/res/layout/status_bar_expanded_plugin_frame.xml b/packages/SystemUI/res/layout/status_bar_expanded_plugin_frame.xml
index 69beffe..6f9d745 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded_plugin_frame.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded_plugin_frame.xml
@@ -25,5 +25,4 @@
     android:layout_marginTop="@dimen/notification_side_paddings"
     android:layout_marginLeft="@dimen/notification_side_paddings"
     android:layout_marginRight="@dimen/notification_side_paddings"
-    android:visibility="gone"
-    android:background="@drawable/qs_background_primary"/>
+    android:visibility="gone"/>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 57e1d43..a960133 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -1194,8 +1194,8 @@
     <dimen name="magnification_frame_move_long">25dp</dimen>
     <dimen name="magnification_drag_view_size">38dp</dimen>
     <dimen name="magnification_controls_size">90dp</dimen>
-    <dimen name="magnification_switch_button_size">32dp</dimen>
-    <dimen name="magnification_switch_button_padding">8dp</dimen>
+    <dimen name="magnification_switch_button_size">60dp</dimen>
+    <dimen name="magnification_switch_button_padding">12dp</dimen>
     <dimen name="magnifier_left_right_controls_width">35dp</dimen>
     <dimen name="magnifier_left_right_controls_height">45dp</dimen>
     <dimen name="magnifier_up_down_controls_width">45dp</dimen>
@@ -1303,6 +1303,7 @@
     <dimen name="media_output_dialog_icon_corner_radius">16dp</dimen>
     <dimen name="media_output_dialog_title_anim_y_delta">12.5dp</dimen>
 
-    <dimen name="people_space_widget_radius">10dp</dimen>
+    <dimen name="people_space_widget_radius">24dp</dimen>
+    <dimen name="people_space_widget_round_radius">100dp</dimen>
     <dimen name="people_space_widget_background_padding">6dp</dimen>
 </resources>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 5b74687..7989b7a 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -2824,13 +2824,15 @@
     <string name="build_number_copy_toast">Build number copied to clipboard.</string>
 
     <!-- Status for last interaction with exact time [CHAR LIMIT=120] -->
-    <string name="last_interaction_status" translatable="false">You last chatted <xliff:g id="duration" example="5 hours">%1$s</xliff:g> ago</string>
+    <string name="last_interaction_status" translatable="false">Last chatted <xliff:g id="duration" example="5 hours">%1$s</xliff:g> ago</string>
     <!-- Status for last interaction when less than a certain time window [CHAR LIMIT=120] -->
-    <string name="last_interaction_status_less_than" translatable="false">You last chatted less than <xliff:g id="duration" example="5 hours">%1$s</xliff:g> ago</string>
+    <string name="last_interaction_status_less_than" translatable="false">Last chatted less than <xliff:g id="duration" example="5 hours">%1$s</xliff:g> ago</string>
     <!-- Status for last interaction when over a certain time window [CHAR LIMIT=120] -->
-    <string name="last_interaction_status_over" translatable="false">You last chatted over <xliff:g id="duration" example="1 week">%1$s</xliff:g> ago</string>
+    <string name="last_interaction_status_over" translatable="false">Last chatted over <xliff:g id="duration" example="1 week">%1$s</xliff:g> ago</string>
     <!-- Status for conversation without interaction data [CHAR LIMIT=120] -->
     <string name="basic_status" translatable="false">Open conversation</string>
+    <!-- Status for conversation without interaction data [CHAR LIMIT=120] -->
+    <string name="select_conversation_text" translatable="false">Select one conversation to show in your widget:</string>
 
     <!-- Title to display in a notification when ACTION_BATTERY_CHANGED.EXTRA_PRESENT field is false
     [CHAR LIMIT=NONE] -->
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 0697c5c..6c0635a 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -489,7 +489,6 @@
 
     <style name="TextAppearance.NotificationInfo">
         <item name="android:fontFamily">@*android:string/config_headlineFontFamily</item>
-        <item name="android:textColor">@color/notification_primary_text_color</item>
     </style>
 
     <style name="TextAppearance.NotificationInfo.Secondary">
@@ -498,7 +497,6 @@
     </style>
 
     <style name="TextAppearance.NotificationInfo.Title">
-        <item name="android:textColor">@color/notification_primary_text_color</item>
         <item name="android:textStyle">bold</item>
     </style>
 
diff --git a/packages/SystemUI/res/xml/people_space_widget_info.xml b/packages/SystemUI/res/xml/people_space_widget_info.xml
index f08c8c8..10e28c4 100644
--- a/packages/SystemUI/res/xml/people_space_widget_info.xml
+++ b/packages/SystemUI/res/xml/people_space_widget_info.xml
@@ -15,10 +15,11 @@
   -->
 
 <appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
-    android:minWidth="72dp"
-    android:minHeight="150dp"
+    android:minWidth="180dp"
+    android:minHeight="40dp"
     android:updatePeriodMillis="60000"
-    android:previewImage="@drawable/cloud"
+    android:previewImage="@drawable/ic_android"
     android:resizeMode="horizontal|vertical"
+    android:configure="com.android.systemui.people.PeopleSpaceActivity"
     android:initialLayout="@layout/people_space_widget">
 </appwidget-provider>
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginInstanceManager.java b/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginInstanceManager.java
index c8607df..ee7030a8 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginInstanceManager.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginInstanceManager.java
@@ -386,7 +386,10 @@
                     }
                     Intent i = new Intent(PluginManagerImpl.DISABLE_PLUGIN).setData(
                             Uri.parse("package://" + component.flattenToString()));
-                    PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, i, 0);
+                    // TODO(b/174161910) Please replace FLAG_MUTABLE_UNAUDITED below
+                    // with either FLAG_IMMUTABLE (recommended) or FLAG_MUTABLE.
+                    PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, i,
+                            PendingIntent.FLAG_MUTABLE_UNAUDITED);
                     nb.addAction(new Action.Builder(null, "Disable plugin", pi).build());
                     mContext.getSystemService(NotificationManager.class)
                             .notify(SystemMessage.NOTE_PLUGIN, nb.build());
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationModeSwitch.java b/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationModeSwitch.java
index e40185c..267debc 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationModeSwitch.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationModeSwitch.java
@@ -23,6 +23,7 @@
 import android.content.pm.ActivityInfo;
 import android.graphics.PixelFormat;
 import android.graphics.PointF;
+import android.graphics.Rect;
 import android.os.Bundle;
 import android.os.UserHandle;
 import android.provider.Settings;
@@ -41,6 +42,8 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.systemui.R;
 
+import java.util.Collections;
+
 /**
  * Shows/hides a {@link android.widget.ImageView} on the screen and changes the values of
  * {@link Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE} when the UI is toggled.
@@ -52,7 +55,7 @@
     @VisibleForTesting
     static final long FADING_ANIMATION_DURATION_MS = 300;
     @VisibleForTesting
-    static final int DEFAULT_FADE_OUT_ANIMATION_DELAY_MS = 3000;
+    static final int DEFAULT_FADE_OUT_ANIMATION_DELAY_MS = 5000;
     private int mUiTimeout;
     private final Runnable mFadeInAnimationTask;
     private final Runnable mFadeOutAnimationTask;
@@ -85,7 +88,6 @@
         mImageView = imageView;
         mTouchSlop = ViewConfiguration.get(mContext).getScaledTouchSlop();
         applyResourcesValues();
-        mImageView.setImageResource(getIconResId(mMagnificationMode));
         mImageView.setOnTouchListener(this::onTouch);
         mImageView.setAccessibilityDelegate(new View.AccessibilityDelegate() {
             @Override
@@ -138,6 +140,7 @@
         final int padding = mContext.getResources().getDimensionPixelSize(
                 R.dimen.magnification_switch_button_padding);
         mImageView.setPadding(padding, padding, padding, padding);
+        mImageView.setImageResource(getIconResId(mMagnificationMode));
     }
 
     private boolean onTouch(View v, MotionEvent event) {
@@ -205,6 +208,8 @@
         }
         if (!mIsVisible) {
             mWindowManager.addView(mImageView, mParams);
+            // Exclude magnification switch button from system gesture area.
+            setSystemGestureExclusion();
             mIsVisible = true;
             mImageView.postOnAnimation(mFadeInAnimationTask);
             mUiTimeout = mAccessibilityManager.getRecommendedTimeoutMillis(
@@ -224,7 +229,11 @@
     void onConfigurationChanged(int configDiff) {
         if ((configDiff & ActivityInfo.CONFIG_DENSITY) != 0) {
             applyResourcesValues();
-            mImageView.setImageResource(getIconResId(mMagnificationMode));
+            if (mIsVisible) {
+                mWindowManager.updateViewLayout(mImageView, mParams);
+                // Exclude magnification switch button from system gesture area.
+                setSystemGestureExclusion();
+            }
             return;
         }
         if ((configDiff & ActivityInfo.CONFIG_LOCALE) != 0) {
@@ -261,7 +270,6 @@
         ImageView imageView = new ImageView(context);
         imageView.setClickable(true);
         imageView.setFocusable(true);
-        imageView.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
         imageView.setAlpha(0f);
         return imageView;
     }
@@ -288,4 +296,13 @@
     private static String getAccessibilityWindowTitle(Context context) {
         return context.getString(com.android.internal.R.string.android_system_label);
     }
+
+    private void setSystemGestureExclusion() {
+        mImageView.post(() -> {
+            mImageView.setSystemGestureExclusionRects(
+                    Collections.singletonList(
+                            new Rect(0, 0, mImageView.getWidth(), mImageView.getHeight())));
+        });
+    }
+
 }
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java b/packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java
index e49a5be..e6ad1cb 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java
@@ -400,7 +400,10 @@
                 case INTENT_ACTION_ACCESSIBILITY_SHORTCUT: {
                     Intent intent = new Intent(intentAction);
                     intent.setPackage(context.getPackageName());
-                    return PendingIntent.getBroadcast(context, 0, intent, 0);
+                    // TODO(b/173157883) Please replace FLAG_MUTABLE_UNAUDITED below
+                    // with either FLAG_IMMUTABLE (recommended) or FLAG_MUTABLE.
+                    return PendingIntent.getBroadcast(context, 0, intent,
+                            PendingIntent.FLAG_MUTABLE_UNAUDITED);
                 }
                 default:
                     break;
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java
index a330be6..ce5795c 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java
@@ -103,7 +103,7 @@
 
         d.setOnShowListener(dialog -> {
             if (mBlurUtils.supportsBlursOnWindows()) {
-                background.setAlpha((int) (ScrimController.BLUR_SCRIM_ALPHA * 255));
+                background.setAlpha((int) (ScrimController.BUSY_SCRIM_ALPHA * 255));
                 mBlurUtils.applyBlur(d.getWindow().getDecorView().getViewRootImpl(),
                         mBlurUtils.blurRadiusOfRatio(1));
             } else {
diff --git a/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceActivity.java b/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceActivity.java
index 5cd3b33..4a633c3 100644
--- a/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceActivity.java
@@ -16,19 +16,30 @@
 
 package com.android.systemui.people;
 
+import static android.appwidget.AppWidgetManager.EXTRA_APPWIDGET_ID;
+import static android.appwidget.AppWidgetManager.INVALID_APPWIDGET_ID;
+
 import android.app.Activity;
 import android.app.INotificationManager;
 import android.app.people.IPeopleManager;
 import android.app.people.PeopleSpaceTile;
+import android.appwidget.AppWidgetManager;
+import android.content.ComponentName;
 import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
 import android.content.pm.LauncherApps;
 import android.content.pm.PackageManager;
 import android.os.Bundle;
 import android.os.ServiceManager;
+import android.provider.Settings;
 import android.util.Log;
 import android.view.ViewGroup;
 
+import androidx.preference.PreferenceManager;
+
 import com.android.systemui.R;
+import com.android.systemui.people.widget.PeopleSpaceWidgetProvider;
 
 import java.util.List;
 import java.util.Map;
@@ -46,6 +57,9 @@
     private PackageManager mPackageManager;
     private LauncherApps mLauncherApps;
     private Context mContext;
+    private AppWidgetManager mAppWidgetManager;
+    private int mAppWidgetId;
+    private boolean mShowSingleConversation;
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
@@ -59,7 +73,18 @@
         mPeopleManager = IPeopleManager.Stub.asInterface(
                 ServiceManager.getService(Context.PEOPLE_SERVICE));
         mLauncherApps = mContext.getSystemService(LauncherApps.class);
+        mAppWidgetManager = AppWidgetManager.getInstance(mContext);
         setTileViewsWithPriorityConversations();
+        mAppWidgetId = getIntent().getIntExtra(EXTRA_APPWIDGET_ID,
+                INVALID_APPWIDGET_ID);
+        mShowSingleConversation = Settings.Global.getInt(mContext.getContentResolver(),
+                Settings.Global.PEOPLE_SPACE_CONVERSATION_TYPE, 0) == 0;
+        // Finish the configuration activity immediately if a widget is added for multiple
+        // conversations. If the mAppWidgetId is INVALID, then the activity wasn't launched as a
+        // widget configuration activity.
+        if (!mShowSingleConversation && mAppWidgetId != INVALID_APPWIDGET_ID) {
+            finishActivity();
+        }
     }
 
     /**
@@ -93,12 +118,39 @@
             tileView.setName(tile.getUserName().toString());
             tileView.setPackageIcon(mPackageManager.getApplicationIcon(pkg));
             tileView.setPersonIcon(tile.getUserIcon());
-            tileView.setOnClickListener(mLauncherApps, tile);
+            tileView.setOnClickListener(v -> storeWidgetConfiguration(tile));
         } catch (Exception e) {
             Log.e(TAG, "Couldn't retrieve shortcut information", e);
         }
     }
 
+    /** Stores the user selected configuration for {@code mAppWidgetId}. */
+    private void storeWidgetConfiguration(PeopleSpaceTile tile) {
+        SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mContext);
+        SharedPreferences.Editor editor = sp.edit();
+        if (PeopleSpaceUtils.DEBUG) {
+            Log.d(TAG, "Put " + tile.getUserName() + "'s shortcut ID: "
+                    + tile.getId() + " for widget ID: "
+                    + mAppWidgetId);
+        }
+        editor.putString(String.valueOf(mAppWidgetId), tile.getId());
+        editor.commit();
+        AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(mContext);
+        int[] widgetIds = appWidgetManager.getAppWidgetIds(
+                new ComponentName(mContext, PeopleSpaceWidgetProvider.class));
+        PeopleSpaceUtils.updateSingleConversationWidgets(mContext, widgetIds, mAppWidgetManager,
+                mNotificationManager);
+        finishActivity();
+    }
+
+    /** Finish activity with a successful widget configuration result. */
+    private void finishActivity() {
+        Intent resultValue = new Intent();
+        resultValue.putExtra(EXTRA_APPWIDGET_ID, mAppWidgetId);
+        setResult(RESULT_OK, resultValue);
+        finish();
+    }
+
     @Override
     protected void onResume() {
         super.onResume();
diff --git a/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceTileView.java b/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceTileView.java
index 4aea5b8..9ae7847 100644
--- a/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceTileView.java
+++ b/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceTileView.java
@@ -84,4 +84,9 @@
                 launcherApps.startShortcut(tile.getPackageName(), tile.getId(), null, null,
                         UserHandle.getUserHandleForUid(tile.getUid())));
     }
+
+    /** Sets the click listener of the tile directly. */
+    public void setOnClickListener(OnClickListener onClickListener) {
+        mTileView.setOnClickListener(onClickListener);
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java b/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java
index fe262b4..dddd39b 100644
--- a/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java
+++ b/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java
@@ -17,11 +17,17 @@
 package com.android.systemui.people;
 
 import android.app.INotificationManager;
+import android.app.PendingIntent;
 import android.app.people.ConversationChannel;
 import android.app.people.IPeopleManager;
 import android.app.people.PeopleSpaceTile;
+import android.appwidget.AppWidgetHost;
+import android.appwidget.AppWidgetManager;
 import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
 import android.content.pm.LauncherApps;
+import android.content.pm.PackageManager;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.drawable.BitmapDrawable;
@@ -29,17 +35,24 @@
 import android.icu.text.MeasureFormat;
 import android.icu.util.Measure;
 import android.icu.util.MeasureUnit;
+import android.os.ServiceManager;
 import android.os.UserHandle;
 import android.provider.Settings;
 import android.service.notification.ConversationChannelWrapper;
 import android.util.Log;
+import android.widget.RemoteViews;
+
+import androidx.preference.PreferenceManager;
 
 import com.android.systemui.R;
+import com.android.systemui.people.widget.LaunchConversationActivity;
+import com.android.systemui.people.widget.PeopleSpaceWidgetProvider;
 
 import java.time.Duration;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
+import java.util.Optional;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
@@ -57,14 +70,15 @@
             Context context, INotificationManager notificationManager, IPeopleManager peopleManager,
             LauncherApps launcherApps)
             throws Exception {
-        boolean showAllConversations = Settings.Global.getInt(context.getContentResolver(),
-                Settings.Global.PEOPLE_SPACE_CONVERSATION_TYPE, 0) == 0;
+        boolean showOnlyPriority = Settings.Global.getInt(context.getContentResolver(),
+                Settings.Global.PEOPLE_SPACE_CONVERSATION_TYPE, 0) == 1;
         List<ConversationChannelWrapper> conversations = notificationManager.getConversations(
                 true).getList();
         List<Map.Entry<Long, PeopleSpaceTile>> tiles = getSortedTiles(peopleManager,
                 conversations.stream().map(c ->
                         new PeopleSpaceTile.Builder(c.getShortcutInfo(), launcherApps).build()));
-        if (showAllConversations) {
+        if (!showOnlyPriority) {
+            if (DEBUG) Log.d(TAG, "Add recent conversations");
             List<ConversationChannel> recentConversations =
                     peopleManager.getRecentConversations().getList();
             List<Map.Entry<Long, PeopleSpaceTile>> recentTiles =
@@ -77,6 +91,79 @@
         return tiles;
     }
 
+    /** Updates {@code appWidgetIds} with their associated conversation stored. */
+    public static void updateSingleConversationWidgets(Context context, int[] appWidgetIds,
+            AppWidgetManager appWidgetManager, INotificationManager notificationManager) {
+        PackageManager mPackageManager = context.getPackageManager();
+        IPeopleManager mPeopleManager = IPeopleManager.Stub.asInterface(
+                ServiceManager.getService(Context.PEOPLE_SERVICE));
+        LauncherApps mLauncherApps = context.getSystemService(LauncherApps.class);
+        SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
+        Intent activityIntent = new Intent(context, LaunchConversationActivity.class);
+        activityIntent.addFlags(
+                Intent.FLAG_ACTIVITY_NEW_TASK
+                        | Intent.FLAG_ACTIVITY_CLEAR_TASK
+                        | Intent.FLAG_ACTIVITY_NO_HISTORY
+                        | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+        try {
+            List<Map.Entry<Long, PeopleSpaceTile>> shortcutInfos =
+                    PeopleSpaceUtils.getTiles(
+                            context, notificationManager,
+                            mPeopleManager, mLauncherApps);
+            for (int appWidgetId : appWidgetIds) {
+                String shortcutId = sp.getString(String.valueOf(appWidgetId), null);
+                if (DEBUG) {
+                    Log.d(TAG, "Set widget: " + appWidgetId + " with shortcut ID: " + shortcutId);
+                }
+
+                Optional<Map.Entry<Long, PeopleSpaceTile>> entry = shortcutInfos.stream().filter(
+                        e -> e.getValue().getId().equals(shortcutId)).findFirst();
+                if (!entry.isPresent() || shortcutId == null) {
+                    if (DEBUG) Log.d(TAG, "Matching conversation not found for shortcut ID");
+                    AppWidgetHost host = new AppWidgetHost(context, 0);
+                    host.deleteAppWidgetId(appWidgetId);
+                    continue;
+                }
+                PeopleSpaceTile tile = entry.get().getValue();
+                RemoteViews views = new RemoteViews(context.getPackageName(),
+                        getLayout(tile));
+
+                String status = PeopleSpaceUtils.getLastInteractionString(context,
+                        entry.get().getKey());
+                views.setTextViewText(R.id.status, status);
+                views.setTextViewText(R.id.name, tile.getUserName().toString());
+
+                activityIntent.putExtra(PeopleSpaceWidgetProvider.EXTRA_TILE_ID, tile.getId());
+                activityIntent.putExtra(
+                        PeopleSpaceWidgetProvider.EXTRA_PACKAGE_NAME, tile.getPackageName());
+                activityIntent.putExtra(PeopleSpaceWidgetProvider.EXTRA_UID, tile.getUid());
+                views.setOnClickPendingIntent(R.id.item, PendingIntent.getActivity(
+                        context,
+                        appWidgetId,
+                        activityIntent,
+                        PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE));
+
+                views.setImageViewBitmap(
+                        R.id.package_icon,
+                        PeopleSpaceUtils.convertDrawableToBitmap(
+                                mPackageManager.getApplicationIcon(tile.getPackageName())
+                        )
+                );
+                views.setImageViewIcon(R.id.person_icon, tile.getUserIcon());
+                // Tell the AppWidgetManager to perform an update on the current app widget.
+                appWidgetManager.updateAppWidget(appWidgetId, views);
+            }
+        } catch (Exception e) {
+            Log.e(TAG, "Failed to retrieve conversations to set tiles");
+        }
+    }
+
+    /** Returns the layout ID for the {@code tile}. */
+    private static int getLayout(PeopleSpaceTile tile) {
+        return tile.getNotification() == null ? R.layout.people_space_large_avatar_tile :
+                R.layout.people_space_small_avatar_tile;
+    }
+
     /** Returns a list sorted by ascending last interaction time from {@code stream}. */
     private static List<Map.Entry<Long, PeopleSpaceTile>> getSortedTiles(
             IPeopleManager peopleManager, Stream<PeopleSpaceTile> stream) {
diff --git a/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetManager.java b/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetManager.java
index 9b7cf6e..ac32e19 100644
--- a/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetManager.java
+++ b/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetManager.java
@@ -16,11 +16,14 @@
 
 package com.android.systemui.people.widget;
 
+import android.app.INotificationManager;
 import android.app.NotificationChannel;
+import android.appwidget.AppWidgetManager;
 import android.content.ComponentName;
 import android.content.Context;
 import android.os.ServiceManager;
 import android.os.UserHandle;
+import android.provider.Settings;
 import android.service.notification.NotificationListenerService;
 import android.service.notification.StatusBarNotification;
 import android.util.Log;
@@ -42,13 +45,18 @@
     private static final boolean DEBUG = PeopleSpaceUtils.DEBUG;
 
     private final Context mContext;
-    private IAppWidgetService mAppWidgetManager;
+    private IAppWidgetService mAppWidgetService;
+    private AppWidgetManager mAppWidgetManager;
+    private INotificationManager mNotificationManager;
 
     @Inject
     public PeopleSpaceWidgetManager(Context context, IAppWidgetService appWidgetService) {
         if (DEBUG) Log.d(TAG, "constructor");
         mContext = context;
-        mAppWidgetManager = appWidgetService;
+        mAppWidgetService = appWidgetService;
+        mAppWidgetManager = AppWidgetManager.getInstance(context);
+        mNotificationManager = INotificationManager.Stub.asInterface(
+                ServiceManager.getService(Context.NOTIFICATION_SERVICE));
     }
 
     /** Constructor used for testing. */
@@ -56,21 +64,24 @@
     protected PeopleSpaceWidgetManager(Context context) {
         if (DEBUG) Log.d(TAG, "constructor");
         mContext = context;
-        mAppWidgetManager = IAppWidgetService.Stub.asInterface(
+        mAppWidgetService = IAppWidgetService.Stub.asInterface(
                 ServiceManager.getService(Context.APPWIDGET_SERVICE));
     }
 
     /** AppWidgetManager setter used for testing. */
     @VisibleForTesting
-    protected void setAppWidgetManager(IAppWidgetService appWidgetService) {
-        mAppWidgetManager = appWidgetService;
+    protected void setAppWidgetManager(IAppWidgetService appWidgetService,
+            AppWidgetManager appWidgetManager, INotificationManager notificationManager) {
+        mAppWidgetService = appWidgetService;
+        mAppWidgetManager = appWidgetManager;
+        mNotificationManager = notificationManager;
     }
 
     /** Updates People Space widgets. */
     public void updateWidgets() {
         try {
             if (DEBUG) Log.d(TAG, "updateWidgets called");
-            int[] widgetIds = mAppWidgetManager.getAppWidgetIds(
+            int[] widgetIds = mAppWidgetService.getAppWidgetIds(
                     new ComponentName(mContext, PeopleSpaceWidgetProvider.class)
             );
 
@@ -80,9 +91,16 @@
             }
 
             if (DEBUG) Log.d(TAG, "updating " + widgetIds.length + " widgets");
-            mAppWidgetManager
-                    .notifyAppWidgetViewDataChanged(mContext.getOpPackageName(), widgetIds,
-                            R.id.widget_list_view);
+            boolean showSingleConversation = Settings.Global.getInt(mContext.getContentResolver(),
+                    Settings.Global.PEOPLE_SPACE_CONVERSATION_TYPE, 0) == 0;
+            if (showSingleConversation) {
+                PeopleSpaceUtils.updateSingleConversationWidgets(mContext, widgetIds,
+                        mAppWidgetManager, mNotificationManager);
+            } else {
+                mAppWidgetService
+                        .notifyAppWidgetViewDataChanged(mContext.getOpPackageName(), widgetIds,
+                                R.id.widget_list_view);
+            }
         } catch (Exception e) {
             Log.e(TAG, "Exception: " + e);
         }
@@ -125,7 +143,8 @@
 
         @Override
         public void onNotificationRankingUpdate(
-                NotificationListenerService.RankingMap rankingMap) { }
+                NotificationListenerService.RankingMap rankingMap) {
+        }
 
         @Override
         public void onNotificationsInitialized() {
diff --git a/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetProvider.java b/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetProvider.java
index 9f84514..1ee9e0e 100644
--- a/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetProvider.java
@@ -16,11 +16,14 @@
 
 package com.android.systemui.people.widget;
 
+import android.app.INotificationManager;
 import android.app.PendingIntent;
 import android.appwidget.AppWidgetManager;
 import android.appwidget.AppWidgetProvider;
 import android.content.Context;
 import android.content.Intent;
+import android.os.ServiceManager;
+import android.provider.Settings;
 import android.util.Log;
 import android.widget.RemoteViews;
 
@@ -41,6 +44,14 @@
         super.onUpdate(context, appWidgetManager, appWidgetIds);
 
         if (DEBUG) Log.d(TAG, "onUpdate called");
+        boolean showSingleConversation = Settings.Global.getInt(context.getContentResolver(),
+                Settings.Global.PEOPLE_SPACE_CONVERSATION_TYPE, 0) == 0;
+        if (showSingleConversation) {
+            PeopleSpaceUtils.updateSingleConversationWidgets(context, appWidgetIds,
+                    appWidgetManager, INotificationManager.Stub.asInterface(
+                            ServiceManager.getService(Context.NOTIFICATION_SERVICE)));
+            return;
+        }
         // Perform this loop procedure for each App Widget that belongs to this provider
         for (int appWidgetId : appWidgetIds) {
             RemoteViews views =
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java b/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java
index 5afe526..3866382 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java
@@ -143,8 +143,6 @@
     }
 
     public void showDeviceMonitoringDialog() {
-        mHost.collapsePanels();
-        // TODO: Delay dialog creation until after panels are collapsed.
         createDialog();
     }
 
@@ -291,6 +289,7 @@
         if (which == DialogInterface.BUTTON_NEGATIVE) {
             final Intent intent = new Intent(Settings.ACTION_ENTERPRISE_PRIVACY_SETTINGS);
             mDialog.dismiss();
+            // This dismisses the shade on opening the activity
             mActivityStarter.postStartActivityDismissingKeyguard(intent, 0);
         }
     }
@@ -605,6 +604,7 @@
         public void onClick(View widget) {
             final Intent intent = new Intent(Settings.ACTION_VPN_SETTINGS);
             mDialog.dismiss();
+            // This dismisses the shade on opening the activity
             mActivityStarter.postStartActivityDismissingKeyguard(intent, 0);
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/FeedbackInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/FeedbackInfo.java
index 4c78e62..149ee8c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/FeedbackInfo.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/FeedbackInfo.java
@@ -19,7 +19,6 @@
 import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
 import static android.service.notification.NotificationListenerService.Ranking.RANKING_DEMOTED;
 import static android.service.notification.NotificationListenerService.Ranking.RANKING_PROMOTED;
-import static android.service.notification.NotificationListenerService.Ranking.RANKING_UNCHANGED;
 
 import android.annotation.SuppressLint;
 import android.app.Notification;
@@ -43,6 +42,7 @@
 import com.android.internal.statusbar.NotificationVisibility;
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
+import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
 import com.android.systemui.statusbar.notification.AssistantFeedbackController;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
@@ -64,6 +64,9 @@
     private NotificationEntryManager mNotificationEntryManager;
     private IStatusBarService mStatusBarService;
     private AssistantFeedbackController mFeedbackController;
+    private NotificationGutsManager mNotificationGutsManager;
+    private NotificationMenuRowPlugin mMenuRowPlugin;
+    private ExpandableNotificationRow mExpandableNotificationRow;
 
     public FeedbackInfo(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -73,19 +76,21 @@
             final PackageManager pm,
             final StatusBarNotification sbn,
             final NotificationEntry entry,
+            final ExpandableNotificationRow row,
             final AssistantFeedbackController controller) {
         mPkg = sbn.getPackageName();
         mPm = pm;
         mEntry = entry;
+        mExpandableNotificationRow = row;
         mRanking = entry.getRanking();
         mFeedbackController = controller;
         mAppName = mPkg;
         mNotificationEntryManager = Dependency.get(NotificationEntryManager.class);
         mStatusBarService = Dependency.get(IStatusBarService.class);
+        mNotificationGutsManager = Dependency.get(NotificationGutsManager.class);
 
         bindHeader();
         bindPrompt();
-        bindButton();
     }
 
     private void bindHeader() {
@@ -161,27 +166,24 @@
         return sb.toString();
     }
 
-    private void bindButton() {
-        TextView ok = findViewById(R.id.ok);
-        ok.setOnClickListener(this::closeControls);
-    }
-
     private void positiveFeedback(View v) {
+        mGutsContainer.closeControls(v, false);
         handleFeedback(true);
     }
 
     private void negativeFeedback(View v) {
+        mMenuRowPlugin = mExpandableNotificationRow.getProvider();
+        NotificationMenuRowPlugin.MenuItem menuItem = null;
+        if (mMenuRowPlugin != null) {
+            menuItem = mMenuRowPlugin.getLongpressMenuItem(mContext);
+        }
+
+        mGutsContainer.closeControls(v, false);
+        mNotificationGutsManager.openGuts(mExpandableNotificationRow, 0, 0, menuItem);
         handleFeedback(false);
     }
 
     private void handleFeedback(boolean positive) {
-        TextView prompt = findViewById(R.id.prompt);
-        prompt.setText(mContext.getString(R.string.feedback_response));
-        TextView yes = findViewById(R.id.yes);
-        yes.setVisibility(View.GONE);
-        TextView no = findViewById(R.id.no);
-        no.setVisibility(View.GONE);
-
         Bundle feedback = new Bundle();
         feedback.putBoolean(FEEDBACK_KEY, positive);
         sendFeedbackToAssistant(feedback);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
index d2cfb29..c4f0098 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
@@ -324,7 +324,7 @@
                 userHandle.getIdentifier());
 
         if (mAssistantFeedbackController.showFeedbackIndicator(row.getEntry())) {
-            feedbackInfo.bindGuts(pmUser, sbn, row.getEntry(), mAssistantFeedbackController);
+            feedbackInfo.bindGuts(pmUser, sbn, row.getEntry(), row, mAssistantFeedbackController);
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationCustomViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationCustomViewWrapper.java
index 4c9c2f9..414d620 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationCustomViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationCustomViewWrapper.java
@@ -47,6 +47,10 @@
     public void onContentUpdated(ExpandableNotificationRow row) {
         super.onContentUpdated(row);
 
+        // Custom views will most likely use just white or black as their text color.
+        // We need to scan through and replace these colors by Material NEXT colors.
+        ensureThemeOnChildren();
+
         // Let's invert the notification colors when we're in night mode and
         // the notification background isn't colorized.
         if (needsInversion(mBackgroundColor, mView)) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationDecoratedCustomViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationDecoratedCustomViewWrapper.java
index 49a8d56..7964845 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationDecoratedCustomViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationDecoratedCustomViewWrapper.java
@@ -43,6 +43,11 @@
         if (childIndex != null && childIndex != -1) {
             mWrappedView = container.getChildAt(childIndex);
         }
+
+        // Custom views will most likely use just white or black as their text color.
+        // We need to scan through and replace these colors by Material NEXT colors.
+        ensureThemeOnChildren();
+
         if (needsInversion(resolveBackgroundColor(), mWrappedView)) {
             invertViewLuminosity(mWrappedView);
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java
index 416c5af..2d706a4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java
@@ -29,11 +29,13 @@
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
 import android.os.Build;
+import android.view.ContextThemeWrapper;
 import android.view.NotificationHeaderView;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.TextView;
 
+import com.android.internal.R;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.graphics.ColorUtils;
 import com.android.internal.util.ContrastColorUtil;
@@ -55,6 +57,9 @@
     private final Rect mTmpRect = new Rect();
 
     protected int mBackgroundColor = 0;
+    private int mLightTextColor;
+    private int mDarkTextColor;
+    private int mDefaultTextColor;
 
     public static NotificationViewWrapper wrap(Context ctx, View v, ExpandableNotificationRow row) {
         if (v.getId() == com.android.internal.R.id.status_bar_latest_event_content) {
@@ -110,6 +115,15 @@
             mBackgroundColor = backgroundColor;
             mView.setBackground(new ColorDrawable(Color.TRANSPARENT));
         }
+        mLightTextColor = mView.getContext().getColor(
+                com.android.internal.R.color.notification_primary_text_color_light);
+        mDarkTextColor = mView.getContext().getColor(
+                R.color.notification_primary_text_color_dark);
+
+        Context themedContext = new ContextThemeWrapper(mView.getContext(),
+                R.style.Theme_DeviceDefault_DayNight);
+        mDefaultTextColor = Utils.getColorAttr(themedContext, R.attr.textColorPrimary)
+                .getDefaultColor();
     }
 
     protected boolean needsInversion(int defaultBackgroundColor, View view) {
@@ -187,6 +201,42 @@
         return false;
     }
 
+    protected void ensureThemeOnChildren() {
+        if (mView == null) {
+            return;
+        }
+
+        // Notifications with custom backgrounds should not be adjusted
+        if (mBackgroundColor != Color.TRANSPARENT
+                || getBackgroundColor(mView) != Color.TRANSPARENT) {
+            return;
+        }
+
+        // Now let's check if there's unprotected text somewhere, and apply the theme if we find it.
+        if (!(mView instanceof ViewGroup)) {
+            return;
+        }
+        processChildrenTextColor((ViewGroup) mView);
+    }
+
+    private void processChildrenTextColor(ViewGroup viewGroup) {
+        if (viewGroup == null) {
+            return;
+        }
+
+        for (int i = 0; i < viewGroup.getChildCount(); i++) {
+            View child = viewGroup.getChildAt(i);
+            if (child instanceof TextView) {
+                int foreground = ((TextView) child).getCurrentTextColor();
+                if (foreground == mLightTextColor || foreground == mDarkTextColor) {
+                    ((TextView) child).setTextColor(mDefaultTextColor);
+                }
+            } else if (child instanceof ViewGroup) {
+                processChildrenTextColor((ViewGroup) child);
+            }
+        }
+    }
+
     protected int getBackgroundColor(View view) {
         if (view == null) {
             return Color.TRANSPARENT;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
index 1a2d1cf..b9e8d74 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
@@ -116,6 +116,11 @@
      */
     private float mDarkAmount;
 
+    /**
+     * How visible the quick settings panel is.
+     */
+    private float mQsExpansion;
+
     private float mEmptyDragAmount;
 
     /**
@@ -159,7 +164,8 @@
     public void setup(int statusBarMinHeight, int maxShadeBottom, int notificationStackHeight,
             float panelExpansion, int parentHeight, int keyguardStatusHeight, int clockPreferredY,
             boolean hasCustomClock, boolean hasVisibleNotifs, float dark, float emptyDragAmount,
-            boolean bypassEnabled, int unlockedStackScrollerPadding, boolean udfpsEnrolled) {
+            boolean bypassEnabled, int unlockedStackScrollerPadding, boolean udfpsEnrolled,
+            float qsExpansion) {
         mMinTopMargin = statusBarMinHeight + (udfpsEnrolled ? mContainerTopPaddingWithoutLockIcon :
                 mContainerTopPaddingWithLockIcon);
         mMaxShadeBottom = maxShadeBottom;
@@ -174,6 +180,7 @@
         mEmptyDragAmount = emptyDragAmount;
         mBypassEnabled = bypassEnabled;
         mUnlockedStackScrollerPadding = unlockedStackScrollerPadding;
+        mQsExpansion = qsExpansion;
     }
 
     public void run(Result result) {
@@ -274,6 +281,7 @@
      */
     private float getClockAlpha(int y) {
         float alphaKeyguard = Math.max(0, y / Math.max(1f, getClockY(1f)));
+        alphaKeyguard *= (1f - mQsExpansion);
         alphaKeyguard = Interpolators.ACCELERATE.getInterpolation(alphaKeyguard);
         return MathUtils.lerp(alphaKeyguard, 1f, mDarkAmount);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
index 84eacdc..01a7292 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
@@ -292,6 +292,7 @@
     private final StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
     private final KeyguardStatusViewComponent.Factory mKeyguardStatusViewComponentFactory;
     private final QSDetailDisplayer mQSDetailDisplayer;
+    private final ScrimController mScrimController;
     // Maximum # notifications to show on Keyguard; extras will be collapsed in an overflow card.
     // If there are exactly 1 + mMaxKeyguardNotifications, then still shows all notifications
     private final int mMaxKeyguardNotifications;
@@ -549,6 +550,7 @@
             NotificationIconAreaController notificationIconAreaController,
             AuthController authController,
             QSDetailDisplayer qsDetailDisplayer,
+            ScrimController scrimController,
             MediaDataManager mediaDataManager) {
         super(view, falsingManager, dozeLog, keyguardStateController,
                 (SysuiStatusBarStateController) statusBarStateController, vibratorHelper,
@@ -579,6 +581,7 @@
         mPulseExpansionHandler = pulseExpansionHandler;
         mDozeParameters = dozeParameters;
         mBiometricUnlockController = biometricUnlockController;
+        mScrimController = scrimController;
         mMediaDataManager = mediaDataManager;
         pulseExpansionHandler.setPulseExpandAbortListener(() -> {
             if (mQs != null) {
@@ -909,7 +912,7 @@
                     clockPreferredY, hasCustomClock(),
                     hasVisibleNotifications, mInterpolatedDarkAmount, mEmptyDragAmount,
                     bypassEnabled, getUnlockedStackScrollerPadding(),
-                    mUpdateMonitor.isUdfpsEnrolled());
+                    mUpdateMonitor.isUdfpsEnrolled(), getQsExpansionFraction());
             mClockPositionAlgorithm.run(mClockPositionResult);
             mKeyguardStatusViewController.updatePosition(
                     mClockPositionResult.clockX, mClockPositionResult.clockY,
@@ -1756,6 +1759,7 @@
         updateHeaderKeyguardAlpha();
         if (mBarState == StatusBarState.SHADE_LOCKED || mBarState == KEYGUARD) {
             updateKeyguardBottomAreaAlpha();
+            positionClockAndNotifications();
             updateBigClockAlpha();
         }
 
@@ -1782,6 +1786,7 @@
         float qsExpansionFraction = getQsExpansionFraction();
         mQs.setQsExpansion(qsExpansionFraction, getHeaderTranslation());
         mMediaHierarchyManager.setQsExpansion(qsExpansionFraction);
+        mScrimController.setQsExpansion(qsExpansionFraction);
         mNotificationStackScrollLayoutController.setQsExpansionFraction(qsExpansionFraction);
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
index 9e7efc1..f8e361f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -125,11 +125,6 @@
      */
     public static final float BUSY_SCRIM_ALPHA = 1f;
 
-    /**
-     * Same as above, but when blur is supported.
-     */
-    public static final float BLUR_SCRIM_ALPHA = 0.80f;
-
     static final int TAG_KEY_ANIM = R.id.scrim;
     private static final int TAG_START_ALPHA = R.id.scrim_alpha_start;
     private static final int TAG_END_ALPHA = R.id.scrim_alpha_end;
@@ -161,6 +156,7 @@
 
     // Assuming the shade is expanded during initialization
     private float mExpansionFraction = 1f;
+    private float mQsExpansion;
 
     private boolean mDarkenWhileDragging;
     private boolean mExpansionAffectsAlpha = true;
@@ -206,8 +202,7 @@
             BlurUtils blurUtils, ConfigurationController configurationController) {
 
         mScrimStateListener = lightBarController::setScrimState;
-        mDefaultScrimAlpha = blurUtils.supportsBlursOnWindows()
-                ? BLUR_SCRIM_ALPHA : BUSY_SCRIM_ALPHA;
+        mDefaultScrimAlpha = BUSY_SCRIM_ALPHA;
         mBlurUtils = blurUtils;
 
         mKeyguardStateController = keyguardStateController;
@@ -464,6 +459,31 @@
 
             boolean relevantState = (mState == ScrimState.UNLOCKED
                     || mState == ScrimState.KEYGUARD
+                    || mState == ScrimState.SHADE_LOCKED
+                    || mState == ScrimState.PULSING
+                    || mState == ScrimState.BUBBLE_EXPANDED);
+            if (!(relevantState && mExpansionAffectsAlpha)) {
+                return;
+            }
+            applyAndDispatchExpansion();
+        }
+    }
+
+    /**
+     * Current state of the QuickSettings expansion when pulling it from the top.
+     *
+     * @param fraction From 0 to 1 where 0 means collapsed and 1 expanded.
+     */
+    public void setQsExpansion(float fraction) {
+        if (isNaN(fraction)) {
+            return;
+        }
+        if (mQsExpansion != fraction) {
+            mQsExpansion = fraction;
+            Log.d(TAG, "set qs fraction");
+
+            boolean relevantState = (mState == ScrimState.SHADE_LOCKED
+                    || mState == ScrimState.KEYGUARD
                     || mState == ScrimState.PULSING
                     || mState == ScrimState.BUBBLE_EXPANDED);
             if (!(relevantState && mExpansionAffectsAlpha)) {
@@ -506,7 +526,8 @@
             behindFraction = (float) Math.pow(behindFraction, 0.8f);
             mBehindAlpha = behindFraction * mDefaultScrimAlpha;
             mInFrontAlpha = 0;
-        } else if (mState == ScrimState.KEYGUARD || mState == ScrimState.PULSING) {
+        } else if (mState == ScrimState.KEYGUARD || mState == ScrimState.SHADE_LOCKED
+                || mState == ScrimState.PULSING) {
             // Either darken of make the scrim transparent when you
             // pull down the shade
             float interpolatedFract = getInterpolatedFraction();
@@ -522,6 +543,11 @@
             }
             mBehindTint = ColorUtils.blendARGB(ScrimState.BOUNCER.getBehindTint(),
                     mState.getBehindTint(), interpolatedFract);
+            if (mQsExpansion > 0) {
+                mBehindAlpha = MathUtils.lerp(mBehindAlpha, mDefaultScrimAlpha, mQsExpansion);
+                mBehindTint = ColorUtils.blendARGB(mBehindTint,
+                        ScrimState.SHADE_LOCKED.getBehindTint(), mQsExpansion);
+            }
         }
         if (isNaN(mBehindAlpha) || isNaN(mInFrontAlpha)) {
             throw new IllegalStateException("Scrim opacity is NaN for state: " + mState
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
index fc91c16..994da79 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
@@ -112,6 +112,15 @@
         }
     },
 
+    SHADE_LOCKED {
+        @Override
+        public void prepare(ScrimState previousState) {
+            mBehindAlpha = mDefaultScrimAlpha;
+            mBubbleAlpha = 0f;
+            mFrontAlpha = 0f;
+        }
+    },
+
     /**
      * Changing screen brightness from quick settings.
      */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 981f9a6..9ebde53 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -4099,6 +4099,8 @@
             mScrimController.transitionTo(ScrimState.UNLOCKED, mUnlockScrimCallback);
         } else if (mBrightnessMirrorVisible) {
             mScrimController.transitionTo(ScrimState.BRIGHTNESS_MIRROR);
+        } else if (mState == StatusBarState.SHADE_LOCKED) {
+            mScrimController.transitionTo(ScrimState.SHADE_LOCKED);
         } else if (mDozeServiceHost.isPulsing()) {
             mScrimController.transitionTo(ScrimState.PULSING,
                     mDozeScrimController.getScrimCallback());
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryStateNotifier.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryStateNotifier.kt
index 92e5b78..27e40e0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryStateNotifier.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryStateNotifier.kt
@@ -56,7 +56,8 @@
 
             val intent = Intent(Intent.ACTION_VIEW,
                     Uri.parse(context.getString(R.string.config_batteryStateUnknownUrl)))
-            val pi = PendingIntent.getActivity(context, 0, intent, 0)
+            val pi = PendingIntent.getActivity(context, 0, intent,
+                    PendingIntent.FLAG_IMMUTABLE)
 
             val builder = Notification.Builder(context, channel.id)
                     .setAutoCancel(false)
@@ -87,4 +88,4 @@
 
 private const val TAG = "BatteryStateNotifier"
 private const val ID = 666
-private const val DELAY_MILLIS: Long = 4 * 60 * 60 * 1000
\ No newline at end of file
+private const val DELAY_MILLIS: Long = 4 * 60 * 60 * 1000
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java
index a879a1e..2a18f3c5 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java
@@ -168,6 +168,11 @@
 
         mConfigurationController.addCallback(new ConfigurationController.ConfigurationListener() {
             @Override
+            public void onConfigChanged(Configuration newConfig) {
+                pip.onConfigurationChanged(newConfig);
+            }
+
+            @Override
             public void onDensityOrFontScaleChanged() {
                 pip.onDensityOrFontScaleChanged();
             }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationModeSwitchTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationModeSwitchTest.java
index 1115043..0451d45 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationModeSwitchTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationModeSwitchTest.java
@@ -143,6 +143,13 @@
     }
 
     @Test
+    public void showButton_excludeSystemGestureArea() {
+        mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW);
+
+        verify(mSpyImageView).setSystemGestureExclusionRects(any(List.class));
+    }
+
+    @Test
     public void showMagnificationButton_setA11yTimeout_postDelayedAnimationWithA11yTimeout() {
         final int a11yTimeout = 12345;
         when(mAccessibilityManager.getRecommendedTimeoutMillis(anyInt(), anyInt())).thenReturn(
@@ -178,14 +185,17 @@
     }
 
     @Test
-    public void onConfigurationChanged_buttonIsShowing_setImageResource() {
+    public void onConfigurationChanged_buttonIsShowing_updateResourcesAndLayout() {
         mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN);
         resetAndStubMockImageViewAndAnimator();
 
         mMagnificationModeSwitch.onConfigurationChanged(ActivityInfo.CONFIG_DENSITY);
 
+        verify(mSpyImageView).setPadding(anyInt(), anyInt(), anyInt(), anyInt());
         verify(mSpyImageView).setImageResource(
                 getIconResId(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN));
+        verify(mWindowManager).updateViewLayout(eq(mSpyImageView), any());
+        verify(mSpyImageView).setSystemGestureExclusionRects(any(List.class));
     }
 
     @Test
@@ -368,6 +378,11 @@
     private void resetAndStubMockImageViewAndAnimator() {
         resetAndStubMockAnimator();
         Mockito.reset(mSpyImageView);
+        doAnswer(invocation -> {
+            final Runnable runnable = invocation.getArgument(0);
+            runnable.run();
+            return null;
+        }).when(mSpyImageView).post(any(Runnable.class));
         doReturn(mViewPropertyAnimator).when(mSpyImageView).animate();
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/people/widget/PeopleSpaceWidgetManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/people/widget/PeopleSpaceWidgetManagerTest.java
index 477fe63..019424c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/people/widget/PeopleSpaceWidgetManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/people/widget/PeopleSpaceWidgetManagerTest.java
@@ -29,12 +29,20 @@
 
 import static java.util.Objects.requireNonNull;
 
+import android.app.INotificationManager;
 import android.app.NotificationChannel;
-import android.content.Context;
+import android.appwidget.AppWidgetManager;
+import android.content.SharedPreferences;
+import android.content.pm.ParceledListSlice;
+import android.content.pm.ShortcutInfo;
 import android.os.RemoteException;
 import android.os.UserHandle;
+import android.provider.Settings;
+import android.service.notification.ConversationChannelWrapper;
 import android.testing.AndroidTestingRunner;
+import android.widget.RemoteViews;
 
+import androidx.preference.PreferenceManager;
 import androidx.test.filters.SmallTest;
 
 import com.android.internal.appwidget.IAppWidgetService;
@@ -54,6 +62,9 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
+import java.util.ArrayList;
+import java.util.List;
+
 @SmallTest
 @RunWith(AndroidTestingRunner.class)
 public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
@@ -65,14 +76,23 @@
     private static final String TEST_CHANNEL_NAME = "channel_name";
     private static final String TEST_PARENT_CHANNEL_ID = "parent_channel_id";
     private static final String TEST_CONVERSATION_ID = "conversation_id";
+    private static final int WIDGET_ID_WITH_SHORTCUT = 1;
+    private static final int WIDGET_ID_WITHOUT_SHORTCUT = 2;
+    private static final String SHORTCUT_ID = "101";
 
     private PeopleSpaceWidgetManager mManager;
 
-    @Mock private NotificationListener mListenerService;
-    @Mock private IAppWidgetService mIAppWidgetService;
-    @Mock private Context mContext;
+    @Mock
+    private NotificationListener mListenerService;
+    @Mock
+    private IAppWidgetService mIAppWidgetService;
+    @Mock
+    private AppWidgetManager mAppWidgetManager;
+    @Mock
+    private INotificationManager mINotificationManager;
 
-    @Captor private ArgumentCaptor<NotificationHandler> mListenerCaptor;
+    @Captor
+    private ArgumentCaptor<NotificationHandler> mListenerCaptor;
 
     private final NoManSimulator mNoMan = new NoManSimulator();
     private final FakeSystemClock mClock = new FakeSystemClock();
@@ -80,18 +100,18 @@
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
-
         mManager =
                 new PeopleSpaceWidgetManager(mContext);
-        mManager.setAppWidgetManager(mIAppWidgetService);
+        mManager.setAppWidgetManager(mIAppWidgetService, mAppWidgetManager, mINotificationManager);
         mManager.attach(mListenerService);
 
         verify(mListenerService).addNotificationHandler(mListenerCaptor.capture());
         NotificationHandler serviceListener = requireNonNull(mListenerCaptor.getValue());
         mNoMan.addListener(serviceListener);
+        Settings.Global.putInt(mContext.getContentResolver(),
+                Settings.Global.PEOPLE_SPACE_CONVERSATION_TYPE, 2);
     }
 
-
     @Test
     public void testDoNotNotifyAppWidgetIfNoWidgets() throws RemoteException {
         int[] widgetIdsArray = {};
@@ -105,7 +125,24 @@
 
         verify(mIAppWidgetService, times(1)).getAppWidgetIds(any());
         verify(mIAppWidgetService, never()).notifyAppWidgetViewDataChanged(any(), any(), anyInt());
+    }
 
+    @Test
+    public void testDoNotNotifySingleConversationAppWidgetIfNoWidgets() throws RemoteException {
+        Settings.Global.putInt(mContext.getContentResolver(),
+                Settings.Global.PEOPLE_SPACE_CONVERSATION_TYPE, 0);
+        int[] widgetIdsArray = {};
+        when(mIAppWidgetService.getAppWidgetIds(any())).thenReturn(widgetIdsArray);
+
+        NotifEvent notif1 = mNoMan.postNotif(
+                new NotificationEntryBuilder()
+                        .setId(0)
+                        .setPkg(TEST_PACKAGE_A));
+        mClock.advanceTime(MIN_LINGER_DURATION);
+
+        verify(mIAppWidgetService, times(1)).getAppWidgetIds(any());
+        verify(mAppWidgetManager, never()).updateAppWidget(anyInt(), any(RemoteViews.class));
+        verify(mIAppWidgetService, never()).notifyAppWidgetViewDataChanged(any(), any(), anyInt());
     }
 
     @Test
@@ -122,7 +159,66 @@
         verify(mIAppWidgetService, times(1)).getAppWidgetIds(any());
         verify(mIAppWidgetService, times(1))
                 .notifyAppWidgetViewDataChanged(any(), eq(widgetIdsArray), anyInt());
+        verify(mIAppWidgetService, never()).updateAppWidgetIds(any(), any(),
+                any(RemoteViews.class));
+    }
 
+    @Test
+    public void testNotifySingleConversationAppWidgetOnceIfNotificationPosted()
+            throws RemoteException {
+        Settings.Global.putInt(mContext.getContentResolver(),
+                Settings.Global.PEOPLE_SPACE_CONVERSATION_TYPE, 0);
+        when(mINotificationManager.getConversations(true)).thenReturn(
+                new ParceledListSlice(getConversationWithShortcutId()));
+        int[] widgetIdsArray = {WIDGET_ID_WITH_SHORTCUT, WIDGET_ID_WITHOUT_SHORTCUT};
+        SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mContext);
+        SharedPreferences.Editor editor = sp.edit();
+        editor.putString(String.valueOf(WIDGET_ID_WITH_SHORTCUT), SHORTCUT_ID);
+        editor.commit();
+        when(mIAppWidgetService.getAppWidgetIds(any())).thenReturn(widgetIdsArray);
+
+        NotifEvent notif1 = mNoMan.postNotif(new NotificationEntryBuilder()
+                .setPkg(TEST_PACKAGE_A)
+                .setId(1));
+
+        verify(mIAppWidgetService, times(1)).getAppWidgetIds(any());
+        verify(mIAppWidgetService, never())
+                .notifyAppWidgetViewDataChanged(any(), eq(widgetIdsArray), anyInt());
+        verify(mAppWidgetManager, times(1)).updateAppWidget(eq(WIDGET_ID_WITH_SHORTCUT),
+                any(RemoteViews.class));
+        verify(mAppWidgetManager, never()).updateAppWidget(eq(WIDGET_ID_WITHOUT_SHORTCUT),
+                any(RemoteViews.class));
+    }
+
+    @Test
+    public void testNotifySingleConversationAppWidgetTwiceIfTwoNotificationsPosted()
+            throws RemoteException {
+        Settings.Global.putInt(mContext.getContentResolver(),
+                Settings.Global.PEOPLE_SPACE_CONVERSATION_TYPE, 0);
+        when(mINotificationManager.getConversations(true)).thenReturn(
+                new ParceledListSlice(getConversationWithShortcutId()));
+        int[] widgetIdsArray = {WIDGET_ID_WITH_SHORTCUT, WIDGET_ID_WITHOUT_SHORTCUT};
+        SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mContext);
+        SharedPreferences.Editor editor = sp.edit();
+        editor.putString(String.valueOf(WIDGET_ID_WITH_SHORTCUT), SHORTCUT_ID);
+        editor.commit();
+        when(mIAppWidgetService.getAppWidgetIds(any())).thenReturn(widgetIdsArray);
+
+        NotifEvent notif1 = mNoMan.postNotif(new NotificationEntryBuilder()
+                .setPkg(TEST_PACKAGE_A)
+                .setId(1));
+        mClock.advanceTime(4);
+        NotifEvent notif2 = mNoMan.postNotif(new NotificationEntryBuilder()
+                .setPkg(TEST_PACKAGE_B)
+                .setId(2));
+
+        verify(mIAppWidgetService, times(2)).getAppWidgetIds(any());
+        verify(mIAppWidgetService, never())
+                .notifyAppWidgetViewDataChanged(any(), eq(widgetIdsArray), anyInt());
+        verify(mAppWidgetManager, times(2)).updateAppWidget(eq(WIDGET_ID_WITH_SHORTCUT),
+                any(RemoteViews.class));
+        verify(mAppWidgetManager, never()).updateAppWidget(eq(WIDGET_ID_WITHOUT_SHORTCUT),
+                any(RemoteViews.class));
     }
 
     @Test
@@ -141,6 +237,8 @@
         verify(mIAppWidgetService, times(2)).getAppWidgetIds(any());
         verify(mIAppWidgetService, times(2))
                 .notifyAppWidgetViewDataChanged(any(), eq(widgetIdsArray), anyInt());
+        verify(mAppWidgetManager, never()).updateAppWidget(anyInt(),
+                any(RemoteViews.class));
     }
 
     @Test
@@ -157,6 +255,8 @@
         verify(mIAppWidgetService, times(2)).getAppWidgetIds(any());
         verify(mIAppWidgetService, times(2))
                 .notifyAppWidgetViewDataChanged(any(), eq(widgetIdsArray), anyInt());
+        verify(mAppWidgetManager, never()).updateAppWidget(anyInt(),
+                any(RemoteViews.class));
     }
 
     @Test
@@ -173,7 +273,8 @@
 
         verify(mIAppWidgetService, never()).getAppWidgetIds(any());
         verify(mIAppWidgetService, never()).notifyAppWidgetViewDataChanged(any(), any(), anyInt());
-
+        verify(mAppWidgetManager, never()).updateAppWidget(anyInt(),
+                any(RemoteViews.class));
     }
 
     @Test
@@ -192,6 +293,17 @@
         verify(mIAppWidgetService, times(1)).getAppWidgetIds(any());
         verify(mIAppWidgetService, times(1))
                 .notifyAppWidgetViewDataChanged(any(), eq(widgetIdsArray), anyInt());
+        verify(mAppWidgetManager, never()).updateAppWidget(anyInt(),
+                any(RemoteViews.class));
+    }
 
+    /** Returns a list of a single conversation associated with {@code SHORTCUT_ID}. */
+    private List<ConversationChannelWrapper> getConversationWithShortcutId() {
+        List<ConversationChannelWrapper> convos = new ArrayList<>();
+        ConversationChannelWrapper convo1 = new ConversationChannelWrapper();
+        convo1.setShortcutInfo(new ShortcutInfo.Builder(mContext, SHORTCUT_ID).setLongLabel(
+                "name").build());
+        convos.add(convo1);
+        return convos;
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationUiAdjustmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationUiAdjustmentTest.java
index 3c9c9cc..353647b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationUiAdjustmentTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationUiAdjustmentTest.java
@@ -39,8 +39,11 @@
 
     @Test
     public void needReinflate_differentLength() {
+        // TODO(b/174258598) Please replace FLAG_MUTABLE_UNAUDITED below
+        // with either FLAG_IMMUTABLE (recommended) or FLAG_MUTABLE.
         PendingIntent pendingIntent =
-                PendingIntent.getActivity(mContext, 0, new Intent(), 0);
+                PendingIntent.getActivity(mContext, 0, new Intent(),
+                        PendingIntent.FLAG_MUTABLE_UNAUDITED);
         Notification.Action action =
                 createActionBuilder("first", R.drawable.ic_corp_icon, pendingIntent).build();
         assertThat(NotificationUiAdjustment.needReinflate(
@@ -51,8 +54,11 @@
 
     @Test
     public void needReinflate_differentLabels() {
+        // TODO(b/174258598) Please replace FLAG_MUTABLE_UNAUDITED below
+        // with either FLAG_IMMUTABLE (recommended) or FLAG_MUTABLE.
         PendingIntent pendingIntent =
-                PendingIntent.getActivity(mContext, 0, new Intent(), 0);
+                PendingIntent.getActivity(mContext, 0, new Intent(),
+                        PendingIntent.FLAG_MUTABLE_UNAUDITED);
         Notification.Action firstAction =
                 createActionBuilder("first", R.drawable.ic_corp_icon, pendingIntent).build();
         Notification.Action secondAction =
@@ -66,8 +72,11 @@
 
     @Test
     public void needReinflate_differentIcons() {
+        // TODO(b/174258598) Please replace FLAG_MUTABLE_UNAUDITED below
+        // with either FLAG_IMMUTABLE (recommended) or FLAG_MUTABLE.
         PendingIntent pendingIntent =
-                PendingIntent.getActivity(mContext, 0, new Intent(), 0);
+                PendingIntent.getActivity(mContext, 0, new Intent(),
+                        PendingIntent.FLAG_MUTABLE_UNAUDITED);
         Notification.Action firstAction =
                 createActionBuilder("same", R.drawable.ic_corp_icon, pendingIntent).build();
         Notification.Action secondAction =
@@ -82,10 +91,14 @@
 
     @Test
     public void needReinflate_differentPendingIntent() {
+        // TODO(b/174258598) Please replace FLAG_MUTABLE_UNAUDITED below
+        // with either FLAG_IMMUTABLE (recommended) or FLAG_MUTABLE.
         PendingIntent firstPendingIntent =
-                PendingIntent.getActivity(mContext, 0, new Intent(Intent.ACTION_VIEW), 0);
+                PendingIntent.getActivity(mContext, 0, new Intent(Intent.ACTION_VIEW),
+                        PendingIntent.FLAG_MUTABLE_UNAUDITED);
         PendingIntent secondPendingIntent =
-                PendingIntent.getActivity(mContext, 0, new Intent(Intent.ACTION_PROCESS_TEXT), 0);
+                PendingIntent.getActivity(mContext, 0, new Intent(Intent.ACTION_PROCESS_TEXT),
+                        PendingIntent.FLAG_MUTABLE_UNAUDITED);
         Notification.Action firstAction =
                 createActionBuilder("same", R.drawable.ic_corp_icon, firstPendingIntent)
                         .build();
@@ -101,8 +114,11 @@
 
     @Test
     public void needReinflate_differentChoices() {
+        // TODO(b/174258598) Please replace FLAG_MUTABLE_UNAUDITED below
+        // with either FLAG_IMMUTABLE (recommended) or FLAG_MUTABLE.
         PendingIntent pendingIntent =
-                PendingIntent.getActivity(mContext, 0, new Intent(), 0);
+                PendingIntent.getActivity(mContext, 0, new Intent(),
+                        PendingIntent.FLAG_MUTABLE_UNAUDITED);
 
         RemoteInput firstRemoteInput =
                 createRemoteInput("same", "same", new CharSequence[] {"first"});
@@ -126,8 +142,11 @@
 
     @Test
     public void needReinflate_differentRemoteInputLabel() {
+        // TODO(b/174258598) Please replace FLAG_MUTABLE_UNAUDITED below
+        // with either FLAG_IMMUTABLE (recommended) or FLAG_MUTABLE.
         PendingIntent pendingIntent =
-                PendingIntent.getActivity(mContext, 0, new Intent(), 0);
+                PendingIntent.getActivity(mContext, 0, new Intent(),
+                        PendingIntent.FLAG_MUTABLE_UNAUDITED);
 
         RemoteInput firstRemoteInput =
                 createRemoteInput("same", "first", new CharSequence[] {"same"});
@@ -151,8 +170,11 @@
 
     @Test
     public void needReinflate_negative() {
+        // TODO(b/174258598) Please replace FLAG_MUTABLE_UNAUDITED below
+        // with either FLAG_IMMUTABLE (recommended) or FLAG_MUTABLE.
         PendingIntent pendingIntent =
-                PendingIntent.getActivity(mContext, 0, new Intent(), 0);
+                PendingIntent.getActivity(mContext, 0, new Intent(),
+                        PendingIntent.FLAG_MUTABLE_UNAUDITED);
         RemoteInput firstRemoteInput =
                 createRemoteInput("same", "same", new CharSequence[] {"same"});
         RemoteInput secondRemoteInput =
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
index 0be9f7d..b0e17cd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
@@ -629,7 +629,10 @@
         return new Notification.Action.Builder(
                 Icon.createWithResource(getContext(), android.R.drawable.sym_def_app_icon),
                 "action",
-                PendingIntent.getBroadcast(getContext(), 0, new Intent("Action"), 0)).build();
+                // TODO(b/174935104) Please replace FLAG_MUTABLE_UNAUDITED below
+                // with either FLAG_IMMUTABLE (recommended) or FLAG_MUTABLE.
+                PendingIntent.getBroadcast(getContext(), 0, new Intent("Action"),
+                    PendingIntent.FLAG_MUTABLE_UNAUDITED)).build();
     }
 
     private static class FakeNotificationLifetimeExtender implements NotificationLifetimeExtender {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationEntryTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationEntryTest.java
index 1a022ec..01b3d8e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationEntryTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationEntryTest.java
@@ -233,7 +233,10 @@
         return new Notification.Action.Builder(
                 Icon.createWithResource(getContext(), android.R.drawable.sym_def_app_icon),
                 title,
-                PendingIntent.getBroadcast(getContext(), 0, new Intent("Action"), 0))
+                // TODO(b/174965424) Please replace FLAG_MUTABLE_UNAUDITED below
+                // with either FLAG_IMMUTABLE (recommended) or FLAG_MUTABLE.
+                PendingIntent.getBroadcast(getContext(), 0, new Intent("Action"),
+                    PendingIntent.FLAG_MUTABLE_UNAUDITED))
                 .setContextual(true)
                 .build();
     }
@@ -242,7 +245,10 @@
         return new Notification.Action.Builder(
                 Icon.createWithResource(getContext(), android.R.drawable.sym_def_app_icon),
                 title,
-                PendingIntent.getBroadcast(getContext(), 0, new Intent("Action"), 0)).build();
+                // TODO(b/174965424) Please replace FLAG_MUTABLE_UNAUDITED below
+                // with either FLAG_IMMUTABLE (recommended) or FLAG_MUTABLE.
+                PendingIntent.getBroadcast(getContext(), 0, new Intent("Action"),
+                    PendingIntent.FLAG_MUTABLE_UNAUDITED)).build();
     }
 
     private ArrayList<Notification.Action> createActions(String... titles) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImplTest.java
index e254cd2..d606316 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImplTest.java
@@ -476,7 +476,10 @@
 
     private NotificationEntry createBubble() {
         Notification.BubbleMetadata data = new Notification.BubbleMetadata.Builder(
-                PendingIntent.getActivity(mContext, 0, new Intent(), 0),
+                // TODO(b/174970399) Please replace FLAG_MUTABLE_UNAUDITED below
+                // with either FLAG_IMMUTABLE (recommended) or FLAG_MUTABLE.
+                PendingIntent.getActivity(mContext, 0, new Intent(),
+                    PendingIntent.FLAG_MUTABLE_UNAUDITED),
                         Icon.createWithResource(mContext.getResources(), R.drawable.android))
                 .build();
         Notification n = new Notification.Builder(getContext(), "a")
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/FeedbackInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/FeedbackInfoTest.java
index 738ce53..9d87579 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/FeedbackInfoTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/FeedbackInfoTest.java
@@ -28,7 +28,6 @@
 import static junit.framework.Assert.assertTrue;
 
 import static org.mockito.Mockito.any;
-import static org.mockito.Mockito.anyBoolean;
 import static org.mockito.Mockito.anyInt;
 import static org.mockito.Mockito.anyString;
 import static org.mockito.Mockito.eq;
@@ -56,6 +55,7 @@
 import com.android.internal.statusbar.IStatusBarService;
 import com.android.systemui.R;
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
 import com.android.systemui.statusbar.notification.AssistantFeedbackController;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
@@ -65,8 +65,7 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
-
-import java.util.concurrent.CountDownLatch;
+import org.mockito.MockitoAnnotations;
 
 @SmallTest
 @RunWith(AndroidTestingRunner.class)
@@ -78,18 +77,24 @@
     private FeedbackInfo mFeedbackInfo;
     private final PackageManager mMockPackageManager = mock(PackageManager.class);
     private final NotificationGuts mGutsParent = mock(NotificationGuts.class);
+    private final ExpandableNotificationRow mMockNotificationRow =
+            mock(ExpandableNotificationRow.class);
     private StatusBarNotification mSbn;
 
     @Mock
     private NotificationEntryManager mNotificationEntryManager;
     @Mock
     private IStatusBarService mStatusBarService;
+    @Mock
+    private NotificationGutsManager mNotificationGutsManager;
 
     @Before
     public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
 
         mDependency.injectTestDependency(NotificationEntryManager.class, mNotificationEntryManager);
         mDependency.injectTestDependency(IStatusBarService.class, mStatusBarService);
+        mDependency.injectTestDependency(NotificationGutsManager.class, mNotificationGutsManager);
 
         // Inflate the layout
         final LayoutInflater layoutInflater = LayoutInflater.from(mContext);
@@ -108,13 +113,14 @@
 
         mSbn = new StatusBarNotification(TEST_PACKAGE_NAME, TEST_PACKAGE_NAME, 0, null, TEST_UID, 0,
                 new Notification(), UserHandle.CURRENT, null, 0);
+
     }
 
     @Test
     public void testBindNotification_SetsTextApplicationName() {
         when(mMockPackageManager.getApplicationLabel(any())).thenReturn("App Name");
         mFeedbackInfo.bindGuts(mMockPackageManager, mSbn, getEntry(),
-                mock(AssistantFeedbackController.class));
+                mMockNotificationRow, mock(AssistantFeedbackController.class));
         final TextView textView = mFeedbackInfo.findViewById(R.id.pkg_name);
         assertTrue(textView.getText().toString().contains("App Name"));
     }
@@ -125,27 +131,16 @@
         when(mMockPackageManager.getApplicationIcon(any(ApplicationInfo.class)))
                 .thenReturn(iconDrawable);
         mFeedbackInfo.bindGuts(mMockPackageManager, mSbn, getEntry(),
-                mock(AssistantFeedbackController.class));
+                mMockNotificationRow, mock(AssistantFeedbackController.class));
         final ImageView iconView = mFeedbackInfo.findViewById(R.id.pkg_icon);
         assertEquals(iconDrawable, iconView.getDrawable());
     }
 
     @Test
-    public void testOk() {
-        final CountDownLatch latch = new CountDownLatch(1);
-        mFeedbackInfo.bindGuts(mMockPackageManager, mSbn, getEntry(),
-                mock(AssistantFeedbackController.class));
-
-        final View okButton = mFeedbackInfo.findViewById(R.id.ok);
-        okButton.performClick();
-        assertEquals(1, latch.getCount());
-        verify(mGutsParent, times(1)).closeControls(any(), anyBoolean());
-    }
-
-    @Test
     public void testPrompt_silenced() {
         mFeedbackInfo.bindGuts(mMockPackageManager, mSbn, getEntry(IMPORTANCE_DEFAULT,
-                IMPORTANCE_LOW, RANKING_UNCHANGED), mock(AssistantFeedbackController.class));
+                IMPORTANCE_LOW, RANKING_UNCHANGED), mMockNotificationRow,
+                mock(AssistantFeedbackController.class));
         TextView prompt = mFeedbackInfo.findViewById(R.id.prompt);
         assertEquals("This notification was silenced by the system. Was this correct?",
                 prompt.getText());
@@ -154,7 +149,8 @@
     @Test
     public void testPrompt_promoted_importance() {
         mFeedbackInfo.bindGuts(mMockPackageManager, mSbn, getEntry(IMPORTANCE_DEFAULT,
-                IMPORTANCE_HIGH, RANKING_UNCHANGED), mock(AssistantFeedbackController.class));
+                IMPORTANCE_HIGH, RANKING_UNCHANGED), mMockNotificationRow,
+                mock(AssistantFeedbackController.class));
         TextView prompt = mFeedbackInfo.findViewById(R.id.prompt);
         assertEquals("This notification was promoted by the system. Was this correct?",
                 prompt.getText());
@@ -163,7 +159,8 @@
     @Test
     public void testPrompt_promoted_ranking() {
         mFeedbackInfo.bindGuts(mMockPackageManager, mSbn, getEntry(IMPORTANCE_DEFAULT,
-                IMPORTANCE_DEFAULT, RANKING_PROMOTED), mock(AssistantFeedbackController.class));
+                IMPORTANCE_DEFAULT, RANKING_PROMOTED), mMockNotificationRow,
+                mock(AssistantFeedbackController.class));
         TextView prompt = mFeedbackInfo.findViewById(R.id.prompt);
         assertEquals("This notification was promoted by the system. Was this correct?",
                 prompt.getText());
@@ -172,7 +169,8 @@
     @Test
     public void testPrompt_demoted_importance() {
         mFeedbackInfo.bindGuts(mMockPackageManager, mSbn, getEntry(IMPORTANCE_LOW,
-                IMPORTANCE_MIN, RANKING_UNCHANGED), mock(AssistantFeedbackController.class));
+                IMPORTANCE_MIN, RANKING_UNCHANGED), mMockNotificationRow,
+                mock(AssistantFeedbackController.class));
         TextView prompt = mFeedbackInfo.findViewById(R.id.prompt);
         assertEquals("This notification was demoted by the system. Was this correct?",
                 prompt.getText());
@@ -181,12 +179,43 @@
     @Test
     public void testPrompt_demoted_ranking() {
         mFeedbackInfo.bindGuts(mMockPackageManager, mSbn, getEntry(IMPORTANCE_DEFAULT,
-                IMPORTANCE_DEFAULT, RANKING_DEMOTED), mock(AssistantFeedbackController.class));
+                IMPORTANCE_DEFAULT, RANKING_DEMOTED), mMockNotificationRow,
+                mock(AssistantFeedbackController.class));
         TextView prompt = mFeedbackInfo.findViewById(R.id.prompt);
         assertEquals("This notification was demoted by the system. Was this correct?",
                 prompt.getText());
     }
 
+    @Test
+    public void testPositiveFeedback() {
+        mFeedbackInfo.bindGuts(mMockPackageManager, mSbn, getEntry(), mMockNotificationRow,
+                mock(AssistantFeedbackController.class));
+
+        final View yes = mFeedbackInfo.findViewById(R.id.yes);
+        yes.performClick();
+        verify(mGutsParent, times(1)).closeControls(yes, false);
+    }
+
+    @Test
+    public void testNegativeFeedback() {
+        when(mNotificationGutsManager.openGuts(
+                any(View.class),
+                anyInt(),
+                anyInt(),
+                any(NotificationMenuRowPlugin.MenuItem.class)))
+                .thenReturn(true);
+
+        mFeedbackInfo.bindGuts(mMockPackageManager, mSbn, getEntry(), mMockNotificationRow,
+                mock(AssistantFeedbackController.class));
+
+        final View no = mFeedbackInfo.findViewById(R.id.no);
+        no.performClick();
+        verify(mGutsParent, times(1)).closeControls(no, false);
+        verify(mNotificationGutsManager, times(1)).openGuts(
+                eq(mMockNotificationRow), eq(0), eq(0),
+                any());
+    }
+
     private NotificationEntry getEntry(int oldImportance, int newImportance,
             int rankingAdjustment) {
         NotificationChannel channel = new NotificationChannel("id", "name", oldImportance);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentViewTest.java
index d08b2b7..2101ea1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentViewTest.java
@@ -81,12 +81,15 @@
         View mockContracted = mock(NotificationHeaderView.class);
         when(mockContracted.findViewById(com.android.internal.R.id.feedback))
                 .thenReturn(mockContracted);
+        when(mockContracted.getContext()).thenReturn(mContext);
         View mockExpanded = mock(NotificationHeaderView.class);
         when(mockExpanded.findViewById(com.android.internal.R.id.feedback))
                 .thenReturn(mockExpanded);
+        when(mockExpanded.getContext()).thenReturn(mContext);
         View mockHeadsUp = mock(NotificationHeaderView.class);
         when(mockHeadsUp.findViewById(com.android.internal.R.id.feedback))
                 .thenReturn(mockHeadsUp);
+        when(mockHeadsUp.getContext()).thenReturn(mContext);
 
         mView.setContractedChild(mockContracted);
         mView.setExpandedChild(mockExpanded);
@@ -107,18 +110,21 @@
         when(mockContracted.animate()).thenReturn(mock(ViewPropertyAnimator.class));
         when(mockContracted.findViewById(com.android.internal.R.id.expand_button)).thenReturn(
                 mockContractedEB);
+        when(mockContracted.getContext()).thenReturn(mContext);
 
         View mockExpandedEB = mock(NotificationExpandButton.class);
         View mockExpanded = mock(NotificationHeaderView.class);
         when(mockExpanded.animate()).thenReturn(mock(ViewPropertyAnimator.class));
         when(mockExpanded.findViewById(com.android.internal.R.id.expand_button)).thenReturn(
                 mockExpandedEB);
+        when(mockExpanded.getContext()).thenReturn(mContext);
 
         View mockHeadsUpEB = mock(NotificationExpandButton.class);
         View mockHeadsUp = mock(NotificationHeaderView.class);
         when(mockHeadsUp.animate()).thenReturn(mock(ViewPropertyAnimator.class));
         when(mockHeadsUp.findViewById(com.android.internal.R.id.expand_button)).thenReturn(
                 mockHeadsUpEB);
+        when(mockHeadsUp.getContext()).thenReturn(mContext);
 
         // Set up all 3 child forms
         mView.setContractedChild(mockContracted);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfoTest.java
index f7dfe0b..1387a63 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfoTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfoTest.java
@@ -213,8 +213,11 @@
                 notification, UserHandle.CURRENT, null, 0);
         mEntry = new NotificationEntryBuilder().setSbn(mSbn).setShortcutInfo(mShortcutInfo).build();
 
+        // TODO(b/175005650) Please replace FLAG_MUTABLE_UNAUDITED below
+        // with either FLAG_IMMUTABLE (recommended) or FLAG_MUTABLE.
         PendingIntent bubbleIntent = PendingIntent.getActivity(mContext, 0,
-                new Intent(mContext, BubblesTestActivity.class), 0);
+                new Intent(mContext, BubblesTestActivity.class),
+                PendingIntent.FLAG_MUTABLE_UNAUDITED);
         mBubbleSbn = new SbnBuilder(mSbn).setBubbleMetadata(
                 new Notification.BubbleMetadata.Builder(bubbleIntent,
                         Icon.createWithResource(mContext, R.drawable.android)).build())
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java
index 7470a13..43ba844 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java
@@ -455,7 +455,10 @@
 
     private BubbleMetadata makeBubbleMetadata(PendingIntent deleteIntent) {
         Intent target = new Intent(mContext, BubblesTestActivity.class);
-        PendingIntent bubbleIntent = PendingIntent.getActivity(mContext, 0, target, 0);
+        // TODO(b/175014468) Please replace FLAG_MUTABLE_UNAUDITED below
+        // with either FLAG_IMMUTABLE (recommended) or FLAG_MUTABLE.
+        PendingIntent bubbleIntent = PendingIntent.getActivity(mContext, 0, target,
+                PendingIntent.FLAG_MUTABLE_UNAUDITED);
 
         return new BubbleMetadata.Builder(bubbleIntent,
                         Icon.createWithResource(mContext, R.drawable.android))
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapperTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapperTest.java
index 085bd90..93a9e59 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapperTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapperTest.java
@@ -17,6 +17,7 @@
 package com.android.systemui.statusbar.notification.row.wrapper;
 
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
 
 import android.content.Context;
 import android.testing.AndroidTestingRunner;
@@ -49,6 +50,7 @@
     public void setup() throws Exception {
         allowTestableLooperAsMainThread();
         mView = mock(View.class);
+        when(mView.getContext()).thenReturn(mContext);
         NotificationTestHelper helper = new NotificationTestHelper(
                 mContext,
                 mDependency,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java
index 83ef87a..c7c1823 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java
@@ -19,7 +19,6 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import android.testing.AndroidTestingRunner;
-import android.testing.TestableLooper;
 
 import androidx.test.filters.SmallTest;
 
@@ -31,7 +30,6 @@
 
 @SmallTest
 @RunWith(AndroidTestingRunner.class)
[email protected]
 public class KeyguardClockPositionAlgorithmTest extends SysuiTestCase {
 
     private static final int SCREEN_HEIGHT = 2000;
@@ -53,6 +51,7 @@
     private int mPreferredClockY;
     private boolean mHasCustomClock;
     private boolean mHasVisibleNotifs;
+    private float mQsExpansion;
 
     @Before
     public void setUp() {
@@ -355,6 +354,17 @@
     }
 
     @Test
+    public void clockHiddenWhenQsIsExpanded() {
+        // GIVEN on the lock screen with a custom clock and visible notifications
+        givenLockScreen();
+        mQsExpansion = 1;
+        // WHEN the clock position algorithm is run
+        positionClock();
+        // THEN the clock Y position is the middle of the screen (SCREEN_HEIGHT / 2).
+        assertThat(mClockPosition.clockAlpha).isEqualTo(TRANSPARENT);
+    }
+
+    @Test
     public void preferredCustomClockPositionWithVisibleNotificationsOnAod() {
         // GIVEN on the lock screen with a custom clock and visible notifications
         givenAOD();
@@ -384,7 +394,7 @@
         mClockPositionAlgorithm.setup(EMPTY_MARGIN, SCREEN_HEIGHT, mNotificationStackHeight,
                 mPanelExpansion, SCREEN_HEIGHT, mKeyguardStatusHeight, mPreferredClockY,
                 mHasCustomClock, mHasVisibleNotifs, mDark, ZERO_DRAG, false /* bypassEnabled */,
-                0 /* unlockedStackScrollerPadding */, false /* udfpsEnrolled */);
+                0 /* unlockedStackScrollerPadding */, false /* udfpsEnrolled */, mQsExpansion);
         mClockPositionAlgorithm.run(mClockPosition);
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
index d4a94a1..d452861 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
@@ -199,6 +199,8 @@
     @Mock
     private AuthController mAuthController;
     @Mock
+    private ScrimController mScrimController;
+    @Mock
     private MediaDataManager mMediaDataManager;
 
     private NotificationPanelViewController mNotificationPanelViewController;
@@ -279,6 +281,7 @@
                 mNotificationAreaController,
                 mAuthController,
                 new QSDetailDisplayer(),
+                mScrimController,
                 mMediaDataManager);
         mNotificationPanelViewController.initDependencies(
                 mStatusBar,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
index eaf31ed..342b2f5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
@@ -249,6 +249,20 @@
     }
 
     @Test
+    public void transitionToShadeLocked() {
+        mScrimController.transitionTo(ScrimState.SHADE_LOCKED);
+        finishAnimationsImmediately();
+
+        assertScrimAlpha(TRANSPARENT /* front */,
+                OPAQUE /* back */,
+                TRANSPARENT /* bubble */);
+
+        assertScrimTint(false /* front */,
+                false /* behind */,
+                false /* bubble */);
+    }
+
+    @Test
     public void transitionToOff() {
         mScrimController.transitionTo(ScrimState.OFF);
         finishAnimationsImmediately();
@@ -464,7 +478,7 @@
         // Front scrim should be transparent
         // Back scrim should be visible without tint
         assertScrimAlpha(TRANSPARENT /* front */,
-                SEMI_TRANSPARENT /* back */,
+                OPAQUE /* back */,
                 TRANSPARENT /* bubble */);
 
         assertScrimTint(false /* front */,
@@ -478,7 +492,7 @@
         finishAnimationsImmediately();
         // Front scrim should be transparent
         // Back scrim should be visible without tint
-        assertScrimAlpha(SEMI_TRANSPARENT /* front */,
+        assertScrimAlpha(OPAQUE /* front */,
                 TRANSPARENT /* back */,
                 TRANSPARENT /* bubble */);
         assertScrimTint(false /* front */,
@@ -519,11 +533,11 @@
         Assert.assertEquals(ScrimController.TRANSPARENT,
                 mScrimInFront.getViewAlpha(), 0.0f);
         // Back scrim should be visible
-        Assert.assertEquals(ScrimController.BLUR_SCRIM_ALPHA,
+        Assert.assertEquals(ScrimController.BUSY_SCRIM_ALPHA,
                 mScrimBehind.getViewAlpha(), 0.0f);
         // Bubble scrim should be visible
-        Assert.assertEquals(ScrimController.BLUR_SCRIM_ALPHA,
-                mScrimBehind.getViewAlpha(), 0.0f);
+        Assert.assertEquals(ScrimController.BUBBLE_SCRIM_ALPHA,
+                mScrimForBubble.getViewAlpha(), 0.0f);
     }
 
     @Test
@@ -564,6 +578,15 @@
     }
 
     @Test
+    public void qsExpansion() {
+        reset(mScrimBehind);
+        mScrimController.setQsExpansion(1f);
+        finishAnimationsImmediately();
+
+        assertScrimAlpha(TRANSPARENT, OPAQUE, TRANSPARENT);
+    }
+
+    @Test
     public void panelExpansionAffectsAlpha() {
         mScrimController.setPanelExpansion(0f);
         mScrimController.setPanelExpansion(0.5f);
@@ -888,7 +911,7 @@
         HashSet<ScrimState> regularStates = new HashSet<>(Arrays.asList(
                 ScrimState.UNINITIALIZED, ScrimState.KEYGUARD, ScrimState.BOUNCER,
                 ScrimState.BOUNCER_SCRIMMED, ScrimState.BRIGHTNESS_MIRROR, ScrimState.UNLOCKED,
-                ScrimState.BUBBLE_EXPANDED));
+                ScrimState.BUBBLE_EXPANDED, ScrimState.SHADE_LOCKED));
 
         for (ScrimState state : ScrimState.values()) {
             if (!lowPowerModeStates.contains(state) && !regularStates.contains(state)) {
diff --git a/packages/Tethering/OWNERS b/packages/Tethering/OWNERS
new file mode 100644
index 0000000..aa87958
--- /dev/null
+++ b/packages/Tethering/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/net/OWNERS
diff --git a/packages/VpnDialogs/OWNERS b/packages/VpnDialogs/OWNERS
new file mode 100644
index 0000000..aa87958
--- /dev/null
+++ b/packages/VpnDialogs/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/net/OWNERS
diff --git a/packages/WAPPushManager/OWNERS b/packages/WAPPushManager/OWNERS
new file mode 100644
index 0000000..640baf2
--- /dev/null
+++ b/packages/WAPPushManager/OWNERS
@@ -0,0 +1 @@
+include /telephony/OWNERS
diff --git a/packages/WallpaperBackup/OWNERS b/packages/WallpaperBackup/OWNERS
new file mode 100644
index 0000000..d99779e
--- /dev/null
+++ b/packages/WallpaperBackup/OWNERS
@@ -0,0 +1 @@
+include /services/backup/OWNERS
diff --git a/packages/WallpaperCropper/OWNERS b/packages/WallpaperCropper/OWNERS
new file mode 100644
index 0000000..8ff0f74
--- /dev/null
+++ b/packages/WallpaperCropper/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/service/wallpaper/OWNERS
diff --git a/packages/WindowManager/OWNERS b/packages/WindowManager/OWNERS
new file mode 100644
index 0000000..0862c05
--- /dev/null
+++ b/packages/WindowManager/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/wm/OWNERS
diff --git a/packages/overlays/OWNERS b/packages/overlays/OWNERS
new file mode 100644
index 0000000..afb98d4
--- /dev/null
+++ b/packages/overlays/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/content/om/OWNERS
diff --git a/packages/services/PacProcessor/OWNERS b/packages/services/PacProcessor/OWNERS
new file mode 100644
index 0000000..aa87958
--- /dev/null
+++ b/packages/services/PacProcessor/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/net/OWNERS
diff --git a/packages/services/Proxy/OWNERS b/packages/services/Proxy/OWNERS
new file mode 100644
index 0000000..aa87958
--- /dev/null
+++ b/packages/services/Proxy/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/net/OWNERS
diff --git a/proto/src/OWNERS b/proto/src/OWNERS
new file mode 100644
index 0000000..e7ddf86
--- /dev/null
+++ b/proto/src/OWNERS
@@ -0,0 +1,2 @@
+per-file gnss.proto = file:/services/core/java/com/android/server/location/OWNERS
+per-file wifi.proto = file:/wifi/OWNERS
diff --git a/proto/src/metrics_constants/OWNERS b/proto/src/metrics_constants/OWNERS
index 7009282..ab4d808 100644
--- a/proto/src/metrics_constants/OWNERS
+++ b/proto/src/metrics_constants/OWNERS
@@ -1,4 +1,4 @@
[email protected]
[email protected]
 [email protected]
 [email protected]
 [email protected]
diff --git a/samples/training/network-usage/OWNERS b/samples/training/network-usage/OWNERS
new file mode 100644
index 0000000..aa87958
--- /dev/null
+++ b/samples/training/network-usage/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/net/OWNERS
diff --git a/services/OWNERS b/services/OWNERS
new file mode 100644
index 0000000..88d0b61
--- /dev/null
+++ b/services/OWNERS
@@ -0,0 +1 @@
+per-file Android.bp = file:platform/build/soong:/OWNERS
diff --git a/services/api/OWNERS b/services/api/OWNERS
new file mode 100644
index 0000000..a609390
--- /dev/null
+++ b/services/api/OWNERS
@@ -0,0 +1,4 @@
+per-file Android.bp = file:platform/build/soong:/OWNERS
+
+# API changes are managed via Prolog rules, not OWNERS
+*
diff --git a/services/appprediction/OWNERS b/services/appprediction/OWNERS
new file mode 100644
index 0000000..3a5d23d
--- /dev/null
+++ b/services/appprediction/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/service/appprediction/OWNERS
diff --git a/services/autofill/OWNERS b/services/autofill/OWNERS
new file mode 100644
index 0000000..c52751d
--- /dev/null
+++ b/services/autofill/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/service/autofill/OWNERS
diff --git a/services/backup/Android.bp b/services/backup/Android.bp
index b5444f4..68376c5 100644
--- a/services/backup/Android.bp
+++ b/services/backup/Android.bp
@@ -10,5 +10,5 @@
     defaults: ["platform_service_defaults"],
     srcs: [":services.backup-sources"],
     libs: ["services.core"],
-    static_libs: ["backuplib"],
+    static_libs: ["backuplib", "app-compat-annotations"],
 }
diff --git a/services/backup/java/com/android/server/backup/UserBackupManagerService.java b/services/backup/java/com/android/server/backup/UserBackupManagerService.java
index 2ff66b5..136cd22f 100644
--- a/services/backup/java/com/android/server/backup/UserBackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/UserBackupManagerService.java
@@ -3030,9 +3030,11 @@
             }
             Slog.i(TAG, addUserIdToLogMessage(mUserId, "Beginning adb backup..."));
 
+            BackupEligibilityRules eligibilityRules = getEligibilityRulesForOperation(
+                    OperationType.ADB_BACKUP);
             AdbBackupParams params = new AdbBackupParams(fd, includeApks, includeObbs,
                     includeShared, doWidgets, doAllApps, includeSystem, compress, doKeyValue,
-                    pkgList, mScheduledBackupEligibility);
+                    pkgList, eligibilityRules);
             final int token = generateRandomIntegerToken();
             synchronized (mAdbBackupRestoreConfirmations) {
                 mAdbBackupRestoreConfirmations.put(token, params);
diff --git a/services/backup/java/com/android/server/backup/restore/PerformAdbRestoreTask.java b/services/backup/java/com/android/server/backup/restore/PerformAdbRestoreTask.java
index c94286f..e03150e 100644
--- a/services/backup/java/com/android/server/backup/restore/PerformAdbRestoreTask.java
+++ b/services/backup/java/com/android/server/backup/restore/PerformAdbRestoreTask.java
@@ -24,6 +24,7 @@
 import static com.android.server.backup.UserBackupManagerService.BACKUP_FILE_HEADER_MAGIC;
 import static com.android.server.backup.UserBackupManagerService.BACKUP_FILE_VERSION;
 
+import android.app.backup.BackupManager;
 import android.app.backup.IFullBackupRestoreObserver;
 import android.content.pm.PackageManagerInternal;
 import android.os.ParcelFileDescriptor;
@@ -104,11 +105,13 @@
                 return;
             }
 
+            BackupEligibilityRules eligibilityRules = new BackupEligibilityRules(
+                    mBackupManagerService.getPackageManager(),
+                    LocalServices.getService(PackageManagerInternal.class),
+                    mBackupManagerService.getUserId(), BackupManager.OperationType.ADB_BACKUP);
             FullRestoreEngine mEngine = new FullRestoreEngine(mBackupManagerService, null,
                     mObserver, null, null, true, 0 /*unused*/, true,
-                    BackupEligibilityRules.forBackup(mBackupManagerService.getPackageManager(),
-                                    LocalServices.getService(PackageManagerInternal.class),
-                                    mBackupManagerService.getUserId()));
+                    eligibilityRules);
             FullRestoreEngineThread mEngineThread = new FullRestoreEngineThread(mEngine,
                     tarInputStream);
             mEngineThread.run();
diff --git a/services/backup/java/com/android/server/backup/utils/BackupEligibilityRules.java b/services/backup/java/com/android/server/backup/utils/BackupEligibilityRules.java
index 73ba1f1..2078492 100644
--- a/services/backup/java/com/android/server/backup/utils/BackupEligibilityRules.java
+++ b/services/backup/java/com/android/server/backup/utils/BackupEligibilityRules.java
@@ -25,12 +25,16 @@
 import android.annotation.Nullable;
 import android.app.backup.BackupManager.OperationType;
 import android.app.backup.BackupTransport;
+import android.compat.annotation.ChangeId;
+import android.compat.annotation.EnabledSince;
+import android.app.compat.CompatChanges;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManagerInternal;
 import android.content.pm.Signature;
 import android.content.pm.SigningInfo;
+import android.os.Build;
 import android.os.UserHandle;
 import android.util.Slog;
 
@@ -41,6 +45,7 @@
 
 import com.google.android.collect.Sets;
 
+import java.util.Objects;
 import java.util.Set;
 
 /**
@@ -57,6 +62,15 @@
     private final int mUserId;
     @OperationType  private final int mOperationType;
 
+    /**
+     * When  this change is enabled, {@code adb backup}  is automatically turned on for apps
+     * running as debuggable ({@code android:debuggable} set to {@code true}) and unavailable to
+     * any other apps.
+     */
+    @ChangeId
+    @EnabledSince(targetSdkVersion = Build.VERSION_CODES.S)
+    static final long RESTRICT_ADB_BACKUP = 171032338L;
+
     public static BackupEligibilityRules forBackup(PackageManager packageManager,
             PackageManagerInternal packageManagerInternal,
             int userId) {
@@ -134,12 +148,53 @@
     * @return boolean indicating whether backup is allowed.
     */
     public boolean isAppBackupAllowed(ApplicationInfo app) {
-        if (mOperationType == OperationType.MIGRATION && !UserHandle.isCore(app.uid)) {
-            // Backup / restore of all apps is force allowed during device-to-device migration.
-            return true;
-        }
+        boolean isSystemApp = UserHandle.isCore(app.uid);
+        boolean allowBackup = (app.flags & ApplicationInfo.FLAG_ALLOW_BACKUP) != 0;
+        switch (mOperationType) {
+            case OperationType.MIGRATION:
+                // Backup / restore of all non-system apps is force allowed during
+                // device-to-device migration.
+                return !isSystemApp || allowBackup;
+            case OperationType.ADB_BACKUP:
+                String packageName = app.packageName;
+                if (packageName == null) {
+                    Slog.w(TAG, "Invalid ApplicationInfo object");
+                    return false;
+                }
 
-        return (app.flags & ApplicationInfo.FLAG_ALLOW_BACKUP) != 0;
+                if (!CompatChanges.isChangeEnabled(RESTRICT_ADB_BACKUP, packageName,
+                        UserHandle.of(mUserId))) {
+                    return allowBackup;
+                }
+
+                if (PLATFORM_PACKAGE_NAME.equals(packageName)) {
+                    // Always enable adb backup for SystemBackupAgent in "android" package (this is
+                    // done to avoid breaking existing integration tests and might change in the
+                    // future).
+                    return true;
+                }
+
+                boolean isPrivileged = (app.flags & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0;
+                boolean isDebuggable = (app.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
+                if (isSystemApp || isPrivileged) {
+                    try {
+                        return mPackageManager.getProperty(PackageManager.PROPERTY_ALLOW_ADB_BACKUP,
+                                packageName).getBoolean();
+                    } catch (PackageManager.NameNotFoundException e) {
+                        Slog.w(TAG, "Failed to read allowAdbBackup property for + "
+                                + packageName);
+                        return false;
+                    }
+                } else {
+                    // All other apps can use adb backup only when running in debuggable mode.
+                    return isDebuggable;
+                }
+            case OperationType.BACKUP:
+                return allowBackup;
+            default:
+                Slog.w(TAG, "Unknown operation type:" + mOperationType);
+                return false;
+        }
     }
 
     /**
diff --git a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
index 5fedf9f..0a80b02 100644
--- a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
+++ b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
@@ -31,8 +31,12 @@
 import android.annotation.CheckResult;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.SuppressLint;
 import android.app.AppOpsManager;
 import android.app.PendingIntent;
+import android.app.role.RoleManager;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
 import android.companion.Association;
 import android.companion.AssociationRequest;
 import android.companion.CompanionDeviceManager;
@@ -47,6 +51,7 @@
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageItemInfo;
 import android.content.pm.PackageManager;
+import android.content.pm.UserInfo;
 import android.net.NetworkPolicyManager;
 import android.os.Binder;
 import android.os.Environment;
@@ -62,6 +67,7 @@
 import android.os.ShellCallback;
 import android.os.ShellCommand;
 import android.os.UserHandle;
+import android.os.UserManager;
 import android.provider.Settings;
 import android.provider.SettingsStringUtil.ComponentNameSet;
 import android.text.BidiFormatter;
@@ -70,6 +76,7 @@
 import android.util.ExceptionUtils;
 import android.util.Log;
 import android.util.Slog;
+import android.util.SparseArray;
 import android.util.Xml;
 
 import com.android.internal.annotations.GuardedBy;
@@ -116,12 +123,16 @@
 //TODO on associate called again after configuration change -> replace old callback with new
 //TODO avoid leaking calling activity in IFindDeviceCallback (see PrintManager#print for example)
 /** @hide */
+@SuppressLint("LongLogTag")
 public class CompanionDeviceManagerService extends SystemService implements Binder.DeathRecipient {
 
     private static final ComponentName SERVICE_TO_BIND_TO = ComponentName.createRelative(
             CompanionDeviceManager.COMPANION_DEVICE_DISCOVERY_PACKAGE_NAME,
             ".DeviceDiscoveryService");
 
+    // 10 min
+    public static final int DEVICE_DISCONNECT_PROFILE_REVOKE_DELAY_MS = 10 * 60 * 1000;
+
     private static final boolean DEBUG = false;
     private static final String LOG_TAG = "CompanionDeviceManagerService";
 
@@ -132,6 +143,8 @@
     private static final String XML_TAG_ASSOCIATION = "association";
     private static final String XML_ATTR_PACKAGE = "package";
     private static final String XML_ATTR_DEVICE = "device";
+    private static final String XML_ATTR_PROFILE = "profile";
+    private static final String XML_ATTR_PERSISTENT_PROFILE_GRANTS = "persistent_profile_grants";
     private static final String XML_FILE_NAME = "companion_device_manager_associations.xml";
 
     private final CompanionDeviceManagerImpl mImpl;
@@ -139,21 +152,29 @@
     private PowerWhitelistManager mPowerWhitelistManager;
     private PerUser<ServiceConnector<ICompanionDeviceDiscoveryService>> mServiceConnectors;
     private IAppOpsService mAppOpsManager;
+    private RoleManager mRoleManager;
+    private BluetoothAdapter mBluetoothAdapter;
 
     private IFindDeviceCallback mFindDeviceCallback;
     private AssociationRequest mRequest;
     private String mCallingPackage;
     private AndroidFuture<Association> mOngoingDeviceDiscovery;
 
+    private BluetoothDeviceConnectedListener mBluetoothDeviceConnectedListener =
+            new BluetoothDeviceConnectedListener();
+    private List<String> mCurrentlyConnectedDevices = new ArrayList<>();
+
     private final Object mLock = new Object();
 
+    /** userId -> [association] */
     @GuardedBy("mLock")
-    private @Nullable Set<Association> mCachedAssociations = null;
+    private @Nullable SparseArray<Set<Association>> mCachedAssociations = new SparseArray<>();
 
     public CompanionDeviceManagerService(Context context) {
         super(context);
         mImpl = new CompanionDeviceManagerImpl();
         mPowerWhitelistManager = context.getSystemService(PowerWhitelistManager.class);
+        mRoleManager = context.getSystemService(RoleManager.class);
         mAppOpsManager = IAppOpsService.Stub.asInterface(
                 ServiceManager.getService(Context.APP_OPS_SERVICE));
 
@@ -184,9 +205,9 @@
             @Override
             public void onPackageModified(String packageName) {
                 int userId = getChangingUserId();
-                if (!ArrayUtils.isEmpty(getAllAssociations(userId, packageName))) {
-                    updateSpecialAccessPermissionForAssociatedPackage(packageName, userId);
-                }
+                forEach(getAllAssociations(userId, packageName), association -> {
+                    updateSpecialAccessPermissionForAssociatedPackage(association);
+                });
             }
 
         }.register(getContext(), FgThread.get().getLooper(), UserHandle.ALL, true);
@@ -198,6 +219,18 @@
     }
 
     @Override
+    public void onBootPhase(int phase) {
+        if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
+            mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
+            if (mBluetoothAdapter != null) {
+                mBluetoothAdapter.registerBluetoothConnectionCallback(
+                        getContext().getMainExecutor(),
+                        mBluetoothDeviceConnectedListener);
+            }
+        }
+    }
+
+    @Override
     public void onUserUnlocking(@NonNull TargetUser user) {
         int userHandle = user.getUserIdentifier();
         Set<Association> associations = getAllAssociations(userHandle);
@@ -495,12 +528,14 @@
 
             fout.append("Companion Device Associations:").append('\n');
             synchronized (mLock) {
-                forEach(mCachedAssociations, a -> {
-                    fout.append("  ")
-                            .append("u").append("" + a.getUserId()).append(": ")
-                            .append(a.getPackageName()).append(" - ")
-                            .append(a.getDeviceMacAddress()).append('\n');
-                });
+                for (UserInfo user : getAllUsers()) {
+                    forEach(mCachedAssociations.get(user.id), a -> {
+                        fout.append("  ")
+                                .append("u").append("" + a.getUserId()).append(": ")
+                                .append(a.getPackageName()).append(" - ")
+                                .append(a.getDeviceMacAddress()).append('\n');
+                    });
+                }
             }
         }
     }
@@ -513,32 +548,34 @@
         return Binder.getCallingUid() == Process.SYSTEM_UID;
     }
 
-    void addAssociation(int userId, String packageName, String deviceAddress) {
-        addAssociation(new Association(userId, deviceAddress, packageName));
-    }
-
     void addAssociation(Association association) {
-        updateSpecialAccessPermissionForAssociatedPackage(
-                association.getPackageName(), association.getUserId());
+        updateSpecialAccessPermissionForAssociatedPackage(association);
         recordAssociation(association);
     }
 
     void removeAssociation(int userId, String pkg, String deviceMacAddress) {
-        updateAssociations(associations -> CollectionUtils.remove(associations,
-                new Association(userId, deviceMacAddress, pkg)));
+        updateAssociations(associations -> CollectionUtils.filter(associations, association -> {
+            return association.getUserId() != userId
+                    || !Objects.equals(association.getDeviceMacAddress(), deviceMacAddress)
+                    || !Objects.equals(association.getPackageName(), pkg);
+        }));
     }
 
-    private void updateSpecialAccessPermissionForAssociatedPackage(String packageName, int userId) {
-        PackageInfo packageInfo = getPackageInfo(packageName, userId);
+    private void updateSpecialAccessPermissionForAssociatedPackage(Association association) {
+        PackageInfo packageInfo = getPackageInfo(
+                association.getPackageName(),
+                association.getUserId());
         if (packageInfo == null) {
             return;
         }
 
         Binder.withCleanCallingIdentity(obtainRunnable(CompanionDeviceManagerService::
-                updateSpecialAccessPermissionAsSystem, this, packageInfo).recycleOnUse());
+                updateSpecialAccessPermissionAsSystem, this, association, packageInfo)
+                .recycleOnUse());
     }
 
-    private void updateSpecialAccessPermissionAsSystem(PackageInfo packageInfo) {
+    private void updateSpecialAccessPermissionAsSystem(
+            Association association, PackageInfo packageInfo) {
         if (containsEither(packageInfo.requestedPermissions,
                 android.Manifest.permission.RUN_IN_BACKGROUND,
                 android.Manifest.permission.REQUEST_COMPANION_RUN_IN_BACKGROUND)) {
@@ -602,10 +639,6 @@
         updateAssociations(associations -> CollectionUtils.add(associations, association));
     }
 
-    private void recordAssociation(String privilegedPackage, String deviceAddress) {
-        recordAssociation(new Association(getCallingUserId(), deviceAddress, privilegedPackage));
-    }
-
     private void updateAssociations(Function<Set<Association>, Set<Association>> update) {
         updateAssociations(update, getCallingUserId());
     }
@@ -625,7 +658,7 @@
             if (DEBUG) {
                 Slog.i(LOG_TAG, "Updating associations: " + old + "  -->  " + associations);
             }
-            mCachedAssociations = Collections.unmodifiableSet(associations);
+            mCachedAssociations.put(userId, Collections.unmodifiableSet(associations));
             BackgroundThread.getHandler().sendMessage(PooledLambda.obtainMessage(
                     CompanionDeviceManagerService::persistAssociations,
                     this, associations, userId));
@@ -651,10 +684,17 @@
                     xml.startTag(null, XML_TAG_ASSOCIATIONS);
 
                     forEach(associations, association -> {
-                        xml.startTag(null, XML_TAG_ASSOCIATION)
+                        XmlSerializer tag = xml.startTag(null, XML_TAG_ASSOCIATION)
                                 .attribute(null, XML_ATTR_PACKAGE, association.getPackageName())
-                                .attribute(null, XML_ATTR_DEVICE, association.getDeviceMacAddress())
-                                .endTag(null, XML_TAG_ASSOCIATION);
+                                .attribute(null, XML_ATTR_DEVICE,
+                                        association.getDeviceMacAddress());
+                        if (association.getDeviceProfile() != null) {
+                            tag.attribute(null, XML_ATTR_PROFILE, association.getDeviceProfile());
+                            tag.attribute(null, XML_ATTR_PERSISTENT_PROFILE_GRANTS,
+                                    Boolean.toString(
+                                            association.isKeepProfilePrivilegesWhenDeviceAway()));
+                        }
+                        tag.endTag(null, XML_TAG_ASSOCIATION);
                     });
 
                     xml.endTag(null, XML_TAG_ASSOCIATIONS);
@@ -678,17 +718,21 @@
     @Nullable
     private Set<Association> getAllAssociations(int userId) {
         synchronized (mLock) {
-            if (mCachedAssociations == null) {
-                mCachedAssociations = Collections.unmodifiableSet(
-                        emptyIfNull(readAllAssociations(userId)));
+            if (mCachedAssociations.get(userId) == null) {
+                mCachedAssociations.put(userId, Collections.unmodifiableSet(
+                        emptyIfNull(readAllAssociations(userId))));
                 if (DEBUG) {
                     Slog.i(LOG_TAG, "Read associations from disk: " + mCachedAssociations);
                 }
             }
-            return mCachedAssociations;
+            return mCachedAssociations.get(userId);
         }
     }
 
+    private List<UserInfo> getAllUsers() {
+        return getContext().getSystemService(UserManager.class).getUsers();
+    }
+
     @Nullable
     private Set<Association> getAllAssociations(int userId, @Nullable String packageFilter) {
         return CollectionUtils.filter(
@@ -714,10 +758,15 @@
                     final String appPackage = parser.getAttributeValue(null, XML_ATTR_PACKAGE);
                     final String deviceAddress = parser.getAttributeValue(null, XML_ATTR_DEVICE);
 
+                    final String profile = parser.getAttributeValue(null, XML_ATTR_PROFILE);
+                    final boolean persistentGrants = Boolean.valueOf(
+                            parser.getAttributeValue(null, XML_ATTR_PERSISTENT_PROFILE_GRANTS));
+
                     if (appPackage == null || deviceAddress == null) continue;
 
                     result = ArrayUtils.add(result,
-                            new Association(userId, deviceAddress, appPackage));
+                            new Association(userId, deviceAddress, appPackage,
+                                    profile, persistentGrants));
                 }
                 return result;
             } catch (XmlPullParserException | IOException e) {
@@ -727,6 +776,77 @@
         }
     }
 
+    void onDeviceConnected(String address) {
+        mCurrentlyConnectedDevices.add(address);
+
+        Handler.getMain().removeCallbacksAndMessages(getDisconnectJobHandlerId(address));
+
+        for (UserInfo user : getAllUsers()) {
+            for (Association association : getAllAssociations(user.id)) {
+                if (Objects.equals(address, association.getDeviceMacAddress())) {
+                    if (association.getDeviceProfile() != null) {
+                        Log.i(LOG_TAG, "Granting role " + association.getDeviceProfile()
+                                + " to " + association.getPackageName()
+                                + " due to device connected: " + address);
+                        mRoleManager.addRoleHolderAsUser(
+                                association.getDeviceProfile(),
+                                association.getPackageName(),
+                                RoleManager.MANAGE_HOLDERS_FLAG_DONT_KILL_APP,
+                                UserHandle.of(association.getUserId()),
+                                getContext().getMainExecutor(),
+                                success -> {
+                                    if (!success) {
+                                        Log.e(LOG_TAG, "Failed to grant device profile role "
+                                                + association.getDeviceProfile()
+                                                + " to " + association.getPackageName()
+                                                + " for user " + association.getUserId());
+                                    }
+                                });
+                    }
+                }
+            }
+        }
+    }
+
+    void onDeviceDisconnected(String address) {
+        mCurrentlyConnectedDevices.remove(address);
+
+        Handler.getMain().postDelayed(() -> {
+            if (!mCurrentlyConnectedDevices.contains(address)) {
+                for (UserInfo user : getAllUsers()) {
+                    for (Association association : getAllAssociations(user.id)) {
+                        if (association.getDeviceProfile() != null
+                                && Objects.equals(address, association.getDeviceMacAddress())
+                                && !association.isKeepProfilePrivilegesWhenDeviceAway()) {
+                            Log.i(LOG_TAG, "Revoking role " + association.getDeviceProfile()
+                                    + " to " + association.getPackageName()
+                                    + " due to device disconnected: " + address);
+                            mRoleManager.removeRoleHolderAsUser(
+                                    association.getDeviceProfile(),
+                                    association.getPackageName(),
+                                    RoleManager.MANAGE_HOLDERS_FLAG_DONT_KILL_APP,
+                                    UserHandle.of(association.getUserId()),
+                                    getContext().getMainExecutor(),
+                                    success -> {
+                                        if (!success) {
+                                            Log.e(LOG_TAG, "Failed to revoke device profile role "
+                                                    + association.getDeviceProfile()
+                                                    + " to " + association.getPackageName()
+                                                    + " for user " + association.getUserId());
+                                        }
+                                    });
+                        }
+                    }
+                }
+            }
+        }, getDisconnectJobHandlerId(address), DEVICE_DISCONNECT_PROFILE_REVOKE_DELAY_MS);
+    }
+
+    @NonNull
+    private String getDisconnectJobHandlerId(String address) {
+        return "CDM_onDisconnected_" + address;
+    }
+
     private class ShellCmd extends ShellCommand {
         public static final String USAGE = "help\n"
                 + "list USER_ID\n"
@@ -749,13 +869,22 @@
                 } break;
 
                 case "associate": {
-                    addAssociation(getNextArgInt(), getNextArgRequired(), getNextArgRequired());
+                    addAssociation(new Association(getNextArgInt(), getNextArgRequired(),
+                            getNextArgRequired(), null, false));
                 } break;
 
                 case "disassociate": {
                     removeAssociation(getNextArgInt(), getNextArgRequired(), getNextArgRequired());
                 } break;
 
+                case "simulate_connect": {
+                    onDeviceConnected(getNextArgRequired());
+                } break;
+
+                case "simulate_disconnect": {
+                    onDeviceDisconnected(getNextArgRequired());
+                } break;
+
                 default: return handleDefaultCommands(cmd);
             }
             return 0;
@@ -771,4 +900,17 @@
         }
     }
 
+
+    private class BluetoothDeviceConnectedListener
+            extends BluetoothAdapter.BluetoothConnectionCallback {
+        @Override
+        public void onDeviceConnected(BluetoothDevice device) {
+            CompanionDeviceManagerService.this.onDeviceConnected(device.getAddress());
+        }
+
+        @Override
+        public void onDeviceDisconnected(BluetoothDevice device) {
+            CompanionDeviceManagerService.this.onDeviceDisconnected(device.getAddress());
+        }
+    }
 }
diff --git a/services/contentcapture/OWNERS b/services/contentcapture/OWNERS
new file mode 100644
index 0000000..a28e00a
--- /dev/null
+++ b/services/contentcapture/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/service/contentcapture/OWNERS
diff --git a/services/contentsuggestions/OWNERS b/services/contentsuggestions/OWNERS
new file mode 100644
index 0000000..449db3a
--- /dev/null
+++ b/services/contentsuggestions/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/service/contentsuggestions/OWNERS
diff --git a/services/core/OWNERS b/services/core/OWNERS
new file mode 100644
index 0000000..88d0b61
--- /dev/null
+++ b/services/core/OWNERS
@@ -0,0 +1 @@
+per-file Android.bp = file:platform/build/soong:/OWNERS
diff --git a/services/core/java/android/content/pm/PackageManagerInternal.java b/services/core/java/android/content/pm/PackageManagerInternal.java
index 6989e32..53bfcec 100644
--- a/services/core/java/android/content/pm/PackageManagerInternal.java
+++ b/services/core/java/android/content/pm/PackageManagerInternal.java
@@ -949,9 +949,6 @@
     /** Returns whether or not permissions need to be upgraded for the given user */
     public abstract boolean isPermissionUpgradeNeeded(@UserIdInt int userId);
 
-    /** Sets the enforcement of reading external storage */
-    public abstract void setReadExternalStorageEnforced(boolean enforced);
-
     /**
      * Allows the integrity component to respond to the
      * {@link Intent#ACTION_PACKAGE_NEEDS_INTEGRITY_VERIFICATION package verification
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index ee9d492..0d0f0dd 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -6052,6 +6052,7 @@
      * Stores into |nai| any data coming from the agent that might also be written to the network's
      * LinkProperties by ConnectivityService itself. This ensures that the data provided by the
      * agent is not lost when updateLinkProperties is called.
+     * This method should never alter the agent's LinkProperties, only store data in |nai|.
      */
     private void processLinkPropertiesFromAgent(NetworkAgentInfo nai, LinkProperties lp) {
         lp.ensureDirectlyConnectedRoutes();
@@ -6353,6 +6354,7 @@
      * Stores into |nai| any data coming from the agent that might also be written to the network's
      * NetworkCapabilities by ConnectivityService itself. This ensures that the data provided by the
      * agent is not lost when updateCapabilities is called.
+     * This method should never alter the agent's NetworkCapabilities, only store data in |nai|.
      */
     private void processCapabilitiesFromAgent(NetworkAgentInfo nai, NetworkCapabilities nc) {
         nai.declaredMetered = !nc.hasCapability(NET_CAPABILITY_NOT_METERED);
diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java
index b2f0c83..f648c3e 100644
--- a/services/core/java/com/android/server/IpSecService.java
+++ b/services/core/java/com/android/server/IpSecService.java
@@ -31,6 +31,7 @@
 import android.content.pm.PackageManager;
 import android.net.IIpSecService;
 import android.net.INetd;
+import android.net.InetAddresses;
 import android.net.IpSecAlgorithm;
 import android.net.IpSecConfig;
 import android.net.IpSecManager;
@@ -41,7 +42,6 @@
 import android.net.IpSecUdpEncapResponse;
 import android.net.LinkAddress;
 import android.net.Network;
-import android.net.NetworkUtils;
 import android.net.TrafficStats;
 import android.net.util.NetdService;
 import android.os.Binder;
@@ -1083,7 +1083,7 @@
             throw new IllegalArgumentException("Unspecified address");
         }
 
-        InetAddress checkAddr = NetworkUtils.numericToInetAddress(inetAddress);
+        InetAddress checkAddr = InetAddresses.parseNumericAddress(inetAddress);
 
         if (checkAddr.isAnyLocalAddress()) {
             throw new IllegalArgumentException("Inappropriate wildcard address: " + inetAddress);
@@ -1467,7 +1467,7 @@
 
     private int getFamily(String inetAddress) {
         int family = AF_UNSPEC;
-        InetAddress checkAddress = NetworkUtils.numericToInetAddress(inetAddress);
+        InetAddress checkAddress = InetAddresses.parseNumericAddress(inetAddress);
         if (checkAddress instanceof Inet4Address) {
             family = AF_INET;
         } else if (checkAddress instanceof Inet6Address) {
diff --git a/services/core/java/com/android/server/MasterClearReceiver.java b/services/core/java/com/android/server/MasterClearReceiver.java
index 793e342..e248b21 100644
--- a/services/core/java/com/android/server/MasterClearReceiver.java
+++ b/services/core/java/com/android/server/MasterClearReceiver.java
@@ -25,7 +25,6 @@
 import android.os.UserHandle;
 import android.os.storage.StorageManager;
 import android.text.TextUtils;
-import android.util.Log;
 import android.util.Slog;
 import android.view.WindowManager;
 
@@ -59,6 +58,7 @@
                 .getString(com.android.internal.R.string.config_factoryResetPackage);
         if (Intent.ACTION_FACTORY_RESET.equals(intent.getAction())
                 && !TextUtils.isEmpty(factoryResetPackage)) {
+            Slog.i(TAG, "Re-directing intent to " + factoryResetPackage);
             intent.setPackage(factoryResetPackage).setComponent(null);
             context.sendBroadcastAsUser(intent, UserHandle.SYSTEM);
             return;
@@ -77,9 +77,12 @@
             @Override
             public void run() {
                 try {
+                    Slog.i(TAG, "Calling RecoverySystem.rebootWipeUserData(context, "
+                            + "shutdown=" + shutdown + ", reason=" + reason
+                            + ", forceWipe=" + forceWipe + ", wipeEsims=" + mWipeEsims + ")");
                     RecoverySystem
                             .rebootWipeUserData(context, shutdown, reason, forceWipe, mWipeEsims);
-                    Log.wtf(TAG, "Still running after master clear?!");
+                    Slog.wtf(TAG, "Still running after master clear?!");
                 } catch (IOException e) {
                     Slog.e(TAG, "Can't perform master clear/factory reset", e);
                 } catch (SecurityException e) {
@@ -90,8 +93,10 @@
 
         if (mWipeExternalStorage) {
             // thr will be started at the end of this task.
+            Slog.i(TAG, "Wiping external storage on async task");
             new WipeDataTask(context, thr).execute();
         } else {
+            Slog.i(TAG, "NOT wiping external storage; starting thread " + thr.getName());
             thr.start();
         }
     }
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index 821a967..5e86f85 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -58,7 +58,6 @@
 import android.net.NetworkPolicyManager;
 import android.net.NetworkStack;
 import android.net.NetworkStats;
-import android.net.NetworkUtils;
 import android.net.RouteInfo;
 import android.net.TetherStatsParcel;
 import android.net.UidRange;
@@ -803,7 +802,7 @@
         InterfaceConfiguration cfg = new InterfaceConfiguration();
         cfg.setHardwareAddress(p.hwAddr);
 
-        final InetAddress addr = NetworkUtils.numericToInetAddress(p.ipv4Addr);
+        final InetAddress addr = InetAddresses.parseNumericAddress(p.ipv4Addr);
         cfg.setLinkAddress(new LinkAddress(addr, p.prefixLength));
         for (String flag : p.flags) {
             cfg.setFlag(flag);
diff --git a/services/core/java/com/android/server/NetworkScoreService.java b/services/core/java/com/android/server/NetworkScoreService.java
index 3443918..fc3a7c8 100644
--- a/services/core/java/com/android/server/NetworkScoreService.java
+++ b/services/core/java/com/android/server/NetworkScoreService.java
@@ -59,7 +59,7 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.content.PackageMonitor;
 import com.android.internal.util.DumpUtils;
-import com.android.server.pm.permission.PermissionManagerServiceInternal;
+import com.android.server.pm.permission.LegacyPermissionManagerInternal;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -290,7 +290,7 @@
                     String useOpenWifiPackage = Global.getString(mContext.getContentResolver(),
                             Global.USE_OPEN_WIFI_PACKAGE);
                     if (!TextUtils.isEmpty(useOpenWifiPackage)) {
-                        LocalServices.getService(PermissionManagerServiceInternal.class)
+                        LocalServices.getService(LegacyPermissionManagerInternal.class)
                                 .grantDefaultPermissionsToDefaultUseOpenWifiApp(useOpenWifiPackage,
                                         userId);
                     }
@@ -302,7 +302,7 @@
                 false /*notifyForDescendants*/,
                 mUseOpenWifiPackageObserver);
         // Set a callback for the package manager to query the use open wifi app.
-        LocalServices.getService(PermissionManagerServiceInternal.class)
+        LocalServices.getService(LegacyPermissionManagerInternal.class)
                 .setUseOpenWifiAppPackagesProvider((userId) -> {
                     String useOpenWifiPackage = Global.getString(mContext.getContentResolver(),
                             Global.USE_OPEN_WIFI_PACKAGE);
diff --git a/services/core/java/com/android/server/OWNERS b/services/core/java/com/android/server/OWNERS
index 8706cdf..48cbd54 100644
--- a/services/core/java/com/android/server/OWNERS
+++ b/services/core/java/com/android/server/OWNERS
@@ -9,3 +9,19 @@
 
 # Userspace reboot
 per-file UserspaceRebootLogger.java = [email protected], [email protected]
+
+per-file *Alarm* = file:/apex/jobscheduler/OWNERS
+per-file *AppOps* = file:/core/java/android/permission/OWNERS
+per-file *Bluetooth* = file:/core/java/android/bluetooth/OWNERS
+per-file *Gnss* = file:/services/core/java/com/android/server/location/OWNERS
+per-file *Location* = file:/services/core/java/com/android/server/location/OWNERS
+per-file *Network* = file:/services/core/java/com/android/server/net/OWNERS
+per-file *Storage* = file:/core/java/android/os/storage/OWNERS
+per-file *TimeUpdate* = file:/core/java/android/app/timezone/OWNERS
+per-file ConnectivityService.java = file:/services/core/java/com/android/server/net/OWNERS
+per-file IpSecService.java = file:/services/core/java/com/android/server/net/OWNERS
+per-file MmsServiceBroker.java = file:/telephony/OWNERS
+per-file NetIdManager.java = file:/services/core/java/com/android/server/net/OWNERS
+per-file PackageWatchdog.java = file:/services/core/java/com/android/server/rollback/OWNERS
+per-file TelephonyRegistry.java = file:/telephony/OWNERS
+per-file UiModeManagerService.java = file:/packages/SystemUI/OWNERS
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index dbd27af4..c95bfd03 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -108,7 +108,6 @@
 import android.os.storage.StorageVolume;
 import android.os.storage.VolumeInfo;
 import android.os.storage.VolumeRecord;
-import android.provider.DeviceConfig;
 import android.provider.DocumentsContract;
 import android.provider.Downloads;
 import android.provider.MediaStore;
@@ -206,27 +205,6 @@
     private static final String ANDROID_VOLD_APP_DATA_ISOLATION_ENABLED_PROPERTY =
             "persist.sys.vold_app_data_isolation_enabled";
 
-    // TODO(b/169327180): Will be fetched from the server, but for now, we emulate this in
-    // the system_server since it can write to DeviceConfig and MediaProvider can read it
-    private static final String PROP_TRANSCODE_ENABLED = "transcode_enabled";
-    private static final String PROP_TRANSCODE_DEFAULT = "transcode_default";
-    private static final String PROP_TRANSCODE_COMPAT_MANIFEST = "transcode_compat_manifest";
-    private static final boolean TRANSCODE_ENABLED_VALUE = false;
-    // Determines the default behavior of apps when transcode is enabled, AKA, Option A/Option B.
-    // If true, transcode by default (Option B). If false, don't transcode by default (Option A)
-    // For dogfood, we go with Option B
-    private static final boolean TRANSCODE_DEFAULT_VALUE = true;
-    // Format is <package_name>,<media_capability_bit_mask>,...
-    // media_capability_bit_mask is defined in MediaProvider/../TranscodeHelper.java:
-    // FLAG_HEVC = 1 << 0;
-    // FLAG_SLOW_MOTION = 1 << 1;
-    // FLAG_HDR_10 = 1 << 2;
-    // FLAG_HDR_10_PLUS = 1 << 3;
-    // FLAG_HDR_HLG = 1 << 4;
-    // FLAG_HDR_DOLBY_VISION = 1 << 5;
-    private static final String TRANSCODE_COMPAT_MANIFEST_VALUE =
-            "com.google.android.apps.photos,1";
-
     // How long we wait to reset storage, if we failed to call onMount on the
     // external storage service.
     public static final int FAILED_MOUNT_RESET_TIMEOUT_SECONDS = 10;
@@ -901,18 +879,6 @@
                     com.android.internal.R.bool.config_zramWriteback)) {
             ZramWriteback.scheduleZramWriteback(mContext);
         }
-
-        // TODO(b/169327180): Remove after setting up server-side DeviceConfig flags
-        // Set DeviceConfig values for transcoding that will be read by MediaProvider
-        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_STORAGE_NATIVE_BOOT,
-                PROP_TRANSCODE_ENABLED, String.valueOf(TRANSCODE_ENABLED_VALUE),
-                false /* makeDefault */);
-        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_STORAGE_NATIVE_BOOT,
-                PROP_TRANSCODE_DEFAULT, String.valueOf(TRANSCODE_DEFAULT_VALUE),
-                false /* makeDefault */);
-        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_STORAGE_NATIVE_BOOT,
-                PROP_TRANSCODE_COMPAT_MANIFEST, TRANSCODE_COMPAT_MANIFEST_VALUE,
-                false /* makeDefault */);
     }
 
     /**
diff --git a/services/core/java/com/android/server/UiModeManagerService.java b/services/core/java/com/android/server/UiModeManagerService.java
index f49f1b1..7f638b9 100644
--- a/services/core/java/com/android/server/UiModeManagerService.java
+++ b/services/core/java/com/android/server/UiModeManagerService.java
@@ -1737,9 +1737,12 @@
                                 context.getString(R.string.car_mode_disable_notification_title))
                         .setContentText(
                                 context.getString(R.string.car_mode_disable_notification_message))
+
                         .setContentIntent(
+                                // TODO(b/173744200) Please replace FLAG_MUTABLE_UNAUDITED below
+                                // with either FLAG_IMMUTABLE (recommended) or FLAG_MUTABLE.
                                 PendingIntent.getActivityAsUser(context, 0,
-                                        carModeOffIntent, 0,
+                                        carModeOffIntent, PendingIntent.FLAG_MUTABLE_UNAUDITED,
                                         null, UserHandle.CURRENT));
                 mNotificationManager.notifyAsUser(null,
                         SystemMessage.NOTE_CAR_MODE_DISABLE, n.build(), UserHandle.ALL);
diff --git a/services/core/java/com/android/server/adb/OWNERS b/services/core/java/com/android/server/adb/OWNERS
new file mode 100644
index 0000000..b97f795
--- /dev/null
+++ b/services/core/java/com/android/server/adb/OWNERS
@@ -0,0 +1 @@
+include platform/packages/modules/adb:/OWNERS
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index c7e3b23..dffe0ba 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -50,6 +50,7 @@
 import android.app.AppGlobals;
 import android.app.AppOpsManager;
 import android.app.ApplicationExitInfo;
+import android.app.BroadcastOptions;
 import android.app.IApplicationThread;
 import android.app.IServiceConnection;
 import android.app.Notification;
@@ -3201,7 +3202,8 @@
                         + " for fg-service launch");
             }
             mAm.tempWhitelistUidLocked(r.appInfo.uid,
-                    SERVICE_START_FOREGROUND_TIMEOUT, "fg-service-launch");
+                    SERVICE_START_FOREGROUND_TIMEOUT, "fg-service-launch",
+                    BroadcastOptions.TEMPORARY_WHITELIST_TYPE_FOREGROUND_SERVICE_ALLOWED);
         }
 
         if (!mPendingServices.contains(r)) {
@@ -5284,8 +5286,9 @@
 
         if (ret == FGS_FEATURE_DENIED) {
             if (mAm.mConstants.mFlagFgsStartTempAllowListEnabled
-                    && mAm.isOnDeviceIdleWhitelistLocked(r.appInfo.uid, false)) {
-                // uid is on DeviceIdleController's allowlist.
+                    && mAm.isWhitelistedForFgsStartLocked(r.appInfo.uid)) {
+                // uid is on DeviceIdleController's user/system allowlist
+                // or AMS's FgsStartTempAllowList.
                 ret = FGS_FEATURE_ALLOWED_BY_DEVICE_IDLE_ALLOW_LIST;
             }
         }
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index bcd122d..18cc9a0 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -1094,6 +1094,11 @@
     final PendingTempWhitelists mPendingTempWhitelist = new PendingTempWhitelists(this);
 
     /**
+     * The temp-allowlist that is allowed to start FGS from background.
+     */
+    final FgsStartTempAllowList mFgsStartTempAllowList = new FgsStartTempAllowList();
+
+    /**
      * Information about and control over application operations
      */
     final AppOpsService mAppOpsService;
@@ -5510,6 +5515,12 @@
                 || mPendingTempWhitelist.indexOfKey(uid) >= 0;
     }
 
+    boolean isWhitelistedForFgsStartLocked(int uid) {
+        final int appId = UserHandle.getAppId(uid);
+        return Arrays.binarySearch(mDeviceIdleExceptIdleWhitelist, appId) >= 0
+                || mFgsStartTempAllowList.isAllowed(uid);
+    }
+
     /**
      * @return whitelist tag for a uid from mPendingTempWhitelist, null if not currently on
      * the whitelist
@@ -15324,17 +15335,22 @@
             }
         }
 
-        tempWhitelistUidLocked(targetUid, duration, tag);
+        tempWhitelistUidLocked(targetUid, duration, tag,
+                BroadcastOptions.TEMPORARY_WHITELIST_TYPE_FOREGROUND_SERVICE_ALLOWED);
     }
 
     /**
      * Whitelists {@code targetUid} to temporarily bypass Power Save mode.
      */
     @GuardedBy("this")
-    void tempWhitelistUidLocked(int targetUid, long duration, String tag) {
+    void tempWhitelistUidLocked(int targetUid, long duration, String tag, int type) {
         mPendingTempWhitelist.put(targetUid, new PendingTempWhitelist(targetUid, duration, tag));
         setUidTempWhitelistStateLocked(targetUid, true);
         mUiHandler.obtainMessage(PUSH_TEMP_WHITELIST_UI_MSG).sendToTarget();
+
+        if (type == BroadcastOptions.TEMPORARY_WHITELIST_TYPE_FOREGROUND_SERVICE_ALLOWED) {
+            mFgsStartTempAllowList.add(targetUid, duration);
+        }
     }
 
     void pushTempWhitelist() {
@@ -17209,8 +17225,6 @@
                     throw new SecurityException("Shell can delegate permissions only "
                             + "to one instrumentation at a time");
                 }
-                delegate.setPermissions(permissions);
-                return;
             }
 
             final int instrCount = mActiveInstrumentation.size();
@@ -17253,7 +17267,8 @@
 
     private class ShellDelegate implements CheckOpsDelegate {
         private final int mTargetUid;
-        private @Nullable String[] mPermissions;
+        @Nullable
+        private final String[] mPermissions;
 
         ShellDelegate(int targetUid, @Nullable String[] permissions) {
             mTargetUid = targetUid;
@@ -17264,19 +17279,15 @@
             return mTargetUid;
         }
 
-        void setPermissions(@Nullable String[] permissions) {
-            mPermissions = permissions;
-            PackageManager.invalidatePackageInfoCache();
-        }
-
         @Override
         public int checkOperation(int code, int uid, String packageName, boolean raw,
                 QuadFunction<Integer, Integer, String, Boolean, Integer> superImpl) {
             if (uid == mTargetUid && isTargetOp(code)) {
+                final int shellUid = UserHandle.getUid(UserHandle.getUserId(uid),
+                        Process.SHELL_UID);
                 final long identity = Binder.clearCallingIdentity();
                 try {
-                    return superImpl.apply(code, Process.SHELL_UID,
-                            "com.android.shell", raw);
+                    return superImpl.apply(code, shellUid, "com.android.shell", raw);
                 } finally {
                     Binder.restoreCallingIdentity(identity);
                 }
@@ -17288,10 +17299,11 @@
         public int checkAudioOperation(int code, int usage, int uid, String packageName,
                 QuadFunction<Integer, Integer, Integer, String, Integer> superImpl) {
             if (uid == mTargetUid && isTargetOp(code)) {
+                final int shellUid = UserHandle.getUid(UserHandle.getUserId(uid),
+                        Process.SHELL_UID);
                 final long identity = Binder.clearCallingIdentity();
                 try {
-                    return superImpl.apply(code, usage, Process.SHELL_UID,
-                            "com.android.shell");
+                    return superImpl.apply(code, usage, shellUid, "com.android.shell");
                 } finally {
                     Binder.restoreCallingIdentity(identity);
                 }
@@ -17306,9 +17318,11 @@
                 @NonNull HeptFunction<Integer, Integer, String, String, Boolean, String, Boolean,
                         Integer> superImpl) {
             if (uid == mTargetUid && isTargetOp(code)) {
+                final int shellUid = UserHandle.getUid(UserHandle.getUserId(uid),
+                        Process.SHELL_UID);
                 final long identity = Binder.clearCallingIdentity();
                 try {
-                    return superImpl.apply(code, Process.SHELL_UID, "com.android.shell", featureId,
+                    return superImpl.apply(code, shellUid, "com.android.shell", featureId,
                             shouldCollectAsyncNotedOp, message, shouldCollectMessage);
                 } finally {
                     Binder.restoreCallingIdentity(identity);
diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java
index 0877dd9..d2ee69e 100644
--- a/services/core/java/com/android/server/am/BroadcastQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastQueue.java
@@ -896,7 +896,8 @@
         return false;
     }
 
-    final void scheduleTempWhitelistLocked(int uid, long duration, BroadcastRecord r) {
+    final void scheduleTempWhitelistLocked(int uid, long duration, BroadcastRecord r,
+            @BroadcastOptions.TempAllowListType int type) {
         if (duration > Integer.MAX_VALUE) {
             duration = Integer.MAX_VALUE;
         }
@@ -919,9 +920,9 @@
         }
         if (DEBUG_BROADCAST) {
             Slog.v(TAG, "Broadcast temp whitelist uid=" + uid + " duration=" + duration
-                    + " : " + b.toString());
+                    + " type=" + type + " : " + b.toString());
         }
-        mService.tempWhitelistUidLocked(uid, duration, b.toString());
+        mService.tempWhitelistUidLocked(uid, duration, b.toString(), type);
     }
 
     /**
@@ -1318,7 +1319,8 @@
                 }
                 if (brOptions != null && brOptions.getTemporaryAppWhitelistDuration() > 0) {
                     scheduleTempWhitelistLocked(filter.owningUid,
-                            brOptions.getTemporaryAppWhitelistDuration(), r);
+                            brOptions.getTemporaryAppWhitelistDuration(), r,
+                            brOptions.getTemporaryAppWhitelistType());
                 }
             }
             return;
@@ -1610,7 +1612,8 @@
                 (brOptions != null && brOptions.getTemporaryAppWhitelistDuration() > 0);
         if (isActivityCapable) {
             scheduleTempWhitelistLocked(receiverUid,
-                    brOptions.getTemporaryAppWhitelistDuration(), r);
+                    brOptions.getTemporaryAppWhitelistDuration(), r,
+                    brOptions.getTemporaryAppWhitelistType());
         }
 
         // Broadcast is being executed, its package can't be stopped.
diff --git a/services/core/java/com/android/server/am/FgsStartTempAllowList.java b/services/core/java/com/android/server/am/FgsStartTempAllowList.java
new file mode 100644
index 0000000..1f90393
--- /dev/null
+++ b/services/core/java/com/android/server/am/FgsStartTempAllowList.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.am;
+
+import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
+
+import android.os.SystemClock;
+import android.util.Slog;
+import android.util.SparseLongArray;
+
+/**
+ * List of uids that are temporarily allowed to start FGS from background.
+ */
+final class FgsStartTempAllowList {
+    private static final int MAX_SIZE = 100;
+    /**
+     * The key is the UID, the value is expiration elapse time in ms of this temp-allowed UID.
+     */
+    private final SparseLongArray mTempAllowListFgs = new SparseLongArray();
+
+    FgsStartTempAllowList() {
+    }
+
+    void add(int uid, long duration) {
+        if (duration <= 0) {
+            Slog.e(TAG_AM, "FgsStartTempAllowList bad duration:" + duration + " uid: " + uid);
+            return;
+        }
+        // The temp allowlist should be a short list with only a few entries in it.
+        final int size = mTempAllowListFgs.size();
+        if (size > MAX_SIZE) {
+            Slog.w(TAG_AM, "FgsStartTempAllowList length:" + size + " exceeds " + MAX_SIZE);
+        }
+        final long now = SystemClock.elapsedRealtime();
+        for (int index = mTempAllowListFgs.size() - 1; index >= 0; index--) {
+            if (mTempAllowListFgs.valueAt(index) < now) {
+                mTempAllowListFgs.removeAt(index);
+            }
+        }
+        final long existingExpirationTime = mTempAllowListFgs.get(uid, -1);
+        final long expirationTime = now + duration;
+        if (existingExpirationTime == -1 || existingExpirationTime < expirationTime) {
+            mTempAllowListFgs.put(uid, expirationTime);
+        }
+    }
+
+    boolean isAllowed(int uid) {
+        final int index = mTempAllowListFgs.indexOfKey(uid);
+        if (index < 0) {
+            return false;
+        } else if (mTempAllowListFgs.valueAt(index) < SystemClock.elapsedRealtime()) {
+            mTempAllowListFgs.removeAt(index);
+            return false;
+        } else {
+            return true;
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/appop/OWNERS b/services/core/java/com/android/server/appop/OWNERS
new file mode 100644
index 0000000..999ea0e
--- /dev/null
+++ b/services/core/java/com/android/server/appop/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/permission/OWNERS
diff --git a/services/core/java/com/android/server/attention/OWNERS b/services/core/java/com/android/server/attention/OWNERS
new file mode 100644
index 0000000..51fc9bd
--- /dev/null
+++ b/services/core/java/com/android/server/attention/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/attention/OWNERS
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 4d971a5..6bc927a 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -2108,6 +2108,12 @@
         return getDevicesForAttributesInt(attributes);
     }
 
+    /** @see AudioManager#isMusicActive() */
+    public boolean isMusicActive() {
+        // no permission required
+        return AudioSystem.isStreamActive(AudioSystem.STREAM_MUSIC, 0);
+    }
+
     protected @NonNull ArrayList<AudioDeviceAttributes> getDevicesForAttributesInt(
             @NonNull AudioAttributes attributes) {
         Objects.requireNonNull(attributes);
@@ -7444,8 +7450,8 @@
     private static final int UNSAFE_VOLUME_MUSIC_ACTIVE_MS_MAX = (20 * 3600 * 1000); // 20 hours
     private static final int MUSIC_ACTIVE_POLL_PERIOD_MS = 60000;  // 1 minute polling interval
     private static final int SAFE_VOLUME_CONFIGURE_TIMEOUT_MS = 30000;  // 30s after boot completed
-    // check playback or record activity every 3 seconds for UIDs owning mode IN_COMMUNICATION
-    private static final int CHECK_MODE_FOR_UID_PERIOD_MS = 3000;
+    // check playback or record activity every 6 seconds for UIDs owning mode IN_COMMUNICATION
+    private static final int CHECK_MODE_FOR_UID_PERIOD_MS = 6000;
 
     private int safeMediaVolumeIndex(int device) {
         if (!mSafeMediaVolumeDevices.contains(device)) {
diff --git a/services/core/java/com/android/server/backup/OWNERS b/services/core/java/com/android/server/backup/OWNERS
new file mode 100644
index 0000000..d99779e
--- /dev/null
+++ b/services/core/java/com/android/server/backup/OWNERS
@@ -0,0 +1 @@
+include /services/backup/OWNERS
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java
index ce880aa..cbffdd3 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java
@@ -198,9 +198,11 @@
             final Intent intent = new Intent("android.settings.FACE_SETTINGS");
             intent.setPackage("com.android.settings");
 
+            // TODO(b/174187097) Please replace FLAG_MUTABLE_UNAUDITED below
+            // with either FLAG_IMMUTABLE (recommended) or FLAG_MUTABLE.
             final PendingIntent pendingIntent = PendingIntent.getActivityAsUser(getContext(),
-                    0 /* requestCode */, intent, 0 /* flags */, null /* options */,
-                    UserHandle.CURRENT);
+                    0 /* requestCode */, intent, PendingIntent.FLAG_MUTABLE_UNAUDITED /* flags */,
+                    null /* options */, UserHandle.CURRENT);
 
             final String channelName = "FaceEnrollNotificationChannel";
 
diff --git a/services/core/java/com/android/server/camera/OWNERS b/services/core/java/com/android/server/camera/OWNERS
new file mode 100644
index 0000000..f48a95c
--- /dev/null
+++ b/services/core/java/com/android/server/camera/OWNERS
@@ -0,0 +1 @@
+include platform/frameworks/av:/camera/OWNERS
diff --git a/services/core/java/com/android/server/connectivity/DnsManager.java b/services/core/java/com/android/server/connectivity/DnsManager.java
index 1f0fb5e..712ef76 100644
--- a/services/core/java/com/android/server/connectivity/DnsManager.java
+++ b/services/core/java/com/android/server/connectivity/DnsManager.java
@@ -34,7 +34,6 @@
 import android.net.IDnsResolver;
 import android.net.LinkProperties;
 import android.net.Network;
-import android.net.NetworkUtils;
 import android.net.ResolverOptionsParcel;
 import android.net.ResolverParamsParcel;
 import android.net.Uri;
@@ -50,6 +49,7 @@
 
 import java.net.InetAddress;
 import java.util.Arrays;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -364,12 +364,11 @@
         paramsParcel.successThreshold = mSuccessThreshold;
         paramsParcel.minSamples = mMinSamples;
         paramsParcel.maxSamples = mMaxSamples;
-        paramsParcel.servers =
-                NetworkUtils.makeStrings(lp.getDnsServers());
+        paramsParcel.servers = makeStrings(lp.getDnsServers());
         paramsParcel.domains = getDomainStrings(lp.getDomains());
         paramsParcel.tlsName = strictMode ? privateDnsCfg.hostname : "";
         paramsParcel.tlsServers =
-                strictMode ? NetworkUtils.makeStrings(
+                strictMode ? makeStrings(
                         Arrays.stream(privateDnsCfg.ips)
                               .filter((ip) -> lp.isReachable(ip))
                               .collect(Collectors.toList()))
@@ -460,6 +459,21 @@
         return Settings.Global.getInt(mContentResolver, which, dflt);
     }
 
+    /**
+     * Create a string array of host addresses from a collection of InetAddresses
+     *
+     * @param addrs a Collection of InetAddresses
+     * @return an array of Strings containing their host addresses
+     */
+    private String[] makeStrings(Collection<InetAddress> addrs) {
+        String[] result = new String[addrs.size()];
+        int i = 0;
+        for (InetAddress addr : addrs) {
+            result[i++] = addr.getHostAddress();
+        }
+        return result;
+    }
+
     private static String getPrivateDnsMode(ContentResolver cr) {
         String mode = getStringSetting(cr, PRIVATE_DNS_MODE);
         if (TextUtils.isEmpty(mode)) mode = getStringSetting(cr, PRIVATE_DNS_DEFAULT_MODE);
diff --git a/services/core/java/com/android/server/connectivity/KeepaliveTracker.java b/services/core/java/com/android/server/connectivity/KeepaliveTracker.java
index 8625a6f..96cbfde 100644
--- a/services/core/java/com/android/server/connectivity/KeepaliveTracker.java
+++ b/services/core/java/com/android/server/connectivity/KeepaliveTracker.java
@@ -40,11 +40,11 @@
 import android.annotation.Nullable;
 import android.content.Context;
 import android.net.ISocketKeepaliveCallback;
+import android.net.InetAddresses;
 import android.net.InvalidPacketException;
 import android.net.KeepalivePacketData;
 import android.net.NattKeepalivePacketData;
 import android.net.NetworkAgent;
-import android.net.NetworkUtils;
 import android.net.SocketKeepalive.InvalidSocketException;
 import android.net.TcpKeepalivePacketData;
 import android.net.util.KeepaliveUtils;
@@ -625,8 +625,8 @@
 
         InetAddress srcAddress, dstAddress;
         try {
-            srcAddress = NetworkUtils.numericToInetAddress(srcAddrString);
-            dstAddress = NetworkUtils.numericToInetAddress(dstAddrString);
+            srcAddress = InetAddresses.parseNumericAddress(srcAddrString);
+            dstAddress = InetAddresses.parseNumericAddress(dstAddrString);
         } catch (IllegalArgumentException e) {
             notifyErrorCallback(cb, ERROR_INVALID_IP_ADDRESS);
             return;
diff --git a/services/core/java/com/android/server/connectivity/NetworkDiagnostics.java b/services/core/java/com/android/server/connectivity/NetworkDiagnostics.java
index 49c16ad..a7be657 100644
--- a/services/core/java/com/android/server/connectivity/NetworkDiagnostics.java
+++ b/services/core/java/com/android/server/connectivity/NetworkDiagnostics.java
@@ -20,10 +20,10 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.net.InetAddresses;
 import android.net.LinkAddress;
 import android.net.LinkProperties;
 import android.net.Network;
-import android.net.NetworkUtils;
 import android.net.RouteInfo;
 import android.net.TrafficStats;
 import android.net.shared.PrivateDnsConfig;
@@ -97,8 +97,8 @@
 public class NetworkDiagnostics {
     private static final String TAG = "NetworkDiagnostics";
 
-    private static final InetAddress TEST_DNS4 = NetworkUtils.numericToInetAddress("8.8.8.8");
-    private static final InetAddress TEST_DNS6 = NetworkUtils.numericToInetAddress(
+    private static final InetAddress TEST_DNS4 = InetAddresses.parseNumericAddress("8.8.8.8");
+    private static final InetAddress TEST_DNS6 = InetAddresses.parseNumericAddress(
             "2001:4860:4860::8888");
 
     // For brevity elsewhere.
diff --git a/services/core/java/com/android/server/content/ContentService.java b/services/core/java/com/android/server/content/ContentService.java
index a2c427b8..027b9af 100644
--- a/services/core/java/com/android/server/content/ContentService.java
+++ b/services/core/java/com/android/server/content/ContentService.java
@@ -76,8 +76,7 @@
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.server.LocalServices;
 import com.android.server.SystemService;
-import com.android.server.SystemService.TargetUser;
-import com.android.server.pm.permission.PermissionManagerServiceInternal;
+import com.android.server.pm.permission.LegacyPermissionManagerInternal;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -296,8 +295,8 @@
 
         // Let the package manager query for the sync adapters for a given authority
         // as we grant default permissions to sync adapters for specific authorities.
-        final PermissionManagerServiceInternal permissionManagerInternal =
-                LocalServices.getService(PermissionManagerServiceInternal.class);
+        final LegacyPermissionManagerInternal permissionManagerInternal =
+                LocalServices.getService(LegacyPermissionManagerInternal.class);
         permissionManagerInternal.setSyncAdapterPackagesProvider((authority, userId) -> {
             return getSyncAdapterPackagesForAuthorityAsUser(authority, userId);
         });
diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java
index 0b2d4d7..6ae410a 100644
--- a/services/core/java/com/android/server/content/SyncManager.java
+++ b/services/core/java/com/android/server/content/SyncManager.java
@@ -3838,9 +3838,12 @@
             }
 
             UserHandle user = new UserHandle(userId);
+            // TODO(b/174186839) Please replace FLAG_MUTABLE_UNAUDITED below
+            // with either FLAG_IMMUTABLE (recommended) or FLAG_MUTABLE.
             final PendingIntent pendingIntent = PendingIntent
                     .getActivityAsUser(mContext, 0, clickIntent,
-                            PendingIntent.FLAG_CANCEL_CURRENT, null, user);
+                            PendingIntent.FLAG_CANCEL_CURRENT
+                            | PendingIntent.FLAG_MUTABLE_UNAUDITED, null, user);
 
             CharSequence tooManyDeletesDescFormat = mContext.getResources().getText(
                     R.string.contentServiceTooManyDeletesNotificationDesc);
diff --git a/services/core/java/com/android/server/contentcapture/OWNERS b/services/core/java/com/android/server/contentcapture/OWNERS
new file mode 100644
index 0000000..a28e00a
--- /dev/null
+++ b/services/core/java/com/android/server/contentcapture/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/service/contentcapture/OWNERS
diff --git a/services/core/java/com/android/server/dreams/OWNERS b/services/core/java/com/android/server/dreams/OWNERS
index 426f002..3c9bbf8 100644
--- a/services/core/java/com/android/server/dreams/OWNERS
+++ b/services/core/java/com/android/server/dreams/OWNERS
@@ -1,3 +1,3 @@
[email protected]
[email protected]
 [email protected]
 [email protected]
diff --git a/services/core/java/com/android/server/hdmi/OWNERS b/services/core/java/com/android/server/hdmi/OWNERS
new file mode 100644
index 0000000..c3c47ed
--- /dev/null
+++ b/services/core/java/com/android/server/hdmi/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/hardware/hdmi/OWNERS
diff --git a/services/core/java/com/android/server/incident/OWNERS b/services/core/java/com/android/server/incident/OWNERS
new file mode 100644
index 0000000..f766115
--- /dev/null
+++ b/services/core/java/com/android/server/incident/OWNERS
@@ -0,0 +1 @@
+include /cmds/incidentd/OWNERS
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index 42aad7d..a0121bb 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -51,6 +51,7 @@
 import android.media.AudioManager;
 import android.os.Binder;
 import android.os.Bundle;
+import android.os.CombinedVibrationEffect;
 import android.os.Environment;
 import android.os.Handler;
 import android.os.IBinder;
@@ -264,7 +265,11 @@
     private static native void nativeReloadCalibration(long ptr);
     private static native void nativeVibrate(long ptr, int deviceId, long[] pattern,
             int[] amplitudes, int repeat, int token);
+    private static native void nativeVibrateCombined(long ptr, int deviceId, long[] pattern,
+            SparseArray<int[]> amplitudes, int repeat, int token);
     private static native void nativeCancelVibrate(long ptr, int deviceId, int token);
+    private static native boolean nativeIsVibrating(long ptr, int deviceId);
+    private static native int[] nativeGetVibratorIds(long ptr, int deviceId);
     private static native void nativeReloadKeyboardLayouts(long ptr);
     private static native void nativeReloadDeviceAliases(long ptr);
     private static native String nativeDump(long ptr);
@@ -1801,43 +1806,57 @@
         return result;
     }
 
-    // Binder call
-    @Override
-    public void vibrate(int deviceId, VibrationEffect effect, IBinder token) {
-        long[] pattern;
-        int[] amplitudes;
-        int repeat;
-        if (effect instanceof VibrationEffect.OneShot) {
-            VibrationEffect.OneShot oneShot = (VibrationEffect.OneShot) effect;
-            pattern = new long[] { 0, oneShot.getDuration() };
-            int amplitude = oneShot.getAmplitude();
-            // android framework uses DEFAULT_AMPLITUDE to signal that the vibration
-            // should use some built-in default value, denoted here as DEFAULT_VIBRATION_MAGNITUDE
-            if (amplitude == VibrationEffect.DEFAULT_AMPLITUDE) {
-                amplitude = DEFAULT_VIBRATION_MAGNITUDE;
-            }
-            amplitudes = new int[] { 0, amplitude };
-            repeat = -1;
-        } else if (effect instanceof VibrationEffect.Waveform) {
-            VibrationEffect.Waveform waveform = (VibrationEffect.Waveform) effect;
-            pattern = waveform.getTimings();
-            amplitudes = waveform.getAmplitudes();
-            for (int i = 0; i < amplitudes.length; i++) {
-                if (amplitudes[i] == VibrationEffect.DEFAULT_AMPLITUDE) {
-                    amplitudes[i] = DEFAULT_VIBRATION_MAGNITUDE;
+    private static class VibrationInfo {
+        private long[] mPattern = new long[0];
+        private int[] mAmplitudes = new int[0];
+        private int mRepeat = -1;
+
+        public long[] getPattern() {
+            return mPattern;
+        }
+
+        public int[] getAmplitudes() {
+            return mAmplitudes;
+        }
+
+        public int getRepeatIndex() {
+            return mRepeat;
+        }
+
+        VibrationInfo(VibrationEffect effect) {
+            if (effect instanceof VibrationEffect.OneShot) {
+                VibrationEffect.OneShot oneShot = (VibrationEffect.OneShot) effect;
+                mPattern = new long[] { 0, oneShot.getDuration() };
+                int amplitude = oneShot.getAmplitude();
+                // android framework uses DEFAULT_AMPLITUDE to signal that the vibration
+                // should use some built-in default value, denoted here as
+                // DEFAULT_VIBRATION_MAGNITUDE
+                if (amplitude == VibrationEffect.DEFAULT_AMPLITUDE) {
+                    amplitude = DEFAULT_VIBRATION_MAGNITUDE;
                 }
+                mAmplitudes = new int[] { 0, amplitude };
+                mRepeat = -1;
+            } else if (effect instanceof VibrationEffect.Waveform) {
+                VibrationEffect.Waveform waveform = (VibrationEffect.Waveform) effect;
+                mPattern = waveform.getTimings();
+                mAmplitudes = waveform.getAmplitudes();
+                for (int i = 0; i < mAmplitudes.length; i++) {
+                    if (mAmplitudes[i] == VibrationEffect.DEFAULT_AMPLITUDE) {
+                        mAmplitudes[i] = DEFAULT_VIBRATION_MAGNITUDE;
+                    }
+                }
+                mRepeat = waveform.getRepeatIndex();
+                if (mRepeat >= mPattern.length) {
+                    throw new ArrayIndexOutOfBoundsException();
+                }
+            } else {
+                // TODO: Add support for prebaked effects
+                Slog.w(TAG, "Pre-baked effects aren't supported on input devices");
             }
-            repeat = waveform.getRepeatIndex();
-        } else {
-            // TODO: Add support for prebaked effects
-            Log.w(TAG, "Pre-baked effects aren't supported on input devices");
-            return;
         }
+    }
 
-        if (repeat >= pattern.length) {
-            throw new ArrayIndexOutOfBoundsException();
-        }
-
+    private VibratorToken getVibratorToken(int deviceId, IBinder token) {
         VibratorToken v;
         synchronized (mVibratorLock) {
             v = mVibratorTokens.get(token);
@@ -1852,9 +1871,70 @@
                 mVibratorTokens.put(token, v);
             }
         }
+        return v;
+    }
+
+    // Binder call
+    @Override
+    public void vibrate(int deviceId, VibrationEffect effect, IBinder token) {
+        VibrationInfo info = new VibrationInfo(effect);
+        VibratorToken v = getVibratorToken(deviceId, token);
         synchronized (v) {
             v.mVibrating = true;
-            nativeVibrate(mPtr, deviceId, pattern, amplitudes, repeat, v.mTokenValue);
+            nativeVibrate(mPtr, deviceId, info.getPattern(), info.getAmplitudes(),
+                    info.getRepeatIndex(), v.mTokenValue);
+        }
+    }
+
+    // Binder call
+    @Override
+    public int[] getVibratorIds(int deviceId) {
+        return nativeGetVibratorIds(mPtr, deviceId);
+    }
+
+    // Binder call
+    @Override
+    public boolean isVibrating(int deviceId) {
+        return nativeIsVibrating(mPtr, deviceId);
+    }
+
+    // Binder call
+    @Override
+    public void vibrateCombined(int deviceId, CombinedVibrationEffect effect, IBinder token) {
+        VibratorToken v = getVibratorToken(deviceId, token);
+        synchronized (v) {
+            if (!(effect instanceof CombinedVibrationEffect.Mono)
+                    && !(effect instanceof CombinedVibrationEffect.Stereo)) {
+                Slog.e(TAG, "Only Mono and Stereo effects are supported");
+                return;
+            }
+
+            v.mVibrating = true;
+            if (effect instanceof CombinedVibrationEffect.Mono) {
+                CombinedVibrationEffect.Mono mono = (CombinedVibrationEffect.Mono) effect;
+                VibrationInfo info = new VibrationInfo(mono.getEffect());
+                nativeVibrate(mPtr, deviceId, info.getPattern(), info.getAmplitudes(),
+                        info.getRepeatIndex(), v.mTokenValue);
+            } else if (effect instanceof CombinedVibrationEffect.Stereo) {
+                CombinedVibrationEffect.Stereo stereo = (CombinedVibrationEffect.Stereo) effect;
+                SparseArray<VibrationEffect> effects = stereo.getEffects();
+                long[] pattern = new long[0];
+                int repeat = Integer.MIN_VALUE;
+                SparseArray<int[]> amplitudes = new SparseArray<int[]>(effects.size());
+                for (int i = 0; i < effects.size(); i++) {
+                    VibrationInfo info = new VibrationInfo(effects.valueAt(i));
+                    // Pattern of all effects should be same
+                    if (pattern.length == 0) {
+                        pattern = info.getPattern();
+                    }
+                    if (repeat == Integer.MIN_VALUE) {
+                        repeat = info.getRepeatIndex();
+                    }
+                    amplitudes.put(effects.keyAt(i), info.getAmplitudes());
+                }
+                nativeVibrateCombined(mPtr, deviceId, pattern, amplitudes, repeat,
+                        v.mTokenValue);
+            }
         }
     }
 
diff --git a/services/core/java/com/android/server/location/LocationManagerService.java b/services/core/java/com/android/server/location/LocationManagerService.java
index e5c1986..3854f8c 100644
--- a/services/core/java/com/android/server/location/LocationManagerService.java
+++ b/services/core/java/com/android/server/location/LocationManagerService.java
@@ -57,6 +57,7 @@
 import android.location.ILocationCallback;
 import android.location.ILocationListener;
 import android.location.ILocationManager;
+import android.location.LastLocationRequest;
 import android.location.Location;
 import android.location.LocationManager;
 import android.location.LocationManagerInternal;
@@ -113,7 +114,7 @@
 import com.android.server.location.provider.PassiveLocationProvider;
 import com.android.server.location.provider.PassiveLocationProviderManager;
 import com.android.server.location.provider.proxy.ProxyLocationProvider;
-import com.android.server.pm.permission.PermissionManagerServiceInternal;
+import com.android.server.pm.permission.LegacyPermissionManagerInternal;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -261,8 +262,8 @@
 
         // Let the package manager query which are the default location
         // providers as they get certain permissions granted by default.
-        PermissionManagerServiceInternal permissionManagerInternal = LocalServices.getService(
-                PermissionManagerServiceInternal.class);
+        LegacyPermissionManagerInternal permissionManagerInternal = LocalServices.getService(
+                LegacyPermissionManagerInternal.class);
         permissionManagerInternal.setLocationPackagesProvider(
                 userId -> mContext.getResources().getStringArray(
                         com.android.internal.R.array.config_locationProviderPackageNames));
@@ -588,6 +589,30 @@
                 new String[0]);
     }
 
+    @Nullable
+    @Override
+    public ICancellationSignal getCurrentLocation(String provider, LocationRequest request,
+            ILocationCallback consumer, String packageName, String attributionTag,
+            String listenerId) {
+        CallerIdentity identity = CallerIdentity.fromBinder(mContext, packageName, attributionTag,
+                listenerId);
+        int permissionLevel = LocationPermissions.getPermissionLevel(mContext, identity.getUid(),
+                identity.getPid());
+        LocationPermissions.enforceLocationPermission(identity.getUid(), permissionLevel,
+                PERMISSION_COARSE);
+
+        // clients in the system process must have an attribution tag set
+        Preconditions.checkState(identity.getPid() != Process.myPid() || attributionTag != null);
+
+        request = validateLocationRequest(request, identity);
+
+        LocationProviderManager manager = getLocationProviderManager(provider);
+        Preconditions.checkArgument(manager != null,
+                "provider \"" + provider + "\" does not exist");
+
+        return manager.getCurrentLocation(request, identity, permissionLevel, consumer);
+    }
+
     @Override
     public void registerLocationListener(String provider, LocationRequest request,
             ILocationListener listener, String packageName, @Nullable String attributionTag,
@@ -741,7 +766,8 @@
     }
 
     @Override
-    public Location getLastLocation(String provider, String packageName, String attributionTag) {
+    public Location getLastLocation(String provider, LastLocationRequest request,
+            String packageName, String attributionTag) {
         CallerIdentity identity = CallerIdentity.fromBinder(mContext, packageName, attributionTag);
         int permissionLevel = LocationPermissions.getPermissionLevel(mContext, identity.getUid(),
                 identity.getPid());
@@ -751,36 +777,29 @@
         // clients in the system process must have an attribution tag set
         Preconditions.checkArgument(identity.getPid() != Process.myPid() || attributionTag != null);
 
+        request = validateLastLocationRequest(request);
+
         LocationProviderManager manager = getLocationProviderManager(provider);
         if (manager == null) {
             return null;
         }
 
-        return manager.getLastLocation(identity, permissionLevel, false);
+        return manager.getLastLocation(request, identity, permissionLevel);
     }
 
-    @Nullable
-    @Override
-    public ICancellationSignal getCurrentLocation(String provider, LocationRequest request,
-            ILocationCallback consumer, String packageName, String attributionTag,
-            String listenerId) {
-        CallerIdentity identity = CallerIdentity.fromBinder(mContext, packageName, attributionTag,
-                listenerId);
-        int permissionLevel = LocationPermissions.getPermissionLevel(mContext, identity.getUid(),
-                identity.getPid());
-        LocationPermissions.enforceLocationPermission(identity.getUid(), permissionLevel,
-                PERMISSION_COARSE);
+    private LastLocationRequest validateLastLocationRequest(LastLocationRequest request) {
+        if (request.isHiddenFromAppOps()) {
+            mContext.enforceCallingOrSelfPermission(
+                    permission.UPDATE_APP_OPS_STATS,
+                    "hiding from app ops requires " + permission.UPDATE_APP_OPS_STATS);
+        }
+        if (request.isLocationSettingsIgnored()) {
+            mContext.enforceCallingOrSelfPermission(
+                    permission.WRITE_SECURE_SETTINGS,
+                    "ignoring location settings requires " + permission.WRITE_SECURE_SETTINGS);
+        }
 
-        // clients in the system process must have an attribution tag set
-        Preconditions.checkState(identity.getPid() != Process.myPid() || attributionTag != null);
-
-        request = validateLocationRequest(request, identity);
-
-        LocationProviderManager manager = getLocationProviderManager(provider);
-        Preconditions.checkArgument(manager != null,
-                "provider \"" + provider + "\" does not exist");
-
-        return manager.getCurrentLocation(request, identity, permissionLevel, consumer);
+        return request;
     }
 
     @Override
diff --git a/services/core/java/com/android/server/location/gnss/GnssPowerStats.java b/services/core/java/com/android/server/location/gnss/GnssPowerStats.java
index 70ab3c6..b924d1f 100644
--- a/services/core/java/com/android/server/location/gnss/GnssPowerStats.java
+++ b/services/core/java/com/android/server/location/gnss/GnssPowerStats.java
@@ -16,8 +16,8 @@
 
 package com.android.server.location.gnss;
 
-import static android.hardware.gnss.IGnss.ELAPSED_REALTIME_HAS_TIMESTAMP_NS;
-import static android.hardware.gnss.IGnss.ELAPSED_REALTIME_HAS_TIME_UNCERTAINTY_NS;
+import static android.hardware.gnss.ElapsedRealtime.HAS_TIMESTAMP_NS;
+import static android.hardware.gnss.ElapsedRealtime.HAS_TIME_UNCERTAINTY_NS;
 
 import com.android.internal.util.Preconditions;
 
@@ -57,12 +57,12 @@
 
     /** Returns true if {@link #getElapsedRealtimeNanos()} is available. */
     public boolean hasElapsedRealtimeNanos() {
-        return (mElapsedRealtimeFlags & ELAPSED_REALTIME_HAS_TIMESTAMP_NS) != 0;
+        return (mElapsedRealtimeFlags & HAS_TIMESTAMP_NS) != 0;
     }
 
     /** Returns true if {@link #getElapsedRealtimeUncertaintyNanos()} is available. */
     public boolean hasElapsedRealtimeUncertaintyNanos() {
-        return (mElapsedRealtimeFlags & ELAPSED_REALTIME_HAS_TIME_UNCERTAINTY_NS) != 0;
+        return (mElapsedRealtimeFlags & HAS_TIME_UNCERTAINTY_NS) != 0;
     }
 
     /**
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 c5d7f2c..2fe8bcc 100644
--- a/services/core/java/com/android/server/location/provider/LocationProviderManager.java
+++ b/services/core/java/com/android/server/location/provider/LocationProviderManager.java
@@ -49,6 +49,7 @@
 import android.location.Criteria;
 import android.location.ILocationCallback;
 import android.location.ILocationListener;
+import android.location.LastLocationRequest;
 import android.location.Location;
 import android.location.LocationManager;
 import android.location.LocationManagerInternal;
@@ -1467,9 +1468,9 @@
         }
     }
 
-    public @Nullable Location getLastLocation(CallerIdentity identity,
-            @PermissionLevel int permissionLevel, boolean ignoreLocationSettings) {
-        if (!isActive(ignoreLocationSettings, identity)) {
+    public @Nullable Location getLastLocation(LastLocationRequest request,
+            CallerIdentity identity, @PermissionLevel int permissionLevel) {
+        if (!isActive(request.isLocationSettingsIgnored(), identity)) {
             return null;
         }
 
@@ -1483,7 +1484,7 @@
                 getLastLocationUnsafe(
                         identity.getUserId(),
                         permissionLevel,
-                        ignoreLocationSettings,
+                        request.isLocationSettingsIgnored(),
                         Long.MAX_VALUE),
                 permissionLevel);
 
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsShellCommand.java b/services/core/java/com/android/server/locksettings/LockSettingsShellCommand.java
index c4581c8..834cf05 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsShellCommand.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsShellCommand.java
@@ -16,8 +16,6 @@
 
 package com.android.server.locksettings;
 
-import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_NONE;
-
 import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_NONE;
 import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PATTERN;
 
@@ -271,15 +269,17 @@
     private boolean isNewCredentialSufficient(LockscreenCredential credential) {
         final PasswordMetrics requiredMetrics =
                 mLockPatternUtils.getRequestedPasswordMetrics(mCurrentUserId);
+        final int requiredComplexity =
+                mLockPatternUtils.getRequestedPasswordComplexity(mCurrentUserId);
         final List<PasswordValidationError> errors;
         if (credential.isPassword() || credential.isPin()) {
-            errors = PasswordMetrics.validatePassword(requiredMetrics, PASSWORD_COMPLEXITY_NONE,
+            errors = PasswordMetrics.validatePassword(requiredMetrics, requiredComplexity,
                     credential.isPin(), credential.getCredential());
         } else {
             PasswordMetrics metrics = new PasswordMetrics(
                     credential.isPattern() ? CREDENTIAL_TYPE_PATTERN : CREDENTIAL_TYPE_NONE);
             errors = PasswordMetrics.validatePasswordMetrics(
-                    requiredMetrics, PASSWORD_COMPLEXITY_NONE, false /* isPin */, metrics);
+                    requiredMetrics, requiredComplexity, false /* isPin */, metrics);
         }
         if (!errors.isEmpty()) {
             getOutPrintWriter().println(
diff --git a/services/core/java/com/android/server/locksettings/OWNERS b/services/core/java/com/android/server/locksettings/OWNERS
new file mode 100644
index 0000000..dad6e39
--- /dev/null
+++ b/services/core/java/com/android/server/locksettings/OWNERS
@@ -0,0 +1,2 @@
[email protected]
[email protected]
diff --git a/services/core/java/com/android/server/net/IpConfigStore.java b/services/core/java/com/android/server/net/IpConfigStore.java
index f0bf5c0..9c5abd4 100644
--- a/services/core/java/com/android/server/net/IpConfigStore.java
+++ b/services/core/java/com/android/server/net/IpConfigStore.java
@@ -16,11 +16,11 @@
 
 package com.android.server.net;
 
+import android.net.InetAddresses;
 import android.net.IpConfiguration;
 import android.net.IpConfiguration.IpAssignment;
 import android.net.IpConfiguration.ProxySettings;
 import android.net.LinkAddress;
-import android.net.NetworkUtils;
 import android.net.ProxyInfo;
 import android.net.RouteInfo;
 import android.net.StaticIpConfiguration;
@@ -284,8 +284,10 @@
                         } else if (key.equals(IP_ASSIGNMENT_KEY)) {
                             ipAssignment = IpAssignment.valueOf(in.readUTF());
                         } else if (key.equals(LINK_ADDRESS_KEY)) {
-                            LinkAddress linkAddr = new LinkAddress(
-                                    NetworkUtils.numericToInetAddress(in.readUTF()), in.readInt());
+                            LinkAddress linkAddr =
+                                    new LinkAddress(
+                                            InetAddresses.parseNumericAddress(in.readUTF()),
+                                            in.readInt());
                             if (linkAddr.getAddress() instanceof Inet4Address &&
                                     staticIpConfiguration.ipAddress == null) {
                                 staticIpConfiguration.ipAddress = linkAddr;
@@ -297,7 +299,7 @@
                             InetAddress gateway = null;
                             if (version == 1) {
                                 // only supported default gateways - leave the dest/prefix empty
-                                gateway = NetworkUtils.numericToInetAddress(in.readUTF());
+                                gateway = InetAddresses.parseNumericAddress(in.readUTF());
                                 if (staticIpConfiguration.gateway == null) {
                                     staticIpConfiguration.gateway = gateway;
                                 } else {
@@ -305,12 +307,13 @@
                                 }
                             } else {
                                 if (in.readInt() == 1) {
-                                    dest = new LinkAddress(
-                                            NetworkUtils.numericToInetAddress(in.readUTF()),
-                                            in.readInt());
+                                    dest =
+                                            new LinkAddress(
+                                                    InetAddresses.parseNumericAddress(in.readUTF()),
+                                                    in.readInt());
                                 }
                                 if (in.readInt() == 1) {
-                                    gateway = NetworkUtils.numericToInetAddress(in.readUTF());
+                                    gateway = InetAddresses.parseNumericAddress(in.readUTF());
                                 }
                                 RouteInfo route = new RouteInfo(dest, gateway);
                                 if (route.isIPv4Default() &&
@@ -322,7 +325,7 @@
                             }
                         } else if (key.equals(DNS_KEY)) {
                             staticIpConfiguration.dnsServers.add(
-                                    NetworkUtils.numericToInetAddress(in.readUTF()));
+                                    InetAddresses.parseNumericAddress(in.readUTF()));
                         } else if (key.equals(PROXY_SETTINGS_KEY)) {
                             proxySettings = ProxySettings.valueOf(in.readUTF());
                         } else if (key.equals(PROXY_HOST_KEY)) {
diff --git a/services/core/java/com/android/server/net/OWNERS b/services/core/java/com/android/server/net/OWNERS
index 28ae6a4..d5c7618 100644
--- a/services/core/java/com/android/server/net/OWNERS
+++ b/services/core/java/com/android/server/net/OWNERS
@@ -2,7 +2,7 @@
 
 [email protected]
 [email protected]
[email protected]
[email protected]
 [email protected]
 [email protected]
 [email protected]
diff --git a/services/core/java/com/android/server/notification/ConditionProviders.java b/services/core/java/com/android/server/notification/ConditionProviders.java
index 8200ca0..769b781 100644
--- a/services/core/java/com/android/server/notification/ConditionProviders.java
+++ b/services/core/java/com/android/server/notification/ConditionProviders.java
@@ -123,7 +123,7 @@
         final Config c = new Config();
         c.caption = "condition provider";
         c.serviceInterface = ConditionProviderService.SERVICE_INTERFACE;
-        c.secureSettingName = Settings.Secure.ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES;
+        c.secureSettingName = null;
         c.xmlTag = TAG_ENABLED_DND_APPS;
         c.secondarySettingName = Settings.Secure.ENABLED_NOTIFICATION_LISTENERS;
         c.bindPermission = android.Manifest.permission.BIND_CONDITION_PROVIDER_SERVICE;
diff --git a/services/core/java/com/android/server/notification/ManagedServices.java b/services/core/java/com/android/server/notification/ManagedServices.java
index a7ee272..54e9b37 100644
--- a/services/core/java/com/android/server/notification/ManagedServices.java
+++ b/services/core/java/com/android/server/notification/ManagedServices.java
@@ -437,9 +437,15 @@
                         }
                     }
                 }
-                Settings.Secure.putStringForUser(
-                        mContext.getContentResolver(), element, value, userId);
-                loadAllowedComponentsFromSettings();
+                if (shouldReflectToSettings()) {
+                    Settings.Secure.putStringForUser(
+                            mContext.getContentResolver(), element, value, userId);
+                }
+
+                for (UserInfo user : mUm.getUsers()) {
+                    addApprovedList(value, user.id, mConfig.secureSettingName.equals(element));
+                }
+                Slog.d(TAG, "Done loading approved values from settings");
                 rebindServices(false, userId);
             }
         }
@@ -498,10 +504,13 @@
                             out.endTag(null, TAG_MANAGED_SERVICES);
 
                             if (!forBackup && isPrimary) {
-                                // Also write values to settings, for observers who haven't migrated yet
-                                Settings.Secure.putStringForUser(mContext.getContentResolver(),
-                                        getConfig().secureSettingName, allowedItems,
-                                        approvedUserId);
+                                if (shouldReflectToSettings()) {
+                                    // Also write values to settings, for observers who haven't
+                                    // migrated yet
+                                    Settings.Secure.putStringForUser(mContext.getContentResolver(),
+                                            getConfig().secureSettingName, allowedItems,
+                                            approvedUserId);
+                                }
                             }
 
                         }
@@ -516,6 +525,13 @@
     }
 
     /**
+     * Returns whether the approved list of services should also be written to the Settings db
+     */
+    protected boolean shouldReflectToSettings() {
+        return false;
+    }
+
+    /**
      * Writes extra xml attributes to {@link #TAG_MANAGED_SERVICES} tag.
      */
     protected void writeExtraAttributes(TypedXmlSerializer out, int userId) throws IOException {}
@@ -530,8 +546,20 @@
      */
     protected void readExtraTag(String tag, TypedXmlPullParser parser) throws IOException {}
 
-    protected void migrateToXml() {
-        loadAllowedComponentsFromSettings();
+    protected final void migrateToXml() {
+        for (UserInfo user : mUm.getUsers()) {
+            final ContentResolver cr = mContext.getContentResolver();
+            addApprovedList(Settings.Secure.getStringForUser(
+                    cr,
+                    getConfig().secureSettingName,
+                    user.id), user.id, true);
+            if (!TextUtils.isEmpty(getConfig().secondarySettingName)) {
+                addApprovedList(Settings.Secure.getStringForUser(
+                        cr,
+                        getConfig().secondarySettingName,
+                        user.id), user.id, false);
+            }
+        }
     }
 
     void readDefaults(TypedXmlPullParser parser) {
@@ -638,23 +666,6 @@
 
     protected abstract String getRequiredPermission();
 
-    private void loadAllowedComponentsFromSettings() {
-        for (UserInfo user : mUm.getUsers()) {
-            final ContentResolver cr = mContext.getContentResolver();
-            addApprovedList(Settings.Secure.getStringForUser(
-                    cr,
-                    getConfig().secureSettingName,
-                    user.id), user.id, true);
-            if (!TextUtils.isEmpty(getConfig().secondarySettingName)) {
-                addApprovedList(Settings.Secure.getStringForUser(
-                        cr,
-                        getConfig().secondarySettingName,
-                        user.id), user.id, false);
-            }
-        }
-        Slog.d(TAG, "Done loading approved values from settings");
-    }
-
     protected void addApprovedList(String approved, int userId, boolean isPrimary) {
         addApprovedList(approved, userId, isPrimary, approved);
     }
diff --git a/services/core/java/com/android/server/notification/NotificationHistoryDatabase.java b/services/core/java/com/android/server/notification/NotificationHistoryDatabase.java
index 7257f52..c1deb96 100644
--- a/services/core/java/com/android/server/notification/NotificationHistoryDatabase.java
+++ b/services/core/java/com/android/server/notification/NotificationHistoryDatabase.java
@@ -293,7 +293,9 @@
                                 .appendPath(file.getAbsolutePath()).build())
                         .addFlags(Intent.FLAG_RECEIVER_FOREGROUND)
                         .putExtra(EXTRA_KEY, file.getAbsolutePath()),
-                PendingIntent.FLAG_UPDATE_CURRENT);
+                // TODO(b/174161800) Please replace FLAG_MUTABLE_UNAUDITED below
+                // with either FLAG_IMMUTABLE (recommended) or FLAG_MUTABLE.
+                PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE_UNAUDITED);
         mAlarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, deletionTime, pi);
     }
 
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 9efbb69..692e97a 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -7169,15 +7169,15 @@
         if (record.getSbn().isGroup() && record.getNotification().suppressAlertingDueToGrouping()) {
             return false;
         }
-        // not if in call or the screen's on
-        if (isInCall() || mScreenOn) {
+        // not if in call
+        if (isInCall()) {
             return false;
         }
         // check current user
         if (!isNotificationForCurrentUser(record)) {
             return false;
         }
-
+        // Light, but only when the screen is off
         return true;
     }
 
@@ -9527,6 +9527,13 @@
             return null;
         }
 
+        @Override
+        protected boolean shouldReflectToSettings() {
+            // androidx has a public method that reads the approved set of listeners from
+            // Settings so we have to continue writing this list for this type of service
+            return true;
+        }
+
         @GuardedBy("mNotificationLock")
         public void setOnNotificationPostedTrimLocked(ManagedServiceInfo info, int trim) {
             if (trim == TRIM_LIGHT) {
diff --git a/services/core/java/com/android/server/notification/OWNERS b/services/core/java/com/android/server/notification/OWNERS
index 5a19656..4dcb799 100644
--- a/services/core/java/com/android/server/notification/OWNERS
+++ b/services/core/java/com/android/server/notification/OWNERS
@@ -1,4 +1,4 @@
[email protected]
[email protected]
 [email protected]
 [email protected]
 [email protected]
diff --git a/services/core/java/com/android/server/notification/SnoozeHelper.java b/services/core/java/com/android/server/notification/SnoozeHelper.java
index 2122b9c..3e197fb 100644
--- a/services/core/java/com/android/server/notification/SnoozeHelper.java
+++ b/services/core/java/com/android/server/notification/SnoozeHelper.java
@@ -462,6 +462,8 @@
     }
 
     private PendingIntent createPendingIntent(String pkg, String key, int userId) {
+        // TODO(b/174969959) Please replace FLAG_MUTABLE_UNAUDITED below
+        // with either FLAG_IMMUTABLE (recommended) or FLAG_MUTABLE.
         return PendingIntent.getBroadcast(mContext,
                 REQUEST_CODE_REPOST,
                 new Intent(REPOST_ACTION)
@@ -469,7 +471,7 @@
                         .addFlags(Intent.FLAG_RECEIVER_FOREGROUND)
                         .putExtra(EXTRA_KEY, key)
                         .putExtra(EXTRA_USER_ID, userId),
-                PendingIntent.FLAG_UPDATE_CURRENT);
+                PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE_UNAUDITED);
     }
 
     public void scheduleRepostsForPersistedNotifications(long currentTime) {
diff --git a/services/core/java/com/android/server/om/OWNERS b/services/core/java/com/android/server/om/OWNERS
new file mode 100644
index 0000000..afb98d4
--- /dev/null
+++ b/services/core/java/com/android/server/om/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/content/om/OWNERS
diff --git a/services/core/java/com/android/server/om/TEST_MAPPING b/services/core/java/com/android/server/om/TEST_MAPPING
index 6edd76f..e8a2a02 100644
--- a/services/core/java/com/android/server/om/TEST_MAPPING
+++ b/services/core/java/com/android/server/om/TEST_MAPPING
@@ -15,9 +15,6 @@
       "name": "OverlayHostTests"
     },
     {
-      "name": "OverlayRemountedTest"
-    },
-    {
       "name": "CtsAppSecurityHostTestCases",
       "options": [
         {
@@ -25,5 +22,10 @@
         }
       ]
     }
+  ],
+  "presubmit-large": [
+    {
+      "name": "OverlayRemountedTest"
+    }
   ]
 }
diff --git a/services/core/java/com/android/server/people/OWNERS b/services/core/java/com/android/server/people/OWNERS
new file mode 100644
index 0000000..3198a5e
--- /dev/null
+++ b/services/core/java/com/android/server/people/OWNERS
@@ -0,0 +1 @@
+include /services/people/OWNERS
diff --git a/services/core/java/com/android/server/pm/DefaultAppProvider.java b/services/core/java/com/android/server/pm/DefaultAppProvider.java
index cc11fb2..a17967fc 100644
--- a/services/core/java/com/android/server/pm/DefaultAppProvider.java
+++ b/services/core/java/com/android/server/pm/DefaultAppProvider.java
@@ -27,7 +27,6 @@
 import com.android.internal.infra.AndroidFuture;
 import com.android.internal.util.CollectionUtils;
 import com.android.server.FgThread;
-import com.android.server.pm.permission.PermissionManagerServiceInternal;
 
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Executor;
@@ -42,19 +41,14 @@
 public class DefaultAppProvider {
     @NonNull
     private final Supplier<RoleManager> mRoleManagerSupplier;
-    @NonNull
-    private final PermissionManagerServiceInternal mPermissionManager;
 
     /**
      * Create a new instance of this class
      *
      * @param roleManagerSupplier the supplier for {@link RoleManager}
-     * @param permissionManager the {@link PermissionManagerServiceInternal}
      */
-    public DefaultAppProvider(@NonNull Supplier<RoleManager> roleManagerSupplier, @NonNull
-            PermissionManagerServiceInternal permissionManager) {
+    public DefaultAppProvider(@NonNull Supplier<RoleManager> roleManagerSupplier) {
         mRoleManagerSupplier = roleManagerSupplier;
-        mPermissionManager = permissionManager;
     }
 
     /**
@@ -73,11 +67,10 @@
      *
      * @param packageName package name of the default browser, or {@code null} to unset
      * @param async whether the operation should be asynchronous
-     * @param doGrant whether to grant default permissions
      * @param userId the user ID
      * @return whether the default browser was successfully set.
      */
-    public boolean setDefaultBrowser(@Nullable String packageName, boolean async, boolean doGrant,
+    public boolean setDefaultBrowser(@Nullable String packageName, boolean async,
             @UserIdInt int userId) {
         if (userId == UserHandle.USER_ALL) {
             return false;
@@ -114,9 +107,6 @@
                     return false;
                 }
             }
-            if (doGrant && packageName != null) {
-                mPermissionManager.grantDefaultPermissionsToDefaultBrowser(packageName, userId);
-            }
         } finally {
             Binder.restoreCallingIdentity(identity);
         }
diff --git a/services/core/java/com/android/server/pm/OWNERS b/services/core/java/com/android/server/pm/OWNERS
index cca2b83..7a2b7a6 100644
--- a/services/core/java/com/android/server/pm/OWNERS
+++ b/services/core/java/com/android/server/pm/OWNERS
@@ -1,12 +1,12 @@
[email protected]
 [email protected]
[email protected]
[email protected]
[email protected]
 [email protected]
 [email protected]
 [email protected]
[email protected]
 [email protected]
[email protected]
[email protected]
[email protected]
 [email protected]
 
 # apex support
@@ -30,9 +30,10 @@
 per-file CrossProfileAppsService.java = [email protected], [email protected]
 per-file CrossProfileIntentFilter.java = [email protected], [email protected]
 per-file CrossProfileIntentResolver.java = [email protected], [email protected]
+per-file RestrictionsSet.java = [email protected], [email protected], [email protected], [email protected], [email protected]
+per-file UserManagerInternal.java = [email protected], [email protected], [email protected]
 per-file UserManagerService.java = [email protected], [email protected], [email protected]
 per-file UserRestrictionsUtils.java = [email protected], [email protected], [email protected], [email protected]
-per-file RestrictionsSet.java = [email protected], [email protected], [email protected], [email protected], [email protected]
 per-file UserSystemPackageInstaller.java = [email protected], [email protected], [email protected]
 per-file UserTypeDetails.java = [email protected], [email protected], [email protected]
 per-file UserTypeFactory.java = [email protected], [email protected], [email protected]
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index 4cee2e5..34bee95 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -686,11 +686,6 @@
             }
         }
 
-        if (params.whitelistedRestrictedPermissions != null) {
-            mPermissionManager.retainHardAndSoftRestrictedPermissions(
-                    params.whitelistedRestrictedPermissions);
-        }
-
         final int sessionId;
         final PackageInstallerSession session;
         synchronized (mSessions) {
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 0aebe72..4ab1282 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -756,6 +756,7 @@
 
             info.mode = params.mode;
             info.installReason = params.installReason;
+            info.installScenario = params.installScenario;
             info.sizeBytes = params.sizeBytes;
             info.appPackageName = mPackageName != null ? mPackageName : params.appPackageName;
             if (includeIcon) {
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 6aa4589..72dad61 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -380,6 +380,8 @@
 import com.android.server.pm.parsing.pkg.AndroidPackageUtils;
 import com.android.server.pm.parsing.pkg.PackageImpl;
 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.Permission;
 import com.android.server.pm.permission.PermissionManagerService;
 import com.android.server.pm.permission.PermissionManagerServiceInternal;
@@ -696,10 +698,15 @@
     public static final int REASON_FIRST_BOOT = 0;
     public static final int REASON_BOOT = 1;
     public static final int REASON_INSTALL = 2;
-    public static final int REASON_BACKGROUND_DEXOPT = 3;
-    public static final int REASON_AB_OTA = 4;
-    public static final int REASON_INACTIVE_PACKAGE_DOWNGRADE = 5;
-    public static final int REASON_SHARED = 6;
+    public static final int REASON_INSTALL_FAST = 3;
+    public static final int REASON_INSTALL_BULK = 4;
+    public static final int REASON_INSTALL_BULK_SECONDARY = 5;
+    public static final int REASON_INSTALL_BULK_DOWNGRADED = 6;
+    public static final int REASON_INSTALL_BULK_SECONDARY_DOWNGRADED = 7;
+    public static final int REASON_BACKGROUND_DEXOPT = 8;
+    public static final int REASON_AB_OTA = 9;
+    public static final int REASON_INACTIVE_PACKAGE_DOWNGRADE = 10;
+    public static final int REASON_SHARED = 11;
 
     public static final int REASON_LAST = REASON_SHARED;
 
@@ -961,6 +968,8 @@
         private final Singleton<PackageInstallerService> mPackageInstallerServiceProducer;
         private final ProducerWithArgument<InstantAppResolverConnection, ComponentName>
                 mInstantAppResolverConnectionProducer;
+        private final Singleton<LegacyPermissionManagerInternal>
+                mLegacyPermissionManagerInternalProducer;
         private final SystemWrapper mSystemWrapper;
         private final ServiceProducer mGetLocalServiceProducer;
         private final ServiceProducer mGetSystemServiceProducer;
@@ -993,6 +1002,7 @@
                 ProducerWithArgument<InstantAppResolverConnection, ComponentName> 
                         instantAppResolverConnectionProducer,
                 Producer<ModuleInfoProvider> moduleInfoProviderProducer,
+                Producer<LegacyPermissionManagerInternal> legacyPermissionManagerInternalProducer,
                 SystemWrapper systemWrapper,
                 ServiceProducer getLocalServiceProducer,
                 ServiceProducer getSystemServiceProducer) {
@@ -1026,6 +1036,8 @@
             mPackageInstallerServiceProducer = new Singleton<>(packageInstallerServiceProducer);
             mInstantAppResolverConnectionProducer = instantAppResolverConnectionProducer;
             mModuleInfoProviderProducer = new Singleton<>(moduleInfoProviderProducer);
+            mLegacyPermissionManagerInternalProducer = new Singleton<>(
+                    legacyPermissionManagerInternalProducer);
             mSystemWrapper = systemWrapper;
             mGetLocalServiceProducer = getLocalServiceProducer;
             mGetSystemServiceProducer = getSystemServiceProducer;
@@ -1174,6 +1186,10 @@
         public ModuleInfoProvider getModuleInfoProvider() {
             return mModuleInfoProviderProducer.get(this, mPackageManager);
         }
+
+        public LegacyPermissionManagerInternal getLegacyPermissionManagerInternal() {
+            return mLegacyPermissionManagerInternalProducer.get(this, mPackageManager);
+        }
     }
 
     /** Provides an abstraction to static access to system state. */
@@ -1232,6 +1248,7 @@
         public boolean isPreNupgrade;
         public boolean isPreQupgrade;
         public boolean isUpgrade;
+        public LegacyPermissionManagerInternal legacyPermissionManagerInternal;
         public DisplayMetrics Metrics;
         public ModuleInfoProvider moduleInfoProvider;
         public MoveCallbacks moveCallbacks;
@@ -1375,6 +1392,8 @@
 
     private final DefaultAppProvider mDefaultAppProvider;
 
+    private final LegacyPermissionManagerInternal mLegacyPermissionManager;
+
     private final PackageProperty mPackageProperty = new PackageProperty();
 
     private static class IFVerificationParams {
@@ -2838,8 +2857,8 @@
                 (i, pm) -> new ViewCompiler(i.getInstallLock(), i.getInstaller()),
                 (i, pm) -> (IncrementalManager)
                         i.getContext().getSystemService(Context.INCREMENTAL_SERVICE),
-                (i, pm) -> new DefaultAppProvider(() -> context.getSystemService(RoleManager.class),
-                        i.getPermissionManagerServiceInternal()),
+                (i, pm) -> new DefaultAppProvider(() -> context.getSystemService(
+                        RoleManager.class)),
                 (i, pm) -> new DisplayMetrics(),
                 (i, pm) -> new PackageParser2(pm.mSeparateProcesses, pm.mOnlyCore,
                         i.getDisplayMetrics(), pm.mCacheDir,
@@ -2856,6 +2875,7 @@
                 (i, pm, cn) -> new InstantAppResolverConnection(
                         i.getContext(), cn, Intent.ACTION_RESOLVE_INSTANT_APP_PACKAGE),
                 (i, pm) -> new ModuleInfoProvider(i.getContext(), pm),
+                (i, pm) -> LegacyPermissionManagerService.create(i.getContext()),
                 new DefaultSystemWrapper(),
                 LocalServices::getService,
                 context::getSystemService);
@@ -3032,6 +3052,7 @@
         mAvailableFeatures = testParams.availableFeatures;
         mDefParseFlags = testParams.defParseFlags;
         mDefaultAppProvider = testParams.defaultAppProvider;
+        mLegacyPermissionManager = testParams.legacyPermissionManagerInternal;
         mDexManager = testParams.dexManager;
         mDirsToScanAsSystem = testParams.dirsToScanAsSystem;
         mFactoryTest = testParams.factoryTest;
@@ -3136,6 +3157,7 @@
         mPermissionManagerService = injector.getPermissionManagerService();
         mIncrementalManager = mInjector.getIncrementalManager();
         mDefaultAppProvider = mInjector.getDefaultAppProvider();
+        mLegacyPermissionManager = mInjector.getLegacyPermissionManagerInternal();
         PlatformCompat platformCompat = mInjector.getCompatibility();
         mPackageParserCallback = new PackageParser2.Callback() {
             @Override
@@ -15291,6 +15313,7 @@
         final int autoRevokePermissionsMode;
         final PackageParser.SigningDetails signingDetails;
         final int installReason;
+        final int mInstallScenario;
         @Nullable MultiPackageInstallParams mParentInstallParams;
         final boolean forceQueryableOverride;
         final int mDataLoaderType;
@@ -15314,6 +15337,7 @@
             this.autoRevokePermissionsMode = MODE_DEFAULT;
             this.signingDetails = PackageParser.SigningDetails.UNKNOWN;
             this.installReason = PackageManager.INSTALL_REASON_UNKNOWN;
+            this.mInstallScenario = PackageManager.INSTALL_SCENARIO_DEFAULT;
             this.forceQueryableOverride = false;
             this.mDataLoaderType = DataLoaderType.NONE;
             this.requiredInstalledVersionCode = PackageManager.VERSION_CODE_HIGHEST;
@@ -15329,6 +15353,7 @@
             move = null;
             installReason = fixUpInstallReason(
                     installSource.installerPackageName, installerUid, sessionParams.installReason);
+            mInstallScenario = sessionParams.installScenario;
             this.observer = observer;
             installFlags = sessionParams.installFlags;
             this.installSource = installSource;
@@ -16057,6 +16082,7 @@
         final int traceCookie;
         final PackageParser.SigningDetails signingDetails;
         final int installReason;
+        final int mInstallScenario;
         final boolean forceQueryableOverride;
         final int mDataLoaderType;
 
@@ -16072,7 +16098,8 @@
                 List<String> whitelistedRestrictedPermissions,
                 int autoRevokePermissionsMode,
                 String traceMethod, int traceCookie, SigningDetails signingDetails,
-                int installReason, boolean forceQueryableOverride, int dataLoaderType) {
+                int installReason, int installScenario, boolean forceQueryableOverride,
+                int dataLoaderType) {
             this.origin = origin;
             this.move = move;
             this.installFlags = installFlags;
@@ -16089,6 +16116,7 @@
             this.traceCookie = traceCookie;
             this.signingDetails = signingDetails;
             this.installReason = installReason;
+            this.mInstallScenario = installScenario;
             this.forceQueryableOverride = forceQueryableOverride;
             this.mDataLoaderType = dataLoaderType;
         }
@@ -16101,7 +16129,8 @@
                     params.grantedRuntimePermissions, params.whitelistedRestrictedPermissions,
                     params.autoRevokePermissionsMode,
                     params.traceMethod, params.traceCookie, params.signingDetails,
-                    params.installReason, params.forceQueryableOverride, params.mDataLoaderType);
+                    params.installReason, params.mInstallScenario, params.forceQueryableOverride,
+                    params.mDataLoaderType);
         }
 
         abstract int copyApk();
@@ -16190,8 +16219,8 @@
             super(OriginInfo.fromNothing(), null, null, 0, InstallSource.EMPTY,
                     null, null, instructionSets, null, null, null, MODE_DEFAULT, null, 0,
                     PackageParser.SigningDetails.UNKNOWN,
-                    PackageManager.INSTALL_REASON_UNKNOWN, false,
-                    DataLoaderType.NONE);
+                    PackageManager.INSTALL_REASON_UNKNOWN, PackageManager.INSTALL_SCENARIO_DEFAULT,
+                    false, DataLoaderType.NONE);
             this.codeFile = (codePath != null) ? new File(codePath) : null;
         }
 
@@ -17517,6 +17546,26 @@
                     resolveUserIds(reconciledPkg.installArgs.user.getIdentifier()),
                     /* updateReferenceProfileContent= */ true);
 
+            // Compute the compilation reason from the installation scenario.
+            final int compilationReason = mDexManager.getCompilationReasonForInstallScenario(
+                    reconciledPkg.installArgs.mInstallScenario);
+
+            // Construct the DexoptOptions early to see if we should skip running dexopt.
+            //
+            // Do not run PackageDexOptimizer through the local performDexOpt
+            // method because `pkg` may not be in `mPackages` yet.
+            //
+            // Also, don't fail application installs if the dexopt step fails.
+            final boolean isBackupOrRestore =
+                    reconciledPkg.installArgs.installReason == INSTALL_REASON_DEVICE_RESTORE
+                    || reconciledPkg.installArgs.installReason == INSTALL_REASON_DEVICE_SETUP;
+
+            final int dexoptFlags = DexoptOptions.DEXOPT_BOOT_COMPLETE
+                    | DexoptOptions.DEXOPT_INSTALL_WITH_DEX_METADATA_FILE
+                    | (isBackupOrRestore ? DexoptOptions.DEXOPT_FOR_RESTORE : 0);
+            DexoptOptions dexoptOptions =
+                    new DexoptOptions(packageName, compilationReason, dexoptFlags);
+
             // Check whether we need to dexopt the app.
             //
             // NOTE: it is IMPORTANT to call dexopt:
@@ -17537,11 +17586,18 @@
             // continuous progress to the useur instead of mysteriously blocking somewhere in the
             // middle of running an instant app. The default behaviour can be overridden
             // via gservices.
+            //
+            // Furthermore, dexopt may be skipped, depending on the install scenario and current
+            // state of the device.
+            //
+            // TODO(b/174695087): instantApp and onIncremental should be removed and their install
+            //       path moved to SCENARIO_FAST.
             final boolean performDexopt =
                     (!instantApp || Global.getInt(mContext.getContentResolver(),
                     Global.INSTANT_APP_DEXOPT_ENABLED, 0) != 0)
                     && !pkg.isDebuggable()
-                    && (!onIncremental);
+                    && (!onIncremental)
+                    && dexoptOptions.isCompilationEnabled();
 
             if (performDexopt) {
                 // Compile the layout resources.
@@ -17552,19 +17608,6 @@
                 }
 
                 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "dexopt");
-                // Do not run PackageDexOptimizer through the local performDexOpt
-                // method because `pkg` may not be in `mPackages` yet.
-                //
-                // Also, don't fail application installs if the dexopt step fails.
-                int flags = DexoptOptions.DEXOPT_BOOT_COMPLETE
-                        | DexoptOptions.DEXOPT_INSTALL_WITH_DEX_METADATA_FILE;
-                if (reconciledPkg.installArgs.installReason == INSTALL_REASON_DEVICE_RESTORE
-                        || reconciledPkg.installArgs.installReason == INSTALL_REASON_DEVICE_SETUP) {
-                    flags |= DexoptOptions.DEXOPT_FOR_RESTORE;
-                }
-                DexoptOptions dexoptOptions = new DexoptOptions(packageName,
-                        REASON_INSTALL,
-                        flags);
                 ScanResult result = reconciledPkg.scanResult;
 
                 // This mirrors logic from commitReconciledScanResultLocked, where the library files
@@ -20702,7 +20745,7 @@
         final String defaultBrowserPackageName = mDefaultAppProvider.getDefaultBrowser(userId);
         if (!TextUtils.isEmpty(defaultBrowserPackageName)) {
             if (packageName.equals(defaultBrowserPackageName)) {
-                mDefaultAppProvider.setDefaultBrowser(null, true, true, userId);
+                mDefaultAppProvider.setDefaultBrowser(null, true, userId);
             }
         }
     }
@@ -20717,14 +20760,13 @@
             // If this browser is restored from user's backup, do not clear
             // default-browser state for this user
             if (installReason != PackageManager.INSTALL_REASON_DEVICE_RESTORE) {
-                mDefaultAppProvider.setDefaultBrowser(null, true, true, userId);
+                mDefaultAppProvider.setDefaultBrowser(null, true, userId);
             }
         }
 
         // We may also need to apply pending (restored) runtime permission grants
         // within these users.
-        mPermissionManager.restoreDelayedRuntimePermissions(packageName,
-                UserHandle.of(userId));
+        mPermissionManager.restoreDelayedRuntimePermissions(packageName, userId);
 
         // Persistent preferred activity might have came into effect due to this
         // install.
@@ -20756,7 +20798,7 @@
             // significant refactoring to keep all default apps in the package
             // manager (cleaner but more work) or have the services provide
             // callbacks to the package manager to request a default app reset.
-            mDefaultAppProvider.setDefaultBrowser(null, true, true, userId);
+            mDefaultAppProvider.setDefaultBrowser(null, true, userId);
             resetNetworkPolicies(userId);
             synchronized (mLock) {
                 scheduleWritePackageRestrictionsLocked(userId);
@@ -20990,8 +21032,7 @@
                             defaultBrowser = mSettings.removeDefaultBrowserPackageNameLPw(userId1);
                         }
                         if (defaultBrowser != null) {
-                            mDefaultAppProvider.setDefaultBrowser(defaultBrowser, false, false,
-                                    userId1);
+                            mDefaultAppProvider.setDefaultBrowser(defaultBrowser, false, userId1);
                         }
                     });
         } catch (Exception e) {
@@ -22251,6 +22292,24 @@
 
         mPermissionManager.systemReady();
 
+        int[] grantPermissionsUserIds = EMPTY_INT_ARRAY;
+        for (int userId : UserManagerService.getInstance().getUserIds()) {
+            if (mPmInternal.isPermissionUpgradeNeeded(userId)) {
+                grantPermissionsUserIds = ArrayUtils.appendInt(
+                        grantPermissionsUserIds, userId);
+            }
+        }
+        // If we upgraded grant all default permissions before kicking off.
+        for (int userId : grantPermissionsUserIds) {
+            mLegacyPermissionManager.grantDefaultPermissions(userId);
+        }
+        if (grantPermissionsUserIds == EMPTY_INT_ARRAY) {
+            // If we did not grant default permissions, we preload from this the
+            // default permission exceptions lazily to ensure we don't hit the
+            // disk on a new user creation.
+            mLegacyPermissionManager.scheduleReadDefaultPermissionExceptions();
+        }
+
         if (mInstantAppResolverConnection != null) {
             mContext.registerReceiver(new BroadcastReceiver() {
                 @Override
@@ -24332,14 +24391,9 @@
             Slog.d(TAG, "onNewUserCreated(id=" + userId
                     + ", convertedFromPreCreated=" + convertedFromPreCreated + ")");
         }
-        if (!convertedFromPreCreated) {
-            mPermissionManager.onNewUserCreated(userId);
-            return;
-        }
-        if (!readPermissionStateForUser(userId)) {
-            // Could not read the existing permissions, re-grant them.
-            Slog.i(TAG, "re-granting permissions for pre-created user " + userId);
-            mPermissionManager.onNewUserCreated(userId);
+        if (!convertedFromPreCreated || !readPermissionStateForUser(userId)) {
+            mPermissionManager.onUserCreated(userId);
+            mLegacyPermissionManager.grantDefaultPermissions(userId);
         }
     }
 
@@ -25886,18 +25940,6 @@
         }
 
         @Override
-        public void setReadExternalStorageEnforced(boolean enforced) {
-            synchronized (mLock) {
-                if (mSettings.mReadExternalStorageEnforced != null
-                        && mSettings.mReadExternalStorageEnforced == enforced) {
-                    return;
-                }
-                mSettings.mReadExternalStorageEnforced = enforced ? Boolean.TRUE : Boolean.FALSE;
-                writeSettingsLPrTEMP();
-            }
-        }
-
-        @Override
         public void setIntegrityVerificationResult(int verificationId, int verificationResult) {
             final Message msg = mHandler.obtainMessage(INTEGRITY_VERIFICATION_COMPLETE);
             msg.arg1 = verificationId;
diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceCompilerMapping.java b/services/core/java/com/android/server/pm/PackageManagerServiceCompilerMapping.java
index 5fc5bac..9cd55a6 100644
--- a/services/core/java/com/android/server/pm/PackageManagerServiceCompilerMapping.java
+++ b/services/core/java/com/android/server/pm/PackageManagerServiceCompilerMapping.java
@@ -18,6 +18,8 @@
 
 import android.os.SystemProperties;
 
+import com.android.server.pm.dex.DexoptOptions;
+
 import dalvik.system.DexFile;
 
 /**
@@ -26,10 +28,22 @@
 public class PackageManagerServiceCompilerMapping {
     // Names for compilation reasons.
     public static final String REASON_STRINGS[] = {
-            "first-boot", "boot", "install", "bg-dexopt", "ab-ota", "inactive", "shared"
+        "first-boot",
+        "boot",
+        "install",
+        "install-fast",
+        "install-bulk",
+        "install-bulk-secondary",
+        "install-bulk-downgraded",
+        "install-bulk-secondary-downgraded",
+        "bg-dexopt",
+        "ab-ota",
+        "inactive",
+        // "shared" must be the last entry
+        "shared"
     };
 
-    static final int REASON_SHARED_INDEX = 6;
+    static final int REASON_SHARED_INDEX = REASON_STRINGS.length - 1;
 
     // Static block to ensure the strings array is of the right length.
     static {
@@ -53,8 +67,9 @@
     // exception in case the reason or value are invalid.
     private static String getAndCheckValidity(int reason) {
         String sysPropValue = SystemProperties.get(getSystemPropertyName(reason));
-        if (sysPropValue == null || sysPropValue.isEmpty() ||
-                !DexFile.isValidCompilerFilter(sysPropValue)) {
+        if (sysPropValue == null || sysPropValue.isEmpty()
+                || !(sysPropValue.equals(DexoptOptions.COMPILER_FILTER_NOOP)
+                        || DexFile.isValidCompilerFilter(sysPropValue))) {
             throw new IllegalStateException("Value \"" + sysPropValue +"\" not valid "
                     + "(reason " + REASON_STRINGS[reason] + ")");
         } else if (!isFilterAllowedForReason(reason, sysPropValue)) {
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index fa100dc..2f6756d 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -27,7 +27,6 @@
 import android.annotation.UserIdInt;
 import android.app.ActivityManager;
 import android.app.ActivityManagerInternal;
-import android.app.role.IRoleManager;
 import android.app.role.RoleManager;
 import android.content.ComponentName;
 import android.content.Context;
@@ -80,7 +79,6 @@
 import android.os.ParcelFileDescriptor.AutoCloseInputStream;
 import android.os.PersistableBundle;
 import android.os.Process;
-import android.os.RemoteCallback;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.ServiceSpecificException;
@@ -106,6 +104,7 @@
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.internal.util.Preconditions;
+import com.android.server.FgThread;
 import com.android.server.LocalServices;
 import com.android.server.SystemConfig;
 import com.android.server.pm.PackageManagerShellCommandDataLoader.Metadata;
@@ -2324,7 +2323,7 @@
             getErrPrintWriter().println("Error: no enforcement specified");
             return 1;
         }
-        mPermissionManager.setPermissionEnforced(permission, Boolean.parseBoolean(enforcedRaw));
+        // Permissions are always enforced now.
         return 0;
     }
 
@@ -2971,12 +2970,10 @@
         final int translatedUserId =
                 translateUserId(userId, UserHandle.USER_NULL, "runSetHomeActivity");
         final CompletableFuture<Boolean> future = new CompletableFuture<>();
-        final RemoteCallback callback = new RemoteCallback(res -> future.complete(res != null));
         try {
-            IRoleManager roleManager = android.app.role.IRoleManager.Stub.asInterface(
-                    ServiceManager.getServiceOrThrow(Context.ROLE_SERVICE));
-            roleManager.addRoleHolderAsUser(RoleManager.ROLE_HOME, pkgName,
-                    0, translatedUserId, callback);
+            RoleManager roleManager = mContext.getSystemService(RoleManager.class);
+            roleManager.addRoleHolderAsUser(RoleManager.ROLE_HOME, pkgName, 0,
+                    UserHandle.of(translatedUserId), FgThread.getExecutor(), future::complete);
             boolean success = future.get();
             if (success) {
                 pw.println("Success");
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index cb4c6a9..2d5034e 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -362,8 +362,6 @@
         }
     }
 
-    Boolean mReadExternalStorageEnforced;
-
     /** Device identity for the purpose of package verification. */
     private VerifierDeviceIdentity mVerifierDeviceIdentity;
 
@@ -2342,13 +2340,6 @@
                 serializer.endTag(null, "verifier");
             }
 
-            if (mReadExternalStorageEnforced != null) {
-                serializer.startTag(null, TAG_READ_EXTERNAL_STORAGE);
-                serializer.attribute(
-                        null, ATTR_ENFORCEMENT, mReadExternalStorageEnforced ? "1" : "0");
-                serializer.endTag(null, TAG_READ_EXTERNAL_STORAGE);
-            }
-
             serializer.startTag(null, "permission-trees");
             mPermissions.writePermissionTrees(serializer);
             serializer.endTag(null, "permission-trees");
@@ -2959,9 +2950,7 @@
                                 + e.getMessage());
                     }
                 } else if (TAG_READ_EXTERNAL_STORAGE.equals(tagName)) {
-                    final String enforcement = parser.getAttributeValue(null, ATTR_ENFORCEMENT);
-                    mReadExternalStorageEnforced =
-                            "1".equals(enforcement) ? Boolean.TRUE : Boolean.FALSE;
+                    // No longer used.
                 } else if (tagName.equals("keyset-settings")) {
                     mKeySetManagerService.readKeySetsLPw(parser, mKeySetRefs);
                 } else if (TAG_VERSION.equals(tagName)) {
@@ -4900,8 +4889,7 @@
             DumpState dumpState) {
         LegacyPermissionSettings.dumpPermissions(pw, packageName, permissionNames,
                 mPermissionDataProvider.getLegacyPermissions(),
-                mPermissionDataProvider.getAllAppOpPermissionPackages(),
-                (mReadExternalStorageEnforced == Boolean.TRUE), dumpState);
+                mPermissionDataProvider.getAllAppOpPermissionPackages(), true, dumpState);
     }
 
     void dumpSharedUsersLPr(PrintWriter pw, String packageName, ArraySet<String> permissionNames,
diff --git a/services/core/java/com/android/server/pm/UserManagerInternal.java b/services/core/java/com/android/server/pm/UserManagerInternal.java
index 47d0a3d5..c182d68 100644
--- a/services/core/java/com/android/server/pm/UserManagerInternal.java
+++ b/services/core/java/com/android/server/pm/UserManagerInternal.java
@@ -57,6 +57,20 @@
     }
 
     /**
+     * Listener for user lifecycle events.
+     *
+     * <p><b>NOTE: </b>implementations MUST not block the current thread.
+     */
+    public interface UserLifecycleListener {
+
+        /** Called when a new user is created. */
+        default void onUserCreated(UserInfo user) {}
+
+        /** Called when an existing user is removed. */
+        default void onUserRemoved(UserInfo user) {}
+    }
+
+    /**
      * Called by {@link com.android.server.devicepolicy.DevicePolicyManagerService} to set
      * restrictions enforced by the user.
      *
@@ -97,6 +111,12 @@
     /** Remove a {@link UserRestrictionsListener}. */
     public abstract void removeUserRestrictionsListener(UserRestrictionsListener listener);
 
+    /** Adds a {@link UserLifecycleListener}. */
+    public abstract void addUserLifecycleListener(UserLifecycleListener listener);
+
+    /** Removes a {@link UserLifecycleListener}. */
+    public abstract void removeUserLifecycleListener(UserLifecycleListener listener);
+
     /**
      * Called by {@link com.android.server.devicepolicy.DevicePolicyManagerService} to update
      * whether the device is managed by device owner.
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 62ac570..ccbf73c 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -110,6 +110,7 @@
 import com.android.server.LockGuard;
 import com.android.server.SystemService;
 import com.android.server.am.UserState;
+import com.android.server.pm.UserManagerInternal.UserLifecycleListener;
 import com.android.server.pm.UserManagerInternal.UserRestrictionsListener;
 import com.android.server.storage.DeviceStorageMonitorInternal;
 import com.android.server.utils.TimingsTraceAndSlog;
@@ -438,6 +439,9 @@
     private final ArrayList<UserRestrictionsListener> mUserRestrictionsListeners =
             new ArrayList<>();
 
+    @GuardedBy("mUserRemovedListeners")
+    private final ArrayList<UserLifecycleListener> mUserLifecycleListeners = new ArrayList<>();
+
     private final LockPatternUtils mLockPatternUtils;
 
     private final String ACTION_DISABLE_QUIET_MODE_AFTER_UNLOCK =
@@ -3633,6 +3637,14 @@
     }
 
     private void dispatchUserAdded(@NonNull UserInfo userInfo) {
+        // Notify internal listeners first...
+        synchronized (mUserLifecycleListeners) {
+            for (int i = 0; i < mUserLifecycleListeners.size(); i++) {
+                mUserLifecycleListeners.get(i).onUserCreated(userInfo);
+            }
+        }
+
+        //...then external ones
         Intent addedIntent = new Intent(Intent.ACTION_USER_ADDED);
         addedIntent.putExtra(Intent.EXTRA_USER_HANDLE, userInfo.id);
         // Also, add the UserHandle for mainline modules which can't use the @hide
@@ -4018,13 +4030,19 @@
             user = getUserInfoLU(userId);
         }
         if (user != null && user.preCreated) {
-            Slog.i(LOG_TAG, "Removing a precreated user with user id: " + userId);
+            Slog.i(LOG_TAG, "Removing a pre-created user with user id: " + userId);
             // Don't want to fire ACTION_USER_REMOVED, so cleanup the state and exit early.
             LocalServices.getService(ActivityTaskManagerInternal.class).onUserStopped(userId);
             removeUserState(userId);
             return;
         }
 
+        synchronized (mUserLifecycleListeners) {
+            for (int i = 0; i < mUserLifecycleListeners.size(); i++) {
+                mUserLifecycleListeners.get(i).onUserRemoved(user);
+            }
+        }
+
         // Let other services shutdown any activity and clean up their state before completely
         // wiping the user's system directory and removing from the user list
         final long ident = Binder.clearCallingIdentity();
@@ -4960,6 +4978,15 @@
             pw.println("  System user allocations: " + mUser0Allocations.get());
         }
 
+        pw.println();
+        pw.println("Number of listeners for");
+        synchronized (mUserRestrictionsListeners) {
+            pw.println("  restrictions: " + mUserRestrictionsListeners.size());
+        }
+        synchronized (mUserLifecycleListeners) {
+            pw.println("  user lifecycle events: " + mUserLifecycleListeners.size());
+        }
+
         // Dump UserTypes
         pw.println();
         pw.println("User types version: " + mUserTypeVersion);
@@ -5078,6 +5105,20 @@
         }
 
         @Override
+        public void addUserLifecycleListener(UserLifecycleListener listener) {
+            synchronized (mUserLifecycleListeners) {
+                mUserLifecycleListeners.add(listener);
+            }
+        }
+
+        @Override
+        public void removeUserLifecycleListener(UserLifecycleListener listener) {
+            synchronized (mUserLifecycleListeners) {
+                mUserLifecycleListeners.remove(listener);
+            }
+        }
+
+        @Override
         public void setDeviceManaged(boolean isManaged) {
             synchronized (mUsersLock) {
                 mIsDeviceManaged = isManaged;
diff --git a/services/core/java/com/android/server/pm/UserTypeFactory.java b/services/core/java/com/android/server/pm/UserTypeFactory.java
index 1d3aecd..1ffbf60 100644
--- a/services/core/java/com/android/server/pm/UserTypeFactory.java
+++ b/services/core/java/com/android/server/pm/UserTypeFactory.java
@@ -30,6 +30,7 @@
 import static android.os.UserManager.USER_TYPE_FULL_SECONDARY;
 import static android.os.UserManager.USER_TYPE_FULL_SYSTEM;
 import static android.os.UserManager.USER_TYPE_PROFILE_MANAGED;
+import static android.os.UserManager.USER_TYPE_PROFILE_TEST;
 import static android.os.UserManager.USER_TYPE_SYSTEM_HEADLESS;
 
 import static com.android.server.pm.UserTypeDetails.UNLIMITED_NUMBER_OF_USERS;
@@ -37,6 +38,7 @@
 import android.content.pm.UserInfo;
 import android.content.res.Resources;
 import android.content.res.XmlResourceParser;
+import android.os.Build;
 import android.os.Bundle;
 import android.os.UserManager;
 import android.util.ArrayMap;
@@ -98,6 +100,9 @@
         builders.put(USER_TYPE_FULL_DEMO, getDefaultTypeFullDemo());
         builders.put(USER_TYPE_FULL_RESTRICTED, getDefaultTypeFullRestricted());
         builders.put(USER_TYPE_SYSTEM_HEADLESS, getDefaultTypeSystemHeadless());
+        if (Build.IS_DEBUGGABLE) {
+            builders.put(USER_TYPE_PROFILE_TEST, getDefaultTypeProfileTest());
+        }
 
         return builders;
     }
@@ -132,6 +137,37 @@
     }
 
     /**
+     * Returns the Builder for the default {@link UserManager#USER_TYPE_PROFILE_TEST}
+     * configuration (for userdebug builds). For now it just uses managed profile badges.
+     */
+    private static UserTypeDetails.Builder getDefaultTypeProfileTest() {
+        final Bundle restrictions = new Bundle();
+        restrictions.putBoolean(UserManager.DISALLOW_FUN, true);
+
+        return new UserTypeDetails.Builder()
+                .setName(USER_TYPE_PROFILE_TEST)
+                .setBaseType(FLAG_PROFILE)
+                .setMaxAllowedPerParent(2)
+                .setLabel(0)
+                .setIconBadge(com.android.internal.R.drawable.ic_corp_icon_badge_case)
+                .setBadgePlain(com.android.internal.R.drawable.ic_corp_badge_case)
+                .setBadgeNoBackground(com.android.internal.R.drawable.ic_corp_badge_no_background)
+                .setBadgeLabels(
+                        com.android.internal.R.string.managed_profile_label_badge,
+                        com.android.internal.R.string.managed_profile_label_badge_2,
+                        com.android.internal.R.string.managed_profile_label_badge_3)
+                .setBadgeColors(
+                        com.android.internal.R.color.profile_badge_1,
+                        com.android.internal.R.color.profile_badge_2,
+                        com.android.internal.R.color.profile_badge_3)
+                .setDarkThemeBadgeColors(
+                        com.android.internal.R.color.profile_badge_1_dark,
+                        com.android.internal.R.color.profile_badge_2_dark,
+                        com.android.internal.R.color.profile_badge_3_dark)
+                .setDefaultRestrictions(restrictions);
+    }
+
+    /**
      * Returns the Builder for the default {@link UserManager#USER_TYPE_FULL_SECONDARY}
      * configuration.
      */
diff --git a/services/core/java/com/android/server/pm/dex/ArtManagerService.java b/services/core/java/com/android/server/pm/dex/ArtManagerService.java
index fadd0c8..139654e 100644
--- a/services/core/java/com/android/server/pm/dex/ArtManagerService.java
+++ b/services/core/java/com/android/server/pm/dex/ArtManagerService.java
@@ -579,6 +579,8 @@
     // Constants used for logging compilation reason to TRON.
     // DO NOT CHANGE existing values.
     //
+    // In the below constants, the abbreviation DM stands for "DEX metadata".
+    //
     // NOTE: '-1' value is reserved for the case where we cannot produce a valid
     // PackageOptimizationInfo because the ArtManagerInternal is not ready to be used by the
     // ActivityMetricsLoggers.
@@ -591,7 +593,18 @@
     private static final int TRON_COMPILATION_REASON_AB_OTA = 6;
     private static final int TRON_COMPILATION_REASON_INACTIVE = 7;
     private static final int TRON_COMPILATION_REASON_SHARED = 8;
-    private static final int TRON_COMPILATION_REASON_INSTALL_WITH_DEX_METADATA = 9;
+    private static final int TRON_COMPILATION_REASON_INSTALL_WITH_DM = 9;
+    private static final int TRON_COMPILATION_REASON_INSTALL_FAST = 10;
+    private static final int TRON_COMPILATION_REASON_INSTALL_BULK = 11;
+    private static final int TRON_COMPILATION_REASON_INSTALL_BULK_SECONDARY = 12;
+    private static final int TRON_COMPILATION_REASON_INSTALL_BULK_DOWNGRADED = 13;
+    private static final int TRON_COMPILATION_REASON_INSTALL_BULK_SECONDARY_DOWNGRADED = 14;
+    private static final int TRON_COMPILATION_REASON_INSTALL_FAST_WITH_DM = 15;
+    private static final int TRON_COMPILATION_REASON_INSTALL_BULK_WITH_DM = 16;
+    private static final int TRON_COMPILATION_REASON_INSTALL_BULK_SECONDARY_WITH_DM = 17;
+    private static final int TRON_COMPILATION_REASON_INSTALL_BULK_DOWNGRADED_WITH_DM = 18;
+    private static final int
+            TRON_COMPILATION_REASON_INSTALL_BULK_SECONDARY_DOWNGRADED_WITH_DM = 19;
 
     // The annotation to add as a suffix to the compilation reason when dexopt was
     // performed with dex metadata.
@@ -611,10 +624,30 @@
             case "ab-ota" : return TRON_COMPILATION_REASON_AB_OTA;
             case "inactive" : return TRON_COMPILATION_REASON_INACTIVE;
             case "shared" : return TRON_COMPILATION_REASON_SHARED;
-            // This is a special marker for dex metadata installation that does not
+            case "install-fast" :
+                return TRON_COMPILATION_REASON_INSTALL_FAST;
+            case "install-bulk" :
+                return TRON_COMPILATION_REASON_INSTALL_BULK;
+            case "install-bulk-secondary" :
+                return TRON_COMPILATION_REASON_INSTALL_BULK_SECONDARY;
+            case "install-bulk-downgraded" :
+                return TRON_COMPILATION_REASON_INSTALL_BULK_DOWNGRADED;
+            case "install-bulk-secondary-downgraded" :
+                return TRON_COMPILATION_REASON_INSTALL_BULK_SECONDARY_DOWNGRADED;
+            // These are special markers for dex metadata installation that do not
             // have an equivalent as a system property.
             case "install" + DEXOPT_REASON_WITH_DEX_METADATA_ANNOTATION :
-                return TRON_COMPILATION_REASON_INSTALL_WITH_DEX_METADATA;
+                return TRON_COMPILATION_REASON_INSTALL_WITH_DM;
+            case "install-fast" + DEXOPT_REASON_WITH_DEX_METADATA_ANNOTATION :
+                return TRON_COMPILATION_REASON_INSTALL_FAST_WITH_DM;
+            case "install-bulk" + DEXOPT_REASON_WITH_DEX_METADATA_ANNOTATION :
+                return TRON_COMPILATION_REASON_INSTALL_BULK_WITH_DM;
+            case "install-bulk-secondary" + DEXOPT_REASON_WITH_DEX_METADATA_ANNOTATION :
+                return TRON_COMPILATION_REASON_INSTALL_BULK_SECONDARY_WITH_DM;
+            case "install-bulk-downgraded" + DEXOPT_REASON_WITH_DEX_METADATA_ANNOTATION :
+                return TRON_COMPILATION_REASON_INSTALL_BULK_DOWNGRADED_WITH_DM;
+            case "install-bulk-secondary-downgraded" + DEXOPT_REASON_WITH_DEX_METADATA_ANNOTATION :
+                return TRON_COMPILATION_REASON_INSTALL_BULK_SECONDARY_DOWNGRADED_WITH_DM;
             default: return TRON_COMPILATION_REASON_UNKNOWN;
         }
     }
diff --git a/services/core/java/com/android/server/pm/dex/DexManager.java b/services/core/java/com/android/server/pm/dex/DexManager.java
index 3074250..cc6d80a 100644
--- a/services/core/java/com/android/server/pm/dex/DexManager.java
+++ b/services/core/java/com/android/server/pm/dex/DexManager.java
@@ -27,8 +27,11 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.IPackageManager;
 import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
 import android.content.pm.PackagePartitions;
+import android.os.BatteryManager;
 import android.os.FileUtils;
+import android.os.PowerManager;
 import android.os.RemoteException;
 import android.os.SystemProperties;
 import android.os.UserHandle;
@@ -107,6 +110,13 @@
     @GuardedBy("mInstallLock")
     private final Installer mInstaller;
 
+    private BatteryManager mBatteryManager = null;
+    private PowerManager mPowerManager = null;
+
+    // An integer percentage value used to determine when the device is considered to be on low
+    // power for compilation purposes.
+    private final int mCriticalBatteryLevel;
+
     // Possible outcomes of a dex search.
     private static int DEX_SEARCH_NOT_FOUND = 0;  // dex file not found
     private static int DEX_SEARCH_FOUND_PRIMARY = 1;  // dex file is the primary/base apk
@@ -123,6 +133,23 @@
         mInstaller = installer;
         mInstallLock = installLock;
         mDynamicCodeLogger = new DynamicCodeLogger(pms, installer);
+
+        // This is currently checked to handle tests that pass in a null context.
+        // TODO(b/174783329): Modify the tests to pass in a mocked Context, PowerManager,
+        //      and BatteryManager.
+        if (mContext != null) {
+            mPowerManager = mContext.getSystemService(PowerManager.class);
+
+            if (mPowerManager == null) {
+                Slog.wtf(TAG, "Power Manager is unavailable at time of Dex Manager start");
+            }
+
+            mCriticalBatteryLevel = mContext.getResources().getInteger(
+                com.android.internal.R.integer.config_criticalBatteryWarningLevel);
+        } else {
+            // This value will never be used as the Battery Manager null check will fail first.
+            mCriticalBatteryLevel = 0;
+        }
     }
 
     public DynamicCodeLogger getDynamicCodeLogger() {
@@ -905,6 +932,74 @@
         }
     }
 
+    /**
+     * Translates install scenarios into compilation reasons.  This process can be influenced
+     * by the state of the device.
+     */
+    public int getCompilationReasonForInstallScenario(int installScenario) {
+        // Compute the compilation reason from the installation scenario.
+
+        boolean resourcesAreCritical = areBatteryThermalOrMemoryCritical();
+        switch (installScenario) {
+            case PackageManager.INSTALL_SCENARIO_DEFAULT: {
+                return PackageManagerService.REASON_INSTALL;
+            }
+            case PackageManager.INSTALL_SCENARIO_FAST: {
+                return PackageManagerService.REASON_INSTALL_FAST;
+            }
+            case PackageManager.INSTALL_SCENARIO_BULK: {
+                if (resourcesAreCritical) {
+                    return PackageManagerService.REASON_INSTALL_BULK_DOWNGRADED;
+                } else {
+                    return PackageManagerService.REASON_INSTALL_BULK;
+                }
+            }
+            case PackageManager.INSTALL_SCENARIO_BULK_SECONDARY: {
+                if (resourcesAreCritical) {
+                    return PackageManagerService.REASON_INSTALL_BULK_SECONDARY_DOWNGRADED;
+                } else {
+                    return PackageManagerService.REASON_INSTALL_BULK_SECONDARY;
+                }
+            }
+            default: {
+                throw new IllegalArgumentException("Invalid installation scenario");
+            }
+        }
+    }
+
+    /**
+     * Fetches the battery manager object and caches it if it hasn't been fetched already.
+     */
+    private BatteryManager getBatteryManager() {
+        if (mBatteryManager == null) {
+            mBatteryManager = mContext.getSystemService(BatteryManager.class);
+        }
+
+        return mBatteryManager;
+    }
+
+    /**
+     * Returns true if the battery level, device temperature, or memory usage are considered to be
+     * in a critical state.
+     */
+    private boolean areBatteryThermalOrMemoryCritical() {
+        BatteryManager batteryManager = getBatteryManager();
+        boolean isBtmCritical = (batteryManager != null
+                && batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_STATUS)
+                    == BatteryManager.BATTERY_STATUS_DISCHARGING
+                && batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY)
+                    <= mCriticalBatteryLevel)
+                || (mPowerManager != null
+                    && mPowerManager.getCurrentThermalStatus()
+                        >= PowerManager.THERMAL_STATUS_SEVERE);
+
+        if (DEBUG) {
+            Log.d(TAG, "Battery, thermal, or memory are critical: " + isBtmCritical);
+        }
+
+        return isBtmCritical;
+    }
+
     public static class RegisterDexModuleResult {
         public RegisterDexModuleResult() {
             this(false, null);
diff --git a/services/core/java/com/android/server/pm/dex/DexoptOptions.java b/services/core/java/com/android/server/pm/dex/DexoptOptions.java
index 68f3886..ea23316 100644
--- a/services/core/java/com/android/server/pm/dex/DexoptOptions.java
+++ b/services/core/java/com/android/server/pm/dex/DexoptOptions.java
@@ -65,6 +65,12 @@
     // or device setup and should be scheduled appropriately.
     public static final int DEXOPT_FOR_RESTORE = 1 << 11; // TODO(b/135202722): remove
 
+    /**
+     * A value indicating that dexopt shouldn't be run.  This string is only used when loading
+     * filters from the `pm.dexopt.install*` properties and is not propagated to dex2oat.
+     */
+    public static final String COMPILER_FILTER_NOOP = "skip";
+
     // The name of package to optimize.
     private final String mPackageName;
 
@@ -176,6 +182,10 @@
         return mCompilationReason;
     }
 
+    public boolean isCompilationEnabled() {
+        return !mCompilerFilter.equals(COMPILER_FILTER_NOOP);
+    }
+
     /**
      * Creates a new set of DexoptOptions which are the same with the exception of the compiler
      * filter (set to the given value).
diff --git a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
index 1656472..44a2187 100644
--- a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
@@ -41,8 +41,9 @@
 import android.os.Build;
 import android.os.Environment;
 import android.os.Handler;
-import android.os.Looper;
+import android.os.HandlerThread;
 import android.os.Message;
+import android.os.Process;
 import android.os.UserHandle;
 import android.os.storage.StorageManager;
 import android.permission.PermissionManager;
@@ -67,8 +68,9 @@
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.XmlUtils;
 import com.android.server.LocalServices;
-import com.android.server.pm.permission.PermissionManagerServiceInternal.PackagesProvider;
-import com.android.server.pm.permission.PermissionManagerServiceInternal.SyncAdapterPackagesProvider;
+import com.android.server.ServiceThread;
+import com.android.server.pm.permission.LegacyPermissionManagerInternal.PackagesProvider;
+import com.android.server.pm.permission.LegacyPermissionManagerInternal.SyncAdapterPackagesProvider;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
@@ -96,7 +98,7 @@
  * to have an interface defined in the package manager but have the impl next to other
  * policy stuff like PhoneWindowManager
  */
-public final class DefaultPermissionGrantPolicy {
+final class DefaultPermissionGrantPolicy {
     private static final String TAG = "DefaultPermGrantPolicy"; // must be <= 23 chars
     private static final boolean DEBUG = false;
 
@@ -291,9 +293,12 @@
         }
     };
 
-    DefaultPermissionGrantPolicy(Context context, Looper looper) {
+    DefaultPermissionGrantPolicy(@NonNull Context context) {
         mContext = context;
-        mHandler = new Handler(looper) {
+        HandlerThread handlerThread = new ServiceThread(TAG,
+                Process.THREAD_PRIORITY_BACKGROUND, true /*allowIo*/);
+        handlerThread.start();
+        mHandler = new Handler(handlerThread.getLooper()) {
             @Override
             public void handleMessage(Message msg) {
                 if (msg.what == MSG_READ_DEFAULT_PERMISSION_EXCEPTIONS) {
@@ -998,12 +1003,6 @@
         }
     }
 
-    public void grantDefaultPermissionsToDefaultBrowser(String packageName, int userId) {
-        Log.i(TAG, "Granting permissions to default browser for user:" + userId);
-        grantPermissionsToSystemPackage(NO_PM_CACHE, packageName, userId,
-                FOREGROUND_LOCATION_PERMISSIONS);
-    }
-
     private String getDefaultSystemHandlerActivityPackage(PackageManagerWrapper pm,
             String intentAction, int userId) {
         return getDefaultSystemHandlerActivityPackage(pm, new Intent(intentAction), userId);
diff --git a/services/core/java/com/android/server/pm/permission/LegacyPermissionManagerInternal.java b/services/core/java/com/android/server/pm/permission/LegacyPermissionManagerInternal.java
new file mode 100644
index 0000000..a098484
--- /dev/null
+++ b/services/core/java/com/android/server/pm/permission/LegacyPermissionManagerInternal.java
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.pm.permission;
+
+import android.annotation.NonNull;
+import android.annotation.UserIdInt;
+
+/**
+ * The internal interface for {@link LegacyPermissionManagerService}.
+ */
+public interface LegacyPermissionManagerInternal {
+    /**
+     * Sets the dialer application packages provider.
+     * @param provider The provider.
+     */
+    void setDialerAppPackagesProvider(PackagesProvider provider);
+
+    /**
+     * Set the location extra packages provider.
+     * @param provider The packages provider.
+     */
+    void setLocationExtraPackagesProvider(PackagesProvider provider);
+
+    /**
+     * Sets the location provider packages provider.
+     * @param provider The packages provider.
+     */
+    void setLocationPackagesProvider(PackagesProvider provider);
+
+    /**
+     * Sets the SIM call manager packages provider.
+     * @param provider The provider.
+     */
+    void setSimCallManagerPackagesProvider(PackagesProvider provider);
+
+    /**
+     * Sets the SMS application packages provider.
+     * @param provider The provider.
+     */
+    void setSmsAppPackagesProvider(PackagesProvider provider);
+
+    /**
+     * Sets the sync adapter packages provider.
+     * @param provider The provider.
+     */
+    void setSyncAdapterPackagesProvider(SyncAdapterPackagesProvider provider);
+
+    /**
+     * Sets the Use Open Wifi packages provider.
+     * @param provider The packages provider.
+     */
+    void setUseOpenWifiAppPackagesProvider(PackagesProvider provider);
+
+    /**
+     * Sets the voice interaction packages provider.
+     * @param provider The packages provider.
+     */
+    void setVoiceInteractionPackagesProvider(PackagesProvider provider);
+
+    /**
+     * Requests granting of the default permissions to the current default Use Open Wifi app.
+     * @param packageName The default use open wifi package name.
+     * @param userId The user for which to grant the permissions.
+     */
+    void grantDefaultPermissionsToDefaultSimCallManager(@NonNull String packageName,
+            @UserIdInt int userId);
+
+    /**
+     * Requests granting of the default permissions to the current default Use Open Wifi app.
+     * @param packageName The default use open wifi package name.
+     * @param userId The user for which to grant the permissions.
+     */
+    void grantDefaultPermissionsToDefaultUseOpenWifiApp(@NonNull String packageName,
+            @UserIdInt int userId);
+
+    /**
+     * Grant the default permissions for a user.
+     *
+     * @param userId the user ID
+     */
+    void grantDefaultPermissions(@UserIdInt int userId);
+
+    /**
+     * Schedule reading the default permission exceptions file.
+     */
+    void scheduleReadDefaultPermissionExceptions();
+
+    // TODO(zhanghai): The following methods should be moved to a new AIDL to support
+    //  the legacy PermissionManager directly in a later CL.
+
+    /**
+     * Grant default permissions to currently active LUI app
+     * @param packageName The package name for the LUI app
+     * @param userId The user ID
+     */
+    void grantDefaultPermissionsToActiveLuiApp(String packageName, int userId);
+
+    /**
+     * Revoke default permissions to currently active LUI app
+     * @param packageNames The package names for the LUI apps
+     * @param userId The user ID
+     */
+    void revokeDefaultPermissionsFromLuiApps(String[] packageNames, int userId);
+
+    /**
+     * Grant default permissions to currently active Ims services
+     * @param packageNames The package names for the Ims services
+     * @param userId The user ID
+     */
+    void grantDefaultPermissionsToEnabledImsServices(String[] packageNames, int userId);
+
+    /**
+     * Grant default permissions to currently enabled telephony data services
+     * @param packageNames The package name for the services
+     * @param userId The user ID
+     */
+    void grantDefaultPermissionsToEnabledTelephonyDataServices(String[] packageNames, int userId);
+
+    /**
+     * Revoke default permissions to currently active telephony data services
+     * @param packageNames The package name for the services
+     * @param userId The IDhandle
+     */
+    void revokeDefaultPermissionsFromDisabledTelephonyDataServices(String[] packageNames,
+            int userId);
+
+    /**
+     * Grant default permissions to currently enabled carrier apps
+     * @param packageNames Package names of the apps to be granted permissions
+     * @param userId The user ID
+     */
+    void grantDefaultPermissionsToEnabledCarrierApps(String[] packageNames, int userId);
+
+    /**
+     * Provider for package names.
+     */
+    interface PackagesProvider {
+        /**
+         * Gets the packages for a given user.
+         * @param userId The user id.
+         * @return The package names.
+         */
+        String[] getPackages(int userId);
+    }
+
+    /**
+     * Provider for package names.
+     */
+    interface SyncAdapterPackagesProvider {
+        /**
+         * Gets the sync adapter packages for given authority and user.
+         * @param authority The authority.
+         * @param userId The user id.
+         * @return The package names.
+         */
+        String[] getPackages(String authority, int userId);
+    }
+}
diff --git a/services/core/java/com/android/server/pm/permission/LegacyPermissionManagerService.java b/services/core/java/com/android/server/pm/permission/LegacyPermissionManagerService.java
new file mode 100644
index 0000000..0c0a8df
--- /dev/null
+++ b/services/core/java/com/android/server/pm/permission/LegacyPermissionManagerService.java
@@ -0,0 +1,181 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.pm.permission;
+
+import android.annotation.NonNull;
+import android.content.Context;
+import android.os.Binder;
+
+import com.android.server.LocalServices;
+import com.android.server.pm.PackageManagerServiceUtils;
+
+/**
+ * Legacy permission manager service.
+ */
+public class LegacyPermissionManagerService {
+    @NonNull
+    private final DefaultPermissionGrantPolicy mDefaultPermissionGrantPolicy;
+
+    /**
+     * Get or create an instance of this class for use by other components.
+     * <p>
+     * This method is not thread-safe.
+     *
+     * @param context the {@link Context}
+     * @return the internal instance
+     */
+    @NonNull
+    public static LegacyPermissionManagerInternal create(@NonNull Context context) {
+        LegacyPermissionManagerInternal legacyPermissionManagerInternal = LocalServices.getService(
+                LegacyPermissionManagerInternal.class);
+        if (legacyPermissionManagerInternal == null) {
+            new LegacyPermissionManagerService(context);
+            legacyPermissionManagerInternal = LocalServices.getService(
+                    LegacyPermissionManagerInternal.class);
+        }
+        return legacyPermissionManagerInternal;
+    }
+
+    private LegacyPermissionManagerService(@NonNull Context context) {
+        mDefaultPermissionGrantPolicy = new DefaultPermissionGrantPolicy(context);
+        LocalServices.addService(LegacyPermissionManagerInternal.class, new Internal());
+    }
+
+    private class Internal implements LegacyPermissionManagerInternal {
+        @Override
+        public void setDialerAppPackagesProvider(PackagesProvider provider) {
+            mDefaultPermissionGrantPolicy.setDialerAppPackagesProvider(provider);
+        }
+
+        @Override
+        public void setLocationExtraPackagesProvider(PackagesProvider provider) {
+            mDefaultPermissionGrantPolicy.setLocationExtraPackagesProvider(provider);
+        }
+
+        @Override
+        public void setLocationPackagesProvider(PackagesProvider provider) {
+            mDefaultPermissionGrantPolicy.setLocationPackagesProvider(provider);
+        }
+
+        @Override
+        public void setSimCallManagerPackagesProvider(PackagesProvider provider) {
+            mDefaultPermissionGrantPolicy.setSimCallManagerPackagesProvider(provider);
+        }
+
+        @Override
+        public void setSmsAppPackagesProvider(PackagesProvider provider) {
+            mDefaultPermissionGrantPolicy.setSmsAppPackagesProvider(provider);
+        }
+
+        @Override
+        public void setSyncAdapterPackagesProvider(SyncAdapterPackagesProvider provider) {
+            mDefaultPermissionGrantPolicy.setSyncAdapterPackagesProvider(provider);
+        }
+
+        @Override
+        public void setUseOpenWifiAppPackagesProvider(PackagesProvider provider) {
+            mDefaultPermissionGrantPolicy.setUseOpenWifiAppPackagesProvider(provider);
+        }
+
+        @Override
+        public void setVoiceInteractionPackagesProvider(PackagesProvider provider) {
+            mDefaultPermissionGrantPolicy.setVoiceInteractionPackagesProvider(provider);
+        }
+
+        @Override
+        public void grantDefaultPermissionsToDefaultSimCallManager(String packageName, int userId) {
+            mDefaultPermissionGrantPolicy.grantDefaultPermissionsToDefaultSimCallManager(
+                    packageName, userId);
+        }
+
+        @Override
+        public void grantDefaultPermissionsToDefaultUseOpenWifiApp(String packageName, int userId) {
+            mDefaultPermissionGrantPolicy.grantDefaultPermissionsToDefaultUseOpenWifiApp(
+                    packageName, userId);
+        }
+
+        @Override
+        public void grantDefaultPermissions(int userId) {
+            mDefaultPermissionGrantPolicy.grantDefaultPermissions(userId);
+        }
+
+        @Override
+        public void scheduleReadDefaultPermissionExceptions() {
+            mDefaultPermissionGrantPolicy.scheduleReadDefaultPermissionExceptions();
+        }
+
+        // TODO(zhanghai): The following methods should be moved to a new AIDL to support
+        //  the legacy PermissionManager directly in a later CL.
+
+        @Override
+        public void grantDefaultPermissionsToActiveLuiApp(String packageName, int userId) {
+            final int callingUid = Binder.getCallingUid();
+            PackageManagerServiceUtils.enforceSystemOrPhoneCaller(
+                    "grantDefaultPermissionsToActiveLuiApp", callingUid);
+            Binder.withCleanCallingIdentity(() -> mDefaultPermissionGrantPolicy
+                    .grantDefaultPermissionsToActiveLuiApp(packageName, userId));
+        }
+
+        @Override
+        public void revokeDefaultPermissionsFromLuiApps(String[] packageNames, int userId) {
+            final int callingUid = Binder.getCallingUid();
+            PackageManagerServiceUtils.enforceSystemOrPhoneCaller(
+                    "revokeDefaultPermissionsFromLuiApps", callingUid);
+            Binder.withCleanCallingIdentity(() -> mDefaultPermissionGrantPolicy
+                    .revokeDefaultPermissionsFromLuiApps(packageNames, userId));
+        }
+
+        @Override
+        public void grantDefaultPermissionsToEnabledImsServices(String[] packageNames, int userId) {
+            final int callingUid = Binder.getCallingUid();
+            PackageManagerServiceUtils.enforceSystemOrPhoneCaller(
+                    "grantDefaultPermissionsToEnabledImsServices", callingUid);
+            Binder.withCleanCallingIdentity(() -> mDefaultPermissionGrantPolicy
+                    .grantDefaultPermissionsToEnabledImsServices(packageNames, userId));
+        }
+
+        @Override
+        public void grantDefaultPermissionsToEnabledTelephonyDataServices(
+                String[] packageNames, int userId) {
+            final int callingUid = Binder.getCallingUid();
+            PackageManagerServiceUtils.enforceSystemOrPhoneCaller(
+                    "grantDefaultPermissionsToEnabledTelephonyDataServices", callingUid);
+            Binder.withCleanCallingIdentity(() -> mDefaultPermissionGrantPolicy
+                    .grantDefaultPermissionsToEnabledTelephonyDataServices(packageNames, userId));
+        }
+
+        @Override
+        public void revokeDefaultPermissionsFromDisabledTelephonyDataServices(
+                String[] packageNames, int userId) {
+            final int callingUid = Binder.getCallingUid();
+            PackageManagerServiceUtils.enforceSystemOrPhoneCaller(
+                    "revokeDefaultPermissionsFromDisabledTelephonyDataServices", callingUid);
+            Binder.withCleanCallingIdentity(() -> mDefaultPermissionGrantPolicy
+                    .revokeDefaultPermissionsFromDisabledTelephonyDataServices(packageNames,
+                            userId));
+        }
+
+        @Override
+        public void grantDefaultPermissionsToEnabledCarrierApps(String[] packageNames, int userId) {
+            final int callingUid = Binder.getCallingUid();
+            PackageManagerServiceUtils.enforceSystemOrPhoneCaller(
+                    "grantPermissionsToEnabledCarrierApps", callingUid);
+            Binder.withCleanCallingIdentity(() -> mDefaultPermissionGrantPolicy
+                    .grantDefaultPermissionsToEnabledCarrierApps(packageNames, userId));
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/pm/permission/OWNERS b/services/core/java/com/android/server/pm/permission/OWNERS
index 0e88862..6e67830 100644
--- a/services/core/java/com/android/server/pm/permission/OWNERS
+++ b/services/core/java/com/android/server/pm/permission/OWNERS
@@ -1,7 +1,7 @@
 [email protected]
 [email protected]
-per-file DefaultPermissionGrantPolicy.java = [email protected]
-per-file DefaultPermissionGrantPolicy.java = [email protected]
+per-file DefaultPermissionGrantPolicy.java = [email protected]
+per-file DefaultPermissionGrantPolicy.java = [email protected]
 per-file DefaultPermissionGrantPolicy.java = [email protected]
 per-file DefaultPermissionGrantPolicy.java = [email protected]
 per-file DefaultPermissionGrantPolicy.java = [email protected]
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 7ed887d..389010a 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -114,7 +114,6 @@
 import android.permission.PermissionControllerManager;
 import android.permission.PermissionManager;
 import android.permission.PermissionManagerInternal;
-import android.permission.PermissionManagerInternal.OnRuntimePermissionStateChangedListener;
 import android.text.TextUtils;
 import android.util.ArrayMap;
 import android.util.ArraySet;
@@ -145,12 +144,12 @@
 import com.android.server.SystemConfig;
 import com.android.server.Watchdog;
 import com.android.server.pm.ApexManager;
-import com.android.server.pm.PackageManagerServiceUtils;
 import com.android.server.pm.PackageSetting;
 import com.android.server.pm.UserManagerInternal;
 import com.android.server.pm.UserManagerService;
 import com.android.server.pm.parsing.PackageInfoUtils;
 import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.permission.PermissionManagerServiceInternal.OnRuntimePermissionStateChangedListener;
 import com.android.server.policy.PermissionPolicyInternal;
 import com.android.server.policy.SoftRestrictedPermissionPolicy;
 
@@ -239,9 +238,6 @@
     private final SparseArray<OneTimePermissionUserManager> mOneTimePermissionUserManagers =
             new SparseArray<>();
 
-    /** Default permission policy to provide proper behaviour out-of-the-box */
-    private final DefaultPermissionGrantPolicy mDefaultPermissionGrantPolicy;
-
     /** App ops manager */
     private final AppOpsManager mAppOpsManager;
 
@@ -390,8 +386,6 @@
         mHandler = new Handler(mHandlerThread.getLooper());
         Watchdog.getInstance().addThread(mHandler);
 
-        mDefaultPermissionGrantPolicy = new DefaultPermissionGrantPolicy(
-                context, mHandlerThread.getLooper());
         SystemConfig systemConfig = SystemConfig.getInstance();
         mSystemPermissions = systemConfig.getSystemPermissions();
         mGlobalGids = systemConfig.getGlobalGids();
@@ -2007,90 +2001,40 @@
 
     @Override
     public void grantDefaultPermissionsToEnabledCarrierApps(String[] packageNames, int userId) {
-        final int callingUid = Binder.getCallingUid();
-        PackageManagerServiceUtils
-                .enforceSystemOrPhoneCaller("grantPermissionsToEnabledCarrierApps", callingUid);
-        Binder.withCleanCallingIdentity(() -> mDefaultPermissionGrantPolicy
-                .grantDefaultPermissionsToEnabledCarrierApps(packageNames, userId));
+        LocalServices.getService(LegacyPermissionManagerInternal.class)
+                .grantDefaultPermissionsToEnabledCarrierApps(packageNames, userId);
     }
 
     @Override
     public void grantDefaultPermissionsToEnabledImsServices(String[] packageNames, int userId) {
-        final int callingUid = Binder.getCallingUid();
-        PackageManagerServiceUtils.enforceSystemOrPhoneCaller(
-                "grantDefaultPermissionsToEnabledImsServices", callingUid);
-        Binder.withCleanCallingIdentity(() -> mDefaultPermissionGrantPolicy
-                .grantDefaultPermissionsToEnabledImsServices(packageNames, userId));
+        LocalServices.getService(LegacyPermissionManagerInternal.class)
+                .grantDefaultPermissionsToEnabledImsServices(packageNames, userId);
     }
 
     @Override
     public void grantDefaultPermissionsToEnabledTelephonyDataServices(
             String[] packageNames, int userId) {
-        final int callingUid = Binder.getCallingUid();
-        PackageManagerServiceUtils.enforceSystemOrPhoneCaller(
-                "grantDefaultPermissionsToEnabledTelephonyDataServices", callingUid);
-        Binder.withCleanCallingIdentity(() -> mDefaultPermissionGrantPolicy
-                .grantDefaultPermissionsToEnabledTelephonyDataServices(packageNames, userId));
+        LocalServices.getService(LegacyPermissionManagerInternal.class)
+                .grantDefaultPermissionsToEnabledTelephonyDataServices(packageNames, userId);
     }
 
     @Override
     public void revokeDefaultPermissionsFromDisabledTelephonyDataServices(
             String[] packageNames, int userId) {
-        final int callingUid = Binder.getCallingUid();
-        PackageManagerServiceUtils.enforceSystemOrPhoneCaller(
-                "revokeDefaultPermissionsFromDisabledTelephonyDataServices", callingUid);
-        Binder.withCleanCallingIdentity(() -> mDefaultPermissionGrantPolicy
-                .revokeDefaultPermissionsFromDisabledTelephonyDataServices(packageNames, userId));
+        LocalServices.getService(LegacyPermissionManagerInternal.class)
+                .revokeDefaultPermissionsFromDisabledTelephonyDataServices(packageNames, userId);
     }
 
     @Override
     public void grantDefaultPermissionsToActiveLuiApp(String packageName, int userId) {
-        final int callingUid = Binder.getCallingUid();
-        PackageManagerServiceUtils
-                .enforceSystemOrPhoneCaller("grantDefaultPermissionsToActiveLuiApp", callingUid);
-        Binder.withCleanCallingIdentity(() -> mDefaultPermissionGrantPolicy
-                .grantDefaultPermissionsToActiveLuiApp(packageName, userId));
+        LocalServices.getService(LegacyPermissionManagerInternal.class)
+                .grantDefaultPermissionsToActiveLuiApp(packageName, userId);
     }
 
     @Override
     public void revokeDefaultPermissionsFromLuiApps(String[] packageNames, int userId) {
-        final int callingUid = Binder.getCallingUid();
-        PackageManagerServiceUtils
-                .enforceSystemOrPhoneCaller("revokeDefaultPermissionsFromLuiApps", callingUid);
-        Binder.withCleanCallingIdentity(() -> mDefaultPermissionGrantPolicy
-                .revokeDefaultPermissionsFromLuiApps(packageNames, userId));
-    }
-
-    @Override
-    public void setPermissionEnforced(String permName, boolean enforced) {
-        // TODO: Now that we no longer change GID for storage, this should to away.
-        mContext.enforceCallingOrSelfPermission(Manifest.permission.GRANT_RUNTIME_PERMISSIONS,
-                "setPermissionEnforced");
-        if (READ_EXTERNAL_STORAGE.equals(permName)) {
-            mPackageManagerInt.setReadExternalStorageEnforced(enforced);
-            // kill any non-foreground processes so we restart them and
-            // grant/revoke the GID.
-            final IActivityManager am = ActivityManager.getService();
-            if (am != null) {
-                final long token = Binder.clearCallingIdentity();
-                try {
-                    am.killProcessesBelowForeground("setPermissionEnforcement");
-                } catch (RemoteException e) {
-                } finally {
-                    Binder.restoreCallingIdentity(token);
-                }
-            }
-        } else {
-            throw new IllegalArgumentException("No selective enforcement for " + permName);
-        }
-    }
-
-    /** @deprecated */
-    @Override
-    @Deprecated
-    public boolean isPermissionEnforced(String permName) {
-        // allow instant applications
-        return true;
+        LocalServices.getService(LegacyPermissionManagerInternal.class)
+                .revokeDefaultPermissionsFromLuiApps(packageNames, userId);
     }
 
     /**
@@ -2197,19 +2141,20 @@
      *
      * <p>Can not be called on main thread.
      *
-     * @param user The user the data should be extracted for
+     * @param userId The user ID the data should be extracted for
      *
      * @return The state as a xml file
      */
-    private @Nullable byte[] backupRuntimePermissions(@NonNull UserHandle user) {
+    @Nullable
+    private byte[] backupRuntimePermissions(@UserIdInt int userId) {
         CompletableFuture<byte[]> backup = new CompletableFuture<>();
-        mPermissionControllerManager.getRuntimePermissionBackup(user, mContext.getMainExecutor(),
-                backup::complete);
+        mPermissionControllerManager.getRuntimePermissionBackup(UserHandle.of(userId),
+                mContext.getMainExecutor(), backup::complete);
 
         try {
             return backup.get(BACKUP_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
         } catch (InterruptedException | ExecutionException  | TimeoutException e) {
-            Slog.e(TAG, "Cannot create permission backup for " + user, e);
+            Slog.e(TAG, "Cannot create permission backup for user " + userId, e);
             return null;
         }
     }
@@ -2221,13 +2166,14 @@
      * applied via {@link #restoreDelayedRuntimePermissions}.
      *
      * @param backup The state as an xml file
-     * @param user The user the data should be restored for
+     * @param userId The user ID the data should be restored for
      */
-    private void restoreRuntimePermissions(@NonNull byte[] backup, @NonNull UserHandle user) {
+    private void restoreRuntimePermissions(@NonNull byte[] backup, @UserIdInt int userId) {
         synchronized (mLock) {
-            mHasNoDelayedPermBackup.delete(user.getIdentifier());
+            mHasNoDelayedPermBackup.delete(userId);
         }
-        mPermissionControllerManager.stageAndApplyRuntimePermissionsBackup(backup, user);
+        mPermissionControllerManager.stageAndApplyRuntimePermissionsBackup(backup,
+                UserHandle.of(userId));
     }
 
     /**
@@ -2236,24 +2182,24 @@
      * <p>Can not be called on main thread.
      *
      * @param packageName The package that is newly installed
-     * @param user The user the package is installed for
+     * @param userId The user ID the package is installed for
      *
      * @see #restoreRuntimePermissions
      */
     private void restoreDelayedRuntimePermissions(@NonNull String packageName,
-            @NonNull UserHandle user) {
+            @UserIdInt int userId) {
         synchronized (mLock) {
-            if (mHasNoDelayedPermBackup.get(user.getIdentifier(), false)) {
+            if (mHasNoDelayedPermBackup.get(userId, false)) {
                 return;
             }
         }
-        mPermissionControllerManager.applyStagedRuntimePermissionBackup(packageName, user,
-                mContext.getMainExecutor(), (hasMoreBackup) -> {
+        mPermissionControllerManager.applyStagedRuntimePermissionBackup(packageName,
+                UserHandle.of(userId), mContext.getMainExecutor(), (hasMoreBackup) -> {
                     if (hasMoreBackup) {
                         return;
                     }
                     synchronized (mLock) {
-                        mHasNoDelayedPermBackup.put(user.getIdentifier(), true);
+                        mHasNoDelayedPermBackup.put(userId, true);
                     }
                 });
     }
@@ -4581,24 +4527,6 @@
 
         mPermissionControllerManager = mContext.getSystemService(PermissionControllerManager.class);
         mPermissionPolicyInternal = LocalServices.getService(PermissionPolicyInternal.class);
-
-        int[] grantPermissionsUserIds = EMPTY_INT_ARRAY;
-        for (int userId : UserManagerService.getInstance().getUserIds()) {
-            if (mPackageManagerInt.isPermissionUpgradeNeeded(userId)) {
-                grantPermissionsUserIds = ArrayUtils.appendInt(
-                        grantPermissionsUserIds, userId);
-            }
-        }
-        // If we upgraded grant all default permissions before kicking off.
-        for (int userId : grantPermissionsUserIds) {
-            mDefaultPermissionGrantPolicy.grantDefaultPermissions(userId);
-        }
-        if (grantPermissionsUserIds == EMPTY_INT_ARRAY) {
-            // If we did not grant default permissions, we preload from this the
-            // default permission exceptions lazily to ensure we don't hit the
-            // disk on a new user creation.
-            mDefaultPermissionGrantPolicy.scheduleReadDefaultPermissionExceptions();
-        }
     }
 
     private static String getVolumeUuidForPackage(AndroidPackage pkg) {
@@ -5058,7 +4986,7 @@
         }
     }
 
-    private class PermissionManagerServiceInternalImpl extends PermissionManagerServiceInternal {
+    private class PermissionManagerServiceInternalImpl implements PermissionManagerServiceInternal {
         @Override
         public void systemReady() {
             PermissionManagerService.this.systemReady();
@@ -5083,6 +5011,7 @@
         }
         @Override
         public void onUserRemoved(@UserIdInt int userId) {
+            Preconditions.checkArgumentNonNegative(userId, "userId");
             PermissionManagerService.this.onUserRemoved(userId);
         }
         @NonNull
@@ -5162,20 +5091,26 @@
             return matchingPermissions;
         }
 
+        @Nullable
         @Override
-        public @Nullable byte[] backupRuntimePermissions(@NonNull UserHandle user) {
-            return PermissionManagerService.this.backupRuntimePermissions(user);
+        public byte[] backupRuntimePermissions(@UserIdInt int userId) {
+            Preconditions.checkArgumentNonNegative(userId, "userId");
+            return PermissionManagerService.this.backupRuntimePermissions(userId);
         }
 
         @Override
-        public void restoreRuntimePermissions(@NonNull byte[] backup, @NonNull UserHandle user) {
-            PermissionManagerService.this.restoreRuntimePermissions(backup, user);
+        public void restoreRuntimePermissions(@NonNull byte[] backup, @UserIdInt int userId) {
+            Objects.requireNonNull(backup, "backup");
+            Preconditions.checkArgumentNonNegative(userId, "userId");
+            PermissionManagerService.this.restoreRuntimePermissions(backup, userId);
         }
 
         @Override
         public void restoreDelayedRuntimePermissions(@NonNull String packageName,
-                @NonNull UserHandle user) {
-            PermissionManagerService.this.restoreDelayedRuntimePermissions(packageName, user);
+                @UserIdInt int userId) {
+            Objects.requireNonNull(packageName, "packageName");
+            Preconditions.checkArgumentNonNegative(userId, "userId");
+            PermissionManagerService.this.restoreDelayedRuntimePermissions(packageName, userId);
         }
 
         @Override
@@ -5205,84 +5140,11 @@
         }
 
         @Override
-        public void setDialerAppPackagesProvider(PackagesProvider provider) {
-            mDefaultPermissionGrantPolicy.setDialerAppPackagesProvider(provider);
-        }
-
-        @Override
-        public void setLocationExtraPackagesProvider(PackagesProvider provider) {
-            mDefaultPermissionGrantPolicy.setLocationExtraPackagesProvider(provider);
-        }
-
-        @Override
-        public void setLocationPackagesProvider(PackagesProvider provider) {
-            mDefaultPermissionGrantPolicy.setLocationPackagesProvider(provider);
-        }
-
-        @Override
-        public void setSimCallManagerPackagesProvider(PackagesProvider provider) {
-            mDefaultPermissionGrantPolicy.setSimCallManagerPackagesProvider(provider);
-        }
-
-        @Override
-        public void setSmsAppPackagesProvider(PackagesProvider provider) {
-            mDefaultPermissionGrantPolicy.setSmsAppPackagesProvider(provider);
-        }
-
-        @Override
-        public void setSyncAdapterPackagesProvider(SyncAdapterPackagesProvider provider) {
-            mDefaultPermissionGrantPolicy.setSyncAdapterPackagesProvider(provider);
-        }
-
-        @Override
-        public void setUseOpenWifiAppPackagesProvider(PackagesProvider provider) {
-            mDefaultPermissionGrantPolicy.setUseOpenWifiAppPackagesProvider(provider);
-        }
-
-        @Override
-        public void setVoiceInteractionPackagesProvider(PackagesProvider provider) {
-            mDefaultPermissionGrantPolicy.setVoiceInteractionPackagesProvider(provider);
-        }
-
-        @Override
-        public void grantDefaultPermissionsToDefaultBrowser(@NonNull String packageName,
-                @UserIdInt int userId) {
-            mDefaultPermissionGrantPolicy.grantDefaultPermissionsToDefaultBrowser(packageName,
-                    userId);
-        }
-
-        @Override
-        public void grantDefaultPermissionsToDefaultSimCallManager(String packageName, int userId) {
-            mDefaultPermissionGrantPolicy.grantDefaultPermissionsToDefaultSimCallManager(
-                    packageName, userId);
-        }
-
-        @Override
-        public void grantDefaultPermissionsToDefaultUseOpenWifiApp(String packageName, int userId) {
-            mDefaultPermissionGrantPolicy.grantDefaultPermissionsToDefaultUseOpenWifiApp(
-                    packageName, userId);
-        }
-
-        @Override
-        public void onNewUserCreated(int userId) {
+        public void onUserCreated(@UserIdInt int userId) {
+            Preconditions.checkArgumentNonNegative(userId, "userId");
             // NOTE: This adds UPDATE_PERMISSIONS_REPLACE_PKG
             PermissionManagerService.this.updateAllPermissions(StorageManager.UUID_PRIVATE_INTERNAL,
                     true, mDefaultPermissionCallback);
-            mDefaultPermissionGrantPolicy.grantDefaultPermissions(userId);
-        }
-
-        @Override
-        public void retainHardAndSoftRestrictedPermissions(@NonNull List<String> permissionNames) {
-            synchronized (mLock) {
-                Iterator<String> iterator = permissionNames.iterator();
-                while (iterator.hasNext()) {
-                    final String permissionName = iterator.next();
-                    final Permission permission = mRegistry.getPermission(permissionName);
-                    if (permission == null || !permission.isHardOrSoftRestricted()) {
-                        iterator.remove();
-                    }
-                }
-            }
         }
 
         @Override
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java
index e006fa7..0817d4f 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java
@@ -34,38 +34,27 @@
 /**
  * Internal interfaces services.
  *
- * TODO: Should be merged into PermissionManagerInternal, but currently uses internal classes.
+ * TODO: Move into module.
  */
-public abstract class PermissionManagerServiceInternal extends PermissionManagerInternal
-        implements LegacyPermissionDataProvider {
+public interface PermissionManagerServiceInternal extends PermissionManagerInternal,
+        LegacyPermissionDataProvider {
     /**
-     * Provider for package names.
+     * Adds a listener for runtime permission state (permissions or flags) changes.
+     *
+     * @param listener The listener.
      */
-    public interface PackagesProvider {
-
-        /**
-         * Gets the packages for a given user.
-         * @param userId The user id.
-         * @return The package names.
-         */
-        String[] getPackages(int userId);
-    }
+    void addOnRuntimePermissionStateChangedListener(
+            @NonNull OnRuntimePermissionStateChangedListener listener);
 
     /**
-     * Provider for package names.
+     * Removes a listener for runtime permission state (permissions or flags) changes.
+     *
+     * @param listener The listener.
      */
-    public interface SyncAdapterPackagesProvider {
+    void removeOnRuntimePermissionStateChangedListener(
+            @NonNull OnRuntimePermissionStateChangedListener listener);
 
-        /**
-         * Gets the sync adapter packages for given authority and user.
-         * @param authority The authority.
-         * @param userId The user id.
-         * @return The package names.
-         */
-        String[] getPackages(String authority, int userId);
-    }
-
-    public abstract void systemReady();
+    void systemReady();
 
     /**
      * Get whether permission review is required for a package.
@@ -75,7 +64,7 @@
      * @return whether permission review is required
      */
     //@SystemApi(client = SystemApi.Client.SYSTEM_SERVER)
-    public abstract boolean isPermissionsReviewRequired(@NonNull String packageName,
+    boolean isPermissionsReviewRequired(@NonNull String packageName,
             @UserIdInt int userId);
 
     /**
@@ -90,7 +79,7 @@
      * @param allPackages All currently known packages
      * @param callback Callback to call after permission changes
      */
-    public abstract void updateAllPermissions(@Nullable String volumeUuid, boolean sdkUpdate);
+    void updateAllPermissions(@Nullable String volumeUuid, boolean sdkUpdate);
 
     /**
      * Reset the runtime permission state changes for a package.
@@ -101,7 +90,7 @@
      * @param userId the user ID
      */
     //@SystemApi(client = SystemApi.Client.SYSTEM_SERVER)
-    public abstract void resetRuntimePermissions(@NonNull AndroidPackage pkg,
+    void resetRuntimePermissions(@NonNull AndroidPackage pkg,
             @UserIdInt int userId);
 
     /**
@@ -110,7 +99,7 @@
      * @param userId the user ID
      */
     //@SystemApi(client = SystemApi.Client.SYSTEM_SERVER)
-    public abstract void resetAllRuntimePermissions(@UserIdInt int userId);
+    void resetAllRuntimePermissions(@UserIdInt int userId);
 
     /**
      * Read legacy permission state from package settings.
@@ -119,7 +108,7 @@
      * {@code PackageSetting} which is a implementation detail that permission should not know.
      * Instead, it should retrieve the legacy state via a defined API.
      */
-    public abstract void readLegacyPermissionStateTEMP();
+    void readLegacyPermissionStateTEMP();
 
     /**
      * Write legacy permission state to package settings.
@@ -127,12 +116,7 @@
      * TODO(zhanghai): This is a temporary method and should be removed once we migrated persistence
      * for permission.
      */
-    public abstract void writeLegacyPermissionStateTEMP();
-
-    /**
-     * Notify that a user has been removed and its permission state should be removed as well.
-     */
-    public abstract void onUserRemoved(@UserIdInt int userId);
+    void writeLegacyPermissionStateTEMP();
 
     /**
      * Get all the permissions granted to a package.
@@ -143,8 +127,7 @@
      */
     //@SystemApi(client = SystemApi.Client.SYSTEM_SERVER)
     @NonNull
-    public abstract Set<String> getGrantedPermissions(@NonNull String packageName,
-            @UserIdInt int userId);
+    Set<String> getGrantedPermissions(@NonNull String packageName, @UserIdInt int userId);
 
     /**
      * Get the GIDs of a permission.
@@ -155,7 +138,7 @@
      */
     //@SystemApi(client = SystemApi.Client.SYSTEM_SERVER)
     @NonNull
-    public abstract int[] getPermissionGids(@NonNull String permissionName, @UserIdInt int userId);
+    int[] getPermissionGids(@NonNull String permissionName, @UserIdInt int userId);
 
     /**
      * Get the packages that have requested an app op permission.
@@ -165,18 +148,19 @@
      */
     //@SystemApi(client = SystemApi.Client.SYSTEM_SERVER)
     @NonNull
-    public abstract String[] getAppOpPermissionPackages(@NonNull String permissionName);
+    String[] getAppOpPermissionPackages(@NonNull String permissionName);
 
     /** HACK HACK methods to allow for partial migration of data to the PermissionManager class */
     @Nullable
-    public abstract Permission getPermissionTEMP(@NonNull String permName);
+    Permission getPermissionTEMP(@NonNull String permName);
 
     /** Get all permissions that have a certain protection */
-    public abstract @NonNull ArrayList<PermissionInfo> getAllPermissionsWithProtection(
+    @NonNull
+    ArrayList<PermissionInfo> getAllPermissionsWithProtection(
             @PermissionInfo.Protection int protection);
 
     /** Get all permissions that have certain protection flags */
-    public abstract @NonNull ArrayList<PermissionInfo> getAllPermissionsWithProtectionFlags(
+    @NonNull ArrayList<PermissionInfo> getAllPermissionsWithProtectionFlags(
             @PermissionInfo.ProtectionFlags int protectionFlags);
 
     /**
@@ -188,7 +172,7 @@
      *                       for, or {@code null} for all permissions
      */
     //@SystemApi(client = SystemApi.Client.SYSTEM_SERVER)
-    public abstract void startShellPermissionIdentityDelegation(int uid,
+    void startShellPermissionIdentityDelegation(int uid,
             @NonNull String packageName, @Nullable List<String> permissionNames);
 
     /**
@@ -197,89 +181,7 @@
      * @see #startShellPermissionIdentityDelegation(int, String, List)
      */
     //@SystemApi(client = SystemApi.Client.SYSTEM_SERVER)
-    public abstract void stopShellPermissionIdentityDelegation();
-
-    /**
-     * Sets the dialer application packages provider.
-     * @param provider The provider.
-     */
-    public abstract void setDialerAppPackagesProvider(PackagesProvider provider);
-
-    /**
-     * Set the location extra packages provider.
-     * @param provider The packages provider.
-     */
-    public abstract  void setLocationExtraPackagesProvider(PackagesProvider provider);
-
-    /**
-     * Sets the location provider packages provider.
-     * @param provider The packages provider.
-     */
-    public abstract void setLocationPackagesProvider(PackagesProvider provider);
-
-    /**
-     * Sets the SIM call manager packages provider.
-     * @param provider The provider.
-     */
-    public abstract void setSimCallManagerPackagesProvider(PackagesProvider provider);
-
-    /**
-     * Sets the SMS application packages provider.
-     * @param provider The provider.
-     */
-    public abstract void setSmsAppPackagesProvider(PackagesProvider provider);
-
-    /**
-     * Sets the sync adapter packages provider.
-     * @param provider The provider.
-     */
-    public abstract void setSyncAdapterPackagesProvider(SyncAdapterPackagesProvider provider);
-
-    /**
-     * Sets the Use Open Wifi packages provider.
-     * @param provider The packages provider.
-     */
-    public abstract void setUseOpenWifiAppPackagesProvider(PackagesProvider provider);
-
-    /**
-     * Sets the voice interaction packages provider.
-     * @param provider The packages provider.
-     */
-    public abstract void setVoiceInteractionPackagesProvider(PackagesProvider provider);
-
-    /**
-     * Requests granting of the default permissions to the current default browser.
-     * @param packageName The default browser package name.
-     * @param userId The user for which to grant the permissions.
-     */
-    public abstract void grantDefaultPermissionsToDefaultBrowser(
-            @NonNull String packageName, @UserIdInt int userId);
-
-    /**
-     * Requests granting of the default permissions to the current default Use Open Wifi app.
-     * @param packageName The default use open wifi package name.
-     * @param userId The user for which to grant the permissions.
-     */
-    public abstract void grantDefaultPermissionsToDefaultSimCallManager(
-            @NonNull String packageName, @UserIdInt int userId);
-
-    /**
-     * Requests granting of the default permissions to the current default Use Open Wifi app.
-     * @param packageName The default use open wifi package name.
-     * @param userId The user for which to grant the permissions.
-     */
-    public abstract void grantDefaultPermissionsToDefaultUseOpenWifiApp(
-            @NonNull String packageName, @UserIdInt int userId);
-
-    /** Called when a new user has been created. */
-    public abstract void onNewUserCreated(@UserIdInt int userId);
-
-    /**
-     * Removes invalid permissions which are not {@link PermissionInfo#FLAG_HARD_RESTRICTED} or
-     * {@link PermissionInfo#FLAG_SOFT_RESTRICTED} from the input.
-     */
-    public abstract void retainHardAndSoftRestrictedPermissions(
-            @NonNull List<String> permissionNames);
+    void stopShellPermissionIdentityDelegation();
 
     /**
      * Read legacy permissions from legacy permission settings.
@@ -288,8 +190,7 @@
      * {@code LegacyPermissionSettings} which is a implementation detail that permission should not
      * know. Instead, it should retrieve the legacy permissions via a defined API.
      */
-    public abstract void readLegacyPermissionsTEMP(
-            @NonNull LegacyPermissionSettings legacyPermissionSettings);
+    void readLegacyPermissionsTEMP(@NonNull LegacyPermissionSettings legacyPermissionSettings);
 
     /**
      * Write legacy permissions to legacy permission settings.
@@ -297,8 +198,23 @@
      * TODO(zhanghai): This is a temporary method and should be removed once we migrated persistence
      * for permission.
      */
-    public abstract void writeLegacyPermissionsTEMP(
-            @NonNull LegacyPermissionSettings legacyPermissionSettings);
+    void writeLegacyPermissionsTEMP(@NonNull LegacyPermissionSettings legacyPermissionSettings);
+
+    /**
+     * Callback when a user has been created.
+     *
+     * @param userId the created user ID
+     */
+    //@SystemApi(client = SystemApi.Client.SYSTEM_SERVER)
+    void onUserCreated(@UserIdInt int userId);
+
+    /**
+     * Callback when a user has been removed.
+     *
+     * @param userId the removed user ID
+     */
+    //@SystemApi(client = SystemApi.Client.SYSTEM_SERVER)
+    void onUserRemoved(@UserIdInt int userId);
 
     /**
      * Callback when a package has been added.
@@ -308,7 +224,7 @@
      * @param oldPkg the old package, or {@code null} if none
      */
     //@SystemApi(client = SystemApi.Client.SYSTEM_SERVER)
-    public abstract void onPackageAdded(@NonNull AndroidPackage pkg, boolean isInstantApp,
+    void onPackageAdded(@NonNull AndroidPackage pkg, boolean isInstantApp,
             @Nullable AndroidPackage oldPkg);
 
     /**
@@ -319,8 +235,8 @@
      * @param userId the user ID this package is installed for
      */
     //@SystemApi(client = SystemApi.Client.SYSTEM_SERVER)
-    public abstract void onPackageInstalled(@NonNull AndroidPackage pkg,
-            @NonNull PackageInstalledParams params, @UserIdInt int userId);
+    void onPackageInstalled(@NonNull AndroidPackage pkg, @NonNull PackageInstalledParams params,
+            @UserIdInt int userId);
 
     /**
      * Callback when a package has been removed.
@@ -328,7 +244,7 @@
      * @param pkg the removed package
      */
     //@SystemApi(client = SystemApi.Client.SYSTEM_SERVER)
-    public abstract void onPackageRemoved(@NonNull AndroidPackage pkg);
+    void onPackageRemoved(@NonNull AndroidPackage pkg);
 
     /**
      * Callback when a package has been uninstalled.
@@ -345,9 +261,8 @@
      * @param userId the user ID the package is uninstalled for
      */
     //@SystemApi(client = SystemApi.Client.SYSTEM_SERVER)
-    public abstract void onPackageUninstalled(@NonNull String packageName, int appId,
-            @Nullable AndroidPackage pkg, @NonNull List<AndroidPackage> sharedUserPkgs,
-            @UserIdInt int userId);
+    void onPackageUninstalled(@NonNull String packageName, int appId, @Nullable AndroidPackage pkg,
+            @NonNull List<AndroidPackage> sharedUserPkgs, @UserIdInt int userId);
 
     /**
      * Check whether a permission can be propagated to instant app.
@@ -355,7 +270,23 @@
      * @param permissionName the name of the permission
      * @return whether the permission can be propagated
      */
-    public abstract boolean canPropagatePermissionToInstantApp(@NonNull String permissionName);
+    boolean canPropagatePermissionToInstantApp(@NonNull String permissionName);
+
+    /**
+     * Listener for package permission state (permissions or flags) changes.
+     */
+    interface OnRuntimePermissionStateChangedListener {
+
+        /**
+         * Called when the runtime permission state (permissions or flags) changed.
+         *
+         * @param packageName The package for which the change happened.
+         * @param userId the user id for which the change happened.
+         */
+        @Nullable
+        void onRuntimePermissionStateChanged(@NonNull String packageName,
+                @UserIdInt int userId);
+    }
 
     /**
      * The permission-related parameters passed in for package installation.
@@ -363,7 +294,7 @@
      * @see android.content.pm.PackageInstaller.SessionParams
      */
     //@SystemApi(client = SystemApi.Client.SYSTEM_SERVER)
-    public static final class PackageInstalledParams {
+    final class PackageInstalledParams {
         /**
          * A static instance whose parameters are all in their default state.
          */
diff --git a/services/core/java/com/android/server/policy/KeyCombinationManager.java b/services/core/java/com/android/server/policy/KeyCombinationManager.java
new file mode 100644
index 0000000..84ac124
--- /dev/null
+++ b/services/core/java/com/android/server/policy/KeyCombinationManager.java
@@ -0,0 +1,229 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.policy;
+
+import static android.view.KeyEvent.KEYCODE_POWER;
+
+import android.os.SystemClock;
+import android.util.SparseLongArray;
+import android.view.KeyEvent;
+
+import com.android.internal.util.ToBooleanFunction;
+
+import java.util.ArrayList;
+import java.util.function.Consumer;
+
+/**
+ * Handles a mapping of two keys combination.
+ */
+public class KeyCombinationManager {
+    private static final String TAG = "KeyCombinationManager";
+
+    // Store the received down time of keycode.
+    private final SparseLongArray mDownTimes = new SparseLongArray(2);
+    private final ArrayList<TwoKeysCombinationRule> mRules = new ArrayList();
+
+    // Selected rules according to current key down.
+    private final ArrayList<TwoKeysCombinationRule> mActiveRules = new ArrayList();
+    // The rule has been triggered by current keys.
+    private TwoKeysCombinationRule mTriggeredRule;
+
+    // Keys in a key combination must be pressed within this interval of each other.
+    private static final long COMBINE_KEY_DELAY_MILLIS = 150;
+
+    /**
+     *  Rule definition for two keys combination.
+     *  E.g : define volume_down + power key.
+     *  <pre class="prettyprint">
+     *  TwoKeysCombinationRule rule =
+     *      new TwoKeysCombinationRule(KEYCODE_VOLUME_DOWN, KEYCODE_POWER) {
+     *           boolean preCondition() { // check if it needs to intercept key }
+     *           void execute() { // trigger action }
+     *           void cancel() { // cancel action }
+     *       };
+     *  </pre>
+     */
+    abstract static class TwoKeysCombinationRule {
+        private int mKeyCode1;
+        private int mKeyCode2;
+
+        TwoKeysCombinationRule(int keyCode1, int keyCode2) {
+            mKeyCode1 = keyCode1;
+            mKeyCode2 = keyCode2;
+        }
+
+        boolean preCondition() {
+            return true;
+        }
+
+        boolean shouldInterceptKey(int keyCode) {
+            return preCondition() && (keyCode == mKeyCode1 || keyCode == mKeyCode2);
+        }
+
+        boolean shouldInterceptKeys(SparseLongArray downTimes) {
+            final long now = SystemClock.uptimeMillis();
+            if (downTimes.get(mKeyCode1) > 0
+                    && downTimes.get(mKeyCode2) > 0
+                    && now <= downTimes.get(mKeyCode1) + COMBINE_KEY_DELAY_MILLIS
+                    && now <= downTimes.get(mKeyCode2) + COMBINE_KEY_DELAY_MILLIS) {
+                return true;
+            }
+            return false;
+        }
+
+        abstract void execute();
+        abstract void cancel();
+
+        @Override
+        public String toString() {
+            return "KeyCode1 = " + KeyEvent.keyCodeToString(mKeyCode1)
+                    + ", KeyCode2 = " +  KeyEvent.keyCodeToString(mKeyCode2);
+        }
+    }
+
+    public KeyCombinationManager() {
+    }
+
+    void addRule(TwoKeysCombinationRule rule) {
+        mRules.add(rule);
+    }
+
+    /**
+     * Check if the key event could be triggered by combine key rule before dispatching to a window.
+     */
+    void interceptKey(KeyEvent event, boolean interactive) {
+        final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
+        final int keyCode = event.getKeyCode();
+        final int count = mActiveRules.size();
+        final long eventTime = event.getEventTime();
+
+        if (interactive && down) {
+            if (mDownTimes.size() > 0) {
+                if (count > 0
+                        && eventTime > mDownTimes.valueAt(0) + COMBINE_KEY_DELAY_MILLIS) {
+                    // exceed time from first key down.
+                    forAllRules(mActiveRules, (rule)-> rule.cancel());
+                    mActiveRules.clear();
+                    return;
+                } else if (count == 0) { // has some key down but no active rule exist.
+                    return;
+                }
+            }
+
+            if (mDownTimes.get(keyCode) == 0) {
+                mDownTimes.put(keyCode, eventTime);
+            } else {
+                // ignore old key, maybe a repeat key.
+                return;
+            }
+
+            if (mDownTimes.size() == 1) {
+                mTriggeredRule = null;
+                // check first key and pick active rules.
+                forAllRules(mRules, (rule)-> {
+                    if (rule.shouldInterceptKey(keyCode)) {
+                        mActiveRules.add(rule);
+                    }
+                });
+            } else {
+                // Ignore if rule already triggered.
+                if (mTriggeredRule != null) {
+                    return;
+                }
+
+                // check if second key can trigger rule, or remove the non-match rule.
+                forAllActiveRules((rule) -> {
+                    if (!rule.shouldInterceptKeys(mDownTimes)) {
+                        return false;
+                    }
+                    rule.execute();
+                    mTriggeredRule = rule;
+                    return true;
+                });
+                mActiveRules.clear();
+                if (mTriggeredRule != null) {
+                    mActiveRules.add(mTriggeredRule);
+                }
+            }
+        } else {
+            mDownTimes.delete(keyCode);
+            for (int index = count - 1; index >= 0; index--) {
+                final TwoKeysCombinationRule rule = mActiveRules.get(index);
+                if (rule.shouldInterceptKey(keyCode)) {
+                    rule.cancel();
+                    mActiveRules.remove(index);
+                }
+            }
+        }
+    }
+
+    /**
+     * Return the interceptTimeout to tell InputDispatcher when is ready to deliver to window.
+     */
+    long getKeyInterceptTimeout(int keyCode) {
+        if (forAllActiveRules((rule) -> rule.shouldInterceptKey(keyCode))) {
+            return mDownTimes.get(keyCode) + COMBINE_KEY_DELAY_MILLIS;
+        }
+        return 0;
+    }
+
+    /**
+     * True if the key event had been handled.
+     */
+    boolean isKeyConsumed(KeyEvent event) {
+        if ((event.getFlags() & KeyEvent.FLAG_FALLBACK) != 0) {
+            return false;
+        }
+        return mTriggeredRule != null && mTriggeredRule.shouldInterceptKey(event.getKeyCode());
+    }
+
+    /**
+     * True if power key is the candidate.
+     */
+    boolean isPowerKeyIntercepted() {
+        if (forAllActiveRules((rule) -> rule.shouldInterceptKey(KEYCODE_POWER))) {
+            // return false if only if power key pressed.
+            return mDownTimes.size() > 1 || mDownTimes.get(KEYCODE_POWER) == 0;
+        }
+        return false;
+    }
+
+    /**
+     * Traverse each item of rules.
+     */
+    private void forAllRules(
+            ArrayList<TwoKeysCombinationRule> rules, Consumer<TwoKeysCombinationRule> callback) {
+        final int count = rules.size();
+        for (int index = 0; index < count; index++) {
+            final TwoKeysCombinationRule rule = rules.get(index);
+            callback.accept(rule);
+        }
+    }
+
+    /**
+     * Traverse each item of active rules until some rule can be applied, otherwise return false.
+     */
+    private boolean forAllActiveRules(ToBooleanFunction<TwoKeysCombinationRule> callback) {
+        final int count = mActiveRules.size();
+        for (int index = 0; index < count; index++) {
+            final TwoKeysCombinationRule rule = mActiveRules.get(index);
+            if (callback.apply(rule)) {
+                return true;
+            }
+        }
+        return false;
+    }
+}
diff --git a/services/core/java/com/android/server/policy/OWNERS b/services/core/java/com/android/server/policy/OWNERS
new file mode 100644
index 0000000..0862c05
--- /dev/null
+++ b/services/core/java/com/android/server/policy/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/wm/OWNERS
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 8beec35eb..ea985df 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -35,7 +35,13 @@
 import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.Display.INVALID_DISPLAY;
 import static android.view.Display.STATE_OFF;
+import static android.view.KeyEvent.KEYCODE_BACK;
+import static android.view.KeyEvent.KEYCODE_DPAD_CENTER;
+import static android.view.KeyEvent.KEYCODE_DPAD_DOWN;
+import static android.view.KeyEvent.KEYCODE_POWER;
 import static android.view.KeyEvent.KEYCODE_UNKNOWN;
+import static android.view.KeyEvent.KEYCODE_VOLUME_DOWN;
+import static android.view.KeyEvent.KEYCODE_VOLUME_UP;
 import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
 import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
 import static android.view.WindowManager.LayoutParams.FIRST_SYSTEM_WINDOW;
@@ -202,6 +208,7 @@
 import com.android.server.LocalServices;
 import com.android.server.SystemServiceManager;
 import com.android.server.inputmethod.InputMethodManagerInternal;
+import com.android.server.policy.KeyCombinationManager.TwoKeysCombinationRule;
 import com.android.server.policy.keyguard.KeyguardServiceDelegate;
 import com.android.server.policy.keyguard.KeyguardServiceDelegate.DrawnListener;
 import com.android.server.policy.keyguard.KeyguardStateMonitor.StateCallback;
@@ -405,7 +412,7 @@
     private boolean mEnableCarDockHomeCapture = true;
 
     boolean mBootMessageNeedsHiding;
-    KeyguardServiceDelegate mKeyguardDelegate;
+    private KeyguardServiceDelegate mKeyguardDelegate;
     private boolean mKeyguardBound;
     final Runnable mWindowManagerDrawCallback = new Runnable() {
         @Override
@@ -422,8 +429,8 @@
         }
     };
 
-    GlobalActions mGlobalActions;
-    Handler mHandler;
+    private GlobalActions mGlobalActions;
+    private Handler mHandler;
 
     // FIXME This state is shared between the input reader and handler thread.
     // Technically it's broken and buggy but it has been like this for many years
@@ -547,34 +554,14 @@
     private boolean mGoToSleepOnButtonPressTheaterMode;
 
     // Screenshot trigger states
-    // Time to volume and power must be pressed within this interval of each other.
-    private static final long SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS = 150;
     // Increase the chord delay when taking a screenshot from the keyguard
     private static final float KEYGUARD_SCREENSHOT_CHORD_DELAY_MULTIPLIER = 2.5f;
-    private boolean mScreenshotChordEnabled;
-    private boolean mScreenshotChordVolumeDownKeyTriggered;
-    private long mScreenshotChordVolumeDownKeyTime;
-    private boolean mScreenshotChordVolumeDownKeyConsumed;
-    private boolean mA11yShortcutChordVolumeUpKeyTriggered;
-    private long mA11yShortcutChordVolumeUpKeyTime;
-    private boolean mA11yShortcutChordVolumeUpKeyConsumed;
-
-    private boolean mScreenshotChordPowerKeyTriggered;
-    private long mScreenshotChordPowerKeyTime;
 
     // Ringer toggle should reuse timing and triggering from screenshot power and a11y vol up
-    private int mRingerToggleChord = VOLUME_HUSH_OFF;
+    int mRingerToggleChord = VOLUME_HUSH_OFF;
 
     private static final long BUGREPORT_TV_GESTURE_TIMEOUT_MILLIS = 1000;
 
-    private boolean mBugreportTvKey1Pressed;
-    private boolean mBugreportTvKey2Pressed;
-    private boolean mBugreportTvScheduled;
-
-    private boolean mAccessibilityTvKey1Pressed;
-    private boolean mAccessibilityTvKey2Pressed;
-    private boolean mAccessibilityTvScheduled;
-
     /* The number of steps between min and max brightness */
     private static final int BRIGHTNESS_STEPS = 10;
 
@@ -603,6 +590,8 @@
 
     private int mPowerButtonSuppressionDelayMillis = POWER_BUTTON_SUPPRESSION_DELAY_DEFAULT_MILLIS;
 
+    private KeyCombinationManager mKeyCombinationManager;
+
     private static final int MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK = 3;
     private static final int MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK = 4;
     private static final int MSG_KEYGUARD_DRAWN_COMPLETE = 5;
@@ -900,15 +889,6 @@
 
         mWindowManagerFuncs.onPowerKeyDown(interactive);
 
-        // Latch power key state to detect screenshot chord.
-        if (interactive && !mScreenshotChordPowerKeyTriggered
-                && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
-            mScreenshotChordPowerKeyTriggered = true;
-            mScreenshotChordPowerKeyTime = event.getDownTime();
-            interceptScreenshotChord();
-            interceptRingerToggleChord();
-        }
-
         // Stop ringing or end call if configured to do so when power is pressed.
         TelecomManager telecomManager = getTelecommService();
         boolean hungUp = false;
@@ -946,9 +926,8 @@
 
         // If the power key has still not yet been handled, then detect short
         // press, long press, or multi press and decide what to do.
-        mPowerKeyHandled = hungUp || mScreenshotChordVolumeDownKeyTriggered
-                || mA11yShortcutChordVolumeUpKeyTriggered || gesturedServiceIntercepted
-                || handledByPowerManager;
+        mPowerKeyHandled = hungUp || gesturedServiceIntercepted
+                || handledByPowerManager || mKeyCombinationManager.isPowerKeyIntercepted();
         if (!mPowerKeyHandled) {
             if (interactive) {
                 // When interactive, we're already awake.
@@ -1004,8 +983,6 @@
 
     private void interceptPowerKeyUp(KeyEvent event, boolean interactive, boolean canceled) {
         final boolean handled = canceled || mPowerKeyHandled;
-        mScreenshotChordPowerKeyTriggered = false;
-        cancelPendingScreenshotChordAction();
         cancelPendingPowerKeyAction();
 
         if (!handled) {
@@ -1315,52 +1292,22 @@
     }
 
     private void interceptScreenshotChord() {
-        if (mScreenshotChordEnabled
-                && mScreenshotChordVolumeDownKeyTriggered && mScreenshotChordPowerKeyTriggered
-                && !mA11yShortcutChordVolumeUpKeyTriggered) {
-            final long now = SystemClock.uptimeMillis();
-            if (now <= mScreenshotChordVolumeDownKeyTime + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS
-                    && now <= mScreenshotChordPowerKeyTime
-                            + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS) {
-                mScreenshotChordVolumeDownKeyConsumed = true;
-                cancelPendingPowerKeyAction();
-                mScreenshotRunnable.setScreenshotType(TAKE_SCREENSHOT_FULLSCREEN);
-                mScreenshotRunnable.setScreenshotSource(SCREENSHOT_KEY_CHORD);
-                mHandler.postDelayed(mScreenshotRunnable, getScreenshotChordLongPressDelay());
-            }
-        }
+        mHandler.removeCallbacks(mScreenshotRunnable);
+        mScreenshotRunnable.setScreenshotType(TAKE_SCREENSHOT_FULLSCREEN);
+        mScreenshotRunnable.setScreenshotSource(SCREENSHOT_KEY_CHORD);
+        mHandler.postDelayed(mScreenshotRunnable, getScreenshotChordLongPressDelay());
     }
 
     private void interceptAccessibilityShortcutChord() {
-        if (mAccessibilityShortcutController.isAccessibilityShortcutAvailable(isKeyguardLocked())
-                && mScreenshotChordVolumeDownKeyTriggered && mA11yShortcutChordVolumeUpKeyTriggered
-                && !mScreenshotChordPowerKeyTriggered) {
-            final long now = SystemClock.uptimeMillis();
-            if (now <= mScreenshotChordVolumeDownKeyTime + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS
-                    && now <= mA11yShortcutChordVolumeUpKeyTime
-                    + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS) {
-                mScreenshotChordVolumeDownKeyConsumed = true;
-                mA11yShortcutChordVolumeUpKeyConsumed = true;
-                mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_ACCESSIBILITY_SHORTCUT),
-                        getAccessibilityShortcutTimeout());
-            }
-        }
+        mHandler.removeMessages(MSG_ACCESSIBILITY_SHORTCUT);
+        mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_ACCESSIBILITY_SHORTCUT),
+                getAccessibilityShortcutTimeout());
     }
 
     private void interceptRingerToggleChord() {
-        if (mRingerToggleChord != Settings.Secure.VOLUME_HUSH_OFF
-                && mScreenshotChordPowerKeyTriggered && mA11yShortcutChordVolumeUpKeyTriggered) {
-            final long now = SystemClock.uptimeMillis();
-            if (now <= mA11yShortcutChordVolumeUpKeyTime + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS
-                    && now <= mScreenshotChordPowerKeyTime
-                    + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS) {
-                mA11yShortcutChordVolumeUpKeyConsumed = true;
-                cancelPendingPowerKeyAction();
-
-                mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_RINGER_TOGGLE_CHORD),
-                        getRingerToggleChordDelay());
-            }
-        }
+        mHandler.removeMessages(MSG_RINGER_TOGGLE_CHORD);
+        mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_RINGER_TOGGLE_CHORD),
+                getRingerToggleChordDelay());
     }
 
     private long getAccessibilityShortcutTimeout() {
@@ -1942,9 +1889,6 @@
         mSafeModeEnabledVibePattern = getLongIntArray(mContext.getResources(),
                 com.android.internal.R.array.config_safeModeEnabledVibePattern);
 
-        mScreenshotChordEnabled = mContext.getResources().getBoolean(
-                com.android.internal.R.bool.config_enableScreenshotChord);
-
         mGlobalKeyManager = new GlobalKeyManager(mContext);
 
         // Controls rotation and the like.
@@ -1980,6 +1924,92 @@
                         mWindowManagerFuncs.onKeyguardShowingAndNotOccludedChanged();
                     }
                 });
+        initKeyCombinationRules();
+    }
+
+    private void initKeyCombinationRules() {
+        mKeyCombinationManager = new KeyCombinationManager();
+        final boolean screenshotChordEnabled = mContext.getResources().getBoolean(
+                com.android.internal.R.bool.config_enableScreenshotChord);
+
+        if (screenshotChordEnabled) {
+            mKeyCombinationManager.addRule(
+                    new TwoKeysCombinationRule(KEYCODE_VOLUME_DOWN, KEYCODE_POWER) {
+                        @Override
+                        void execute() {
+                            cancelPendingPowerKeyAction();
+                            interceptScreenshotChord();
+                        }
+                        @Override
+                        void cancel() {
+                            cancelPendingScreenshotChordAction();
+                        }
+                    });
+        }
+
+        mKeyCombinationManager.addRule(
+                new TwoKeysCombinationRule(KEYCODE_VOLUME_DOWN, KEYCODE_VOLUME_UP) {
+                    @Override
+                    boolean preCondition() {
+                        return mAccessibilityShortcutController
+                                .isAccessibilityShortcutAvailable(isKeyguardLocked());
+                    }
+                    @Override
+                    void execute() {
+                        interceptAccessibilityShortcutChord();
+                    }
+                    @Override
+                    void cancel() {
+                        cancelPendingAccessibilityShortcutAction();
+                    }
+                });
+
+        mKeyCombinationManager.addRule(
+                new TwoKeysCombinationRule(KEYCODE_VOLUME_UP, KEYCODE_POWER) {
+                    @Override
+                    boolean preCondition() {
+                        return mRingerToggleChord != VOLUME_HUSH_OFF;
+                    }
+                    @Override
+                    void execute() {
+                        cancelPendingPowerKeyAction();
+                        interceptRingerToggleChord();
+                    }
+                    @Override
+                    void cancel() {
+                        cancelPendingRingerToggleChordAction();
+                    }
+                });
+
+        if (mHasFeatureLeanback) {
+            mKeyCombinationManager.addRule(
+                    new TwoKeysCombinationRule(KEYCODE_BACK, KEYCODE_DPAD_DOWN) {
+                        @Override
+                        void execute() {
+                            cancelPendingBackKeyAction();
+                            interceptAccessibilityGestureTv();
+                        }
+
+                        @Override
+                        void cancel() {
+                            cancelAccessibilityGestureTv();
+                        }
+                    });
+
+            mKeyCombinationManager.addRule(
+                    new TwoKeysCombinationRule(KEYCODE_DPAD_CENTER, KEYCODE_BACK) {
+                        @Override
+                        void execute() {
+                            cancelPendingBackKeyAction();
+                            interceptBugreportGestureTv();
+                        }
+
+                        @Override
+                        void cancel() {
+                            cancelBugreportGestureTv();
+                        }
+                    });
+        }
     }
 
     /**
@@ -2383,15 +2413,6 @@
             wm = (WindowManager) context.getSystemService(WINDOW_SERVICE);
             view = win.getDecorView();
 
-            // Ignore to show splash screen if the decorView is not opaque.
-            if (!view.isOpaque()) {
-                if (DEBUG_SPLASH_SCREEN) {
-                    Slog.d(TAG, "addSplashScreen: the view of " + packageName
-                            + " is not opaque, cancel it");
-                }
-                return null;
-            }
-
             if (DEBUG_SPLASH_SCREEN) Slog.d(TAG, "Adding splash screen window for "
                 + packageName + " / " + appToken + ": " + (view.getParent() != null ? view : null));
 
@@ -2552,70 +2573,15 @@
                     + repeatCount + " keyguardOn=" + keyguardOn + " canceled=" + canceled);
         }
 
-        // If we think we might have a volume down & power key chord on the way
-        // but we're not sure, then tell the dispatcher to wait a little while and
-        // try again later before dispatching.
-        if (mScreenshotChordEnabled && (flags & KeyEvent.FLAG_FALLBACK) == 0) {
-            if (mScreenshotChordVolumeDownKeyTriggered && !mScreenshotChordPowerKeyTriggered) {
-                final long now = SystemClock.uptimeMillis();
-                final long timeoutTime = mScreenshotChordVolumeDownKeyTime
-                        + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS;
-                if (now < timeoutTime) {
-                    return timeoutTime - now;
-                }
-            }
-            if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN
-                    && mScreenshotChordVolumeDownKeyConsumed) {
-                if (!down) {
-                    mScreenshotChordVolumeDownKeyConsumed = false;
-                }
-                return -1;
-            }
+        if (mKeyCombinationManager.isKeyConsumed(event)) {
+            return -1;
         }
 
-        // If an accessibility shortcut might be partially complete, hold off dispatching until we
-        // know if it is complete or not
-        if (mAccessibilityShortcutController.isAccessibilityShortcutAvailable(false)
-                && (flags & KeyEvent.FLAG_FALLBACK) == 0) {
-            if (mScreenshotChordVolumeDownKeyTriggered ^ mA11yShortcutChordVolumeUpKeyTriggered) {
-                final long now = SystemClock.uptimeMillis();
-                final long timeoutTime = (mScreenshotChordVolumeDownKeyTriggered
-                        ? mScreenshotChordVolumeDownKeyTime : mA11yShortcutChordVolumeUpKeyTime)
-                        + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS;
-                if (now < timeoutTime) {
-                    return timeoutTime - now;
-                }
-            }
-            if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN && mScreenshotChordVolumeDownKeyConsumed) {
-                if (!down) {
-                    mScreenshotChordVolumeDownKeyConsumed = false;
-                }
-                return -1;
-            }
-            if (keyCode == KeyEvent.KEYCODE_VOLUME_UP && mA11yShortcutChordVolumeUpKeyConsumed) {
-                if (!down) {
-                    mA11yShortcutChordVolumeUpKeyConsumed = false;
-                }
-                return -1;
-            }
-        }
-
-        // If a ringer toggle chord could be on the way but we're not sure, then tell the dispatcher
-        // to wait a little while and try again later before dispatching.
-        if (mRingerToggleChord != VOLUME_HUSH_OFF && (flags & KeyEvent.FLAG_FALLBACK) == 0) {
-            if (mA11yShortcutChordVolumeUpKeyTriggered && !mScreenshotChordPowerKeyTriggered) {
-                final long now = SystemClock.uptimeMillis();
-                final long timeoutTime = mA11yShortcutChordVolumeUpKeyTime
-                        + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS;
-                if (now < timeoutTime) {
-                    return timeoutTime - now;
-                }
-            }
-            if (keyCode == KeyEvent.KEYCODE_VOLUME_UP && mA11yShortcutChordVolumeUpKeyConsumed) {
-                if (!down) {
-                    mA11yShortcutChordVolumeUpKeyConsumed = false;
-                }
-                return -1;
+        if ((flags & KeyEvent.FLAG_FALLBACK) == 0) {
+            final long now = SystemClock.uptimeMillis();
+            final long interceptTimeout = mKeyCombinationManager.getKeyInterceptTimeout(keyCode);
+            if (now < interceptTimeout) {
+                return interceptTimeout - now;
             }
         }
 
@@ -2774,8 +2740,6 @@
         } else if (keyCode == KeyEvent.KEYCODE_TAB && event.isMetaPressed()) {
             // Pass through keyboard navigation keys.
             return 0;
-        } else if (mHasFeatureLeanback && interceptBugreportGestureTv(keyCode, down)) {
-            return -1;
         } else if (keyCode == KeyEvent.KEYCODE_ALL_APPS) {
             if (!down) {
                 mHandler.removeMessages(MSG_HANDLE_ALL_APPS);
@@ -2978,53 +2942,30 @@
     /**
      * TV only: recognizes a remote control gesture for capturing a bug report.
      */
-    private boolean interceptBugreportGestureTv(int keyCode, boolean down) {
+    private void interceptBugreportGestureTv() {
+        mHandler.removeMessages(MSG_BUGREPORT_TV);
         // The bugreport capture chord is a long press on DPAD CENTER and BACK simultaneously.
-        if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {
-            mBugreportTvKey1Pressed = down;
-        } else if (keyCode == KeyEvent.KEYCODE_BACK) {
-            mBugreportTvKey2Pressed = down;
-        }
+        Message msg = Message.obtain(mHandler, MSG_BUGREPORT_TV);
+        msg.setAsynchronous(true);
+        mHandler.sendMessageDelayed(msg, BUGREPORT_TV_GESTURE_TIMEOUT_MILLIS);
+    }
 
-        if (mBugreportTvKey1Pressed && mBugreportTvKey2Pressed) {
-            if (!mBugreportTvScheduled) {
-                mBugreportTvScheduled = true;
-                Message msg = Message.obtain(mHandler, MSG_BUGREPORT_TV);
-                msg.setAsynchronous(true);
-                mHandler.sendMessageDelayed(msg, BUGREPORT_TV_GESTURE_TIMEOUT_MILLIS);
-            }
-        } else if (mBugreportTvScheduled) {
-            mHandler.removeMessages(MSG_BUGREPORT_TV);
-            mBugreportTvScheduled = false;
-        }
-
-        return mBugreportTvScheduled;
+    private void cancelBugreportGestureTv() {
+        mHandler.removeMessages(MSG_BUGREPORT_TV);
     }
 
     /**
      * TV only: recognizes a remote control gesture as Accessibility shortcut.
      * Shortcut: Long press (BACK + DPAD_DOWN)
      */
-    private boolean interceptAccessibilityGestureTv(int keyCode, boolean down) {
-        if (keyCode == KeyEvent.KEYCODE_BACK) {
-            mAccessibilityTvKey1Pressed = down;
-        } else if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN) {
-            mAccessibilityTvKey2Pressed = down;
-        }
-
-        if (mAccessibilityTvKey1Pressed && mAccessibilityTvKey2Pressed) {
-            if (!mAccessibilityTvScheduled) {
-                mAccessibilityTvScheduled = true;
-                Message msg = Message.obtain(mHandler, MSG_ACCESSIBILITY_TV);
-                msg.setAsynchronous(true);
-                mHandler.sendMessageDelayed(msg, getAccessibilityShortcutTimeout());
-            }
-        } else if (mAccessibilityTvScheduled) {
-            mHandler.removeMessages(MSG_ACCESSIBILITY_TV);
-            mAccessibilityTvScheduled = false;
-        }
-
-        return mAccessibilityTvScheduled;
+    private void interceptAccessibilityGestureTv() {
+        mHandler.removeMessages(MSG_ACCESSIBILITY_TV);
+        Message msg = Message.obtain(mHandler, MSG_ACCESSIBILITY_TV);
+        msg.setAsynchronous(true);
+        mHandler.sendMessageDelayed(msg, getAccessibilityShortcutTimeout());
+    }
+    private void cancelAccessibilityGestureTv() {
+        mHandler.removeMessages(MSG_ACCESSIBILITY_TV);
     }
 
     private void requestBugreportForTv() {
@@ -3547,16 +3488,14 @@
         final int displayId = event.getDisplayId();
         final boolean isInjected = (policyFlags & WindowManagerPolicy.FLAG_INJECTED) != 0;
 
-        // If screen is off then we treat the case where the keyguard is open but hidden
-        // the same as if it were open and in front.
-        // This will prevent any keys other than the power button from waking the screen
-        // when the keyguard is hidden by another activity.
-        final boolean keyguardActive = (mKeyguardDelegate == null ? false :
-                                            (interactive ?
-                                                isKeyguardShowingAndNotOccluded() :
-                                                mKeyguardDelegate.isShowing()));
-
         if (DEBUG_INPUT) {
+            // If screen is off then we treat the case where the keyguard is open but hidden
+            // the same as if it were open and in front.
+            // This will prevent any keys other than the power button from waking the screen
+            // when the keyguard is hidden by another activity.
+            final boolean keyguardActive = (mKeyguardDelegate != null
+                    && (interactive ? isKeyguardShowingAndNotOccluded() :
+                    mKeyguardDelegate.isShowing()));
             Log.d(TAG, "interceptKeyTq keycode=" + keyCode
                     + " interactive=" + interactive + " keyguardActive=" + keyguardActive
                     + " policyFlags=" + Integer.toHexString(policyFlags));
@@ -3581,7 +3520,7 @@
                 // Reset the pending key
                 mPendingWakeKey = PENDING_KEY_NULL;
             }
-        } else if (!interactive && shouldDispatchInputWhenNonInteractive(displayId, keyCode)) {
+        } else if (shouldDispatchInputWhenNonInteractive(displayId, keyCode)) {
             // If we're currently dozing with the screen on and the keyguard showing, pass the key
             // to the application but preserve its wake key status to make sure we still move
             // from dozing to fully interactive if we would normally go from off to fully
@@ -3613,6 +3552,10 @@
             return result;
         }
 
+        if ((event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
+            mKeyCombinationManager.interceptKey(event, interactive);
+        }
+
         // Enable haptics if down and virtual key without multiple repetitions. If this is a hard
         // virtual key such as a navigation bar button, only vibrate if flag is enabled.
         final boolean isNavBarVirtKey = ((event.getFlags() & KeyEvent.FLAG_VIRTUAL_HARD_KEY) != 0);
@@ -3640,46 +3583,6 @@
             case KeyEvent.KEYCODE_VOLUME_DOWN:
             case KeyEvent.KEYCODE_VOLUME_UP:
             case KeyEvent.KEYCODE_VOLUME_MUTE: {
-                if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
-                    if (down) {
-                        // Any activity on the vol down button stops the ringer toggle shortcut
-                        cancelPendingRingerToggleChordAction();
-
-                        if (interactive && !mScreenshotChordVolumeDownKeyTriggered
-                                && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
-                            mScreenshotChordVolumeDownKeyTriggered = true;
-                            mScreenshotChordVolumeDownKeyTime = event.getDownTime();
-                            mScreenshotChordVolumeDownKeyConsumed = false;
-                            cancelPendingPowerKeyAction();
-                            interceptScreenshotChord();
-                            interceptAccessibilityShortcutChord();
-                        }
-                    } else {
-                        mScreenshotChordVolumeDownKeyTriggered = false;
-                        cancelPendingScreenshotChordAction();
-                        cancelPendingAccessibilityShortcutAction();
-                    }
-                } else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
-                    if (down) {
-                        if (interactive && !mA11yShortcutChordVolumeUpKeyTriggered
-                                && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
-                            mA11yShortcutChordVolumeUpKeyTriggered = true;
-                            mA11yShortcutChordVolumeUpKeyTime = event.getDownTime();
-                            mA11yShortcutChordVolumeUpKeyConsumed = false;
-                            cancelPendingPowerKeyAction();
-                            cancelPendingScreenshotChordAction();
-                            cancelPendingRingerToggleChordAction();
-
-                            interceptAccessibilityShortcutChord();
-                            interceptRingerToggleChord();
-                        }
-                    } else {
-                        mA11yShortcutChordVolumeUpKeyTriggered = false;
-                        cancelPendingScreenshotChordAction();
-                        cancelPendingAccessibilityShortcutAction();
-                        cancelPendingRingerToggleChordAction();
-                    }
-                }
                 if (down) {
                     sendSystemKeyToStatusBarAsync(event.getKeyCode());
 
@@ -3784,7 +3687,6 @@
                         KeyEvent.actionToString(event.getAction()),
                         mPowerKeyHandled ? 1 : 0, mPowerKeyPressCounter);
                 // Any activity on the power button stops the accessibility shortcut
-                cancelPendingAccessibilityShortcutAction();
                 result &= ~ACTION_PASS_TO_USER;
                 isWakeKey = false; // wake-up will be handled separately
                 if (down) {
@@ -3922,22 +3824,6 @@
             }
         }
 
-        // Intercept the Accessibility keychord for TV (DPAD_DOWN + Back) before the keyevent is
-        // processed through interceptKeyEventBeforeDispatch since Talkback may consume this event
-        // before it has a chance to reach that method.
-        if (mHasFeatureLeanback) {
-            switch (keyCode) {
-                case KeyEvent.KEYCODE_DPAD_DOWN:
-                case KeyEvent.KEYCODE_BACK: {
-                    boolean handled = interceptAccessibilityGestureTv(keyCode, down);
-                    if (handled) {
-                        result &= ~ACTION_PASS_TO_USER;
-                    }
-                    break;
-                }
-            }
-        }
-
         // Intercept the Accessibility keychord (CTRL + ALT + Z) for keyboard users.
         if (mAccessibilityShortcutController.isAccessibilityShortcutAvailable(isKeyguardLocked())) {
             switch (keyCode) {
@@ -5388,14 +5274,6 @@
                 pw.print(!mAllowLockscreenWhenOnDisplays.isEmpty());
                 pw.print(" mLockScreenTimeout="); pw.print(mLockScreenTimeout);
                 pw.print(" mLockScreenTimerActive="); pw.println(mLockScreenTimerActive);
-        if (mHasFeatureLeanback) {
-            pw.print(prefix);
-            pw.print("mAccessibilityTvKey1Pressed="); pw.println(mAccessibilityTvKey1Pressed);
-            pw.print(prefix);
-            pw.print("mAccessibilityTvKey2Pressed="); pw.println(mAccessibilityTvKey2Pressed);
-            pw.print(prefix);
-            pw.print("mAccessibilityTvScheduled="); pw.println(mAccessibilityTvScheduled);
-        }
 
         mGlobalKeyManager.dump(prefix, pw);
 
diff --git a/services/core/java/com/android/server/power/batterysaver/BatterySaverController.java b/services/core/java/com/android/server/power/batterysaver/BatterySaverController.java
index 68d038b..16f5069 100644
--- a/services/core/java/com/android/server/power/batterysaver/BatterySaverController.java
+++ b/services/core/java/com/android/server/power/batterysaver/BatterySaverController.java
@@ -113,11 +113,6 @@
     private boolean mIsInteractive;
 
     /**
-     * Read-only list of plugins. No need for synchronization.
-     */
-    private final Plugin[] mPlugins;
-
-    /**
      * Package name that will receive an explicit manifest broadcast for
      * {@link PowerManager#ACTION_POWER_SAVE_MODE_CHANGED}. It's {@code null} if it hasn't been
      * retrieved yet.
@@ -172,15 +167,6 @@
         }
     }
 
-    /**
-     * Plugin interface. All methods are guaranteed to be called on the same (handler) thread.
-     */
-    public interface Plugin {
-        void onSystemReady(BatterySaverController caller);
-
-        void onBatterySaverChanged(BatterySaverController caller);
-    }
-
     private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
@@ -194,6 +180,7 @@
                         updateBatterySavingStats();
                         return; // No need to send it if not enabled.
                     }
+                    // We currently evaluate state only for CPU frequency changes.
                     // Don't send the broadcast, because we never did so in this case.
                     mHandler.postStateChanged(/*sendBroadcast=*/ false,
                             REASON_INTERACTIVE_CHANGED);
@@ -224,9 +211,6 @@
         mFileUpdater = new FileUpdater(context);
         mBatterySavingStats = batterySavingStats;
 
-        // TODO(79580230): remove plugin code and maybe screen on/off listeners?
-        // Initialize plugins.
-        mPlugins = new Plugin[0];
         PowerManager.invalidatePowerSaveModeCaches();
     }
 
@@ -300,12 +284,6 @@
                             msg.arg1 == ARG_SEND_BROADCAST,
                             msg.arg2);
                     break;
-
-                case MSG_SYSTEM_READY:
-                    for (Plugin p : mPlugins) {
-                        p.onSystemReady(BatterySaverController.this);
-                    }
-                    break;
             }
         }
     }
@@ -479,10 +457,6 @@
             mFileUpdater.writeFiles(fileValues);
         }
 
-        for (Plugin p : mPlugins) {
-            p.onBatterySaverChanged(this);
-        }
-
         if (sendBroadcast) {
 
             if (DEBUG) {
diff --git a/services/core/java/com/android/server/powerstats/OWNERS b/services/core/java/com/android/server/powerstats/OWNERS
new file mode 100644
index 0000000..d68066b
--- /dev/null
+++ b/services/core/java/com/android/server/powerstats/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/power/OWNERS
diff --git a/services/core/java/com/android/server/role/RoleManagerService.java b/services/core/java/com/android/server/role/RoleManagerService.java
index 3d91a85..caa275d 100644
--- a/services/core/java/com/android/server/role/RoleManagerService.java
+++ b/services/core/java/com/android/server/role/RoleManagerService.java
@@ -34,7 +34,6 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
-import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.PackageManagerInternal;
 import android.content.pm.Signature;
@@ -71,7 +70,6 @@
 import com.android.server.LocalServices;
 import com.android.server.SystemService;
 import com.android.server.pm.UserManagerInternal;
-import com.android.server.pm.permission.PermissionManagerServiceInternal;
 
 import java.io.ByteArrayOutputStream;
 import java.io.FileDescriptor;
@@ -709,12 +707,6 @@
                     Slog.e(LOG_TAG, "Exception while setting default browser: " + packageName, e);
                     return false;
                 }
-
-                if (packageName != null) {
-                    final PermissionManagerServiceInternal permissionManager =
-                            LocalServices.getService(PermissionManagerServiceInternal.class);
-                    permissionManager.grantDefaultPermissionsToDefaultBrowser(packageName, userId);
-                }
             } finally {
                 Binder.restoreCallingIdentity(identity);
             }
@@ -761,18 +753,6 @@
 
             dumpOutputStream.flush();
         }
-
-        private int getUidForPackage(String packageName) {
-            final long ident = Binder.clearCallingIdentity();
-            try {
-                return getContext().getPackageManager().getApplicationInfo(packageName,
-                        PackageManager.MATCH_ANY_USER).uid;
-            } catch (NameNotFoundException nnfe) {
-                return -1;
-            } finally {
-                Binder.restoreCallingIdentity(ident);
-            }
-        }
     }
 
     private class Internal extends RoleManagerInternal {
diff --git a/services/core/java/com/android/server/rollback/OWNERS b/services/core/java/com/android/server/rollback/OWNERS
new file mode 100644
index 0000000..7feb85f
--- /dev/null
+++ b/services/core/java/com/android/server/rollback/OWNERS
@@ -0,0 +1 @@
[email protected]
diff --git a/services/core/java/com/android/server/slice/OWNERS b/services/core/java/com/android/server/slice/OWNERS
new file mode 100644
index 0000000..3d0859f
--- /dev/null
+++ b/services/core/java/com/android/server/slice/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/app/slice/OWNERS
diff --git a/services/core/java/com/android/server/slice/SliceManagerService.java b/services/core/java/com/android/server/slice/SliceManagerService.java
index ee9694f..ee0e5ba 100644
--- a/services/core/java/com/android/server/slice/SliceManagerService.java
+++ b/services/core/java/com/android/server/slice/SliceManagerService.java
@@ -256,11 +256,6 @@
                 }
             }
         }
-        // Fallback to allowing uri permissions through.
-        if (mContext.checkUriPermission(uri, pid, uid, Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
-                == PERMISSION_GRANTED) {
-            return PackageManager.PERMISSION_GRANTED;
-        }
         return PackageManager.PERMISSION_DENIED;
     }
 
diff --git a/services/core/java/com/android/server/statusbar/OWNERS b/services/core/java/com/android/server/statusbar/OWNERS
new file mode 100644
index 0000000..2e96c97
--- /dev/null
+++ b/services/core/java/com/android/server/statusbar/OWNERS
@@ -0,0 +1 @@
+include /packages/SystemUI/OWNERS
diff --git a/services/core/java/com/android/server/storage/OWNERS b/services/core/java/com/android/server/storage/OWNERS
new file mode 100644
index 0000000..6f9dbea
--- /dev/null
+++ b/services/core/java/com/android/server/storage/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/os/storage/OWNERS
diff --git a/services/core/java/com/android/server/telecom/TelecomLoaderService.java b/services/core/java/com/android/server/telecom/TelecomLoaderService.java
index 52ad893..f0c96e1 100644
--- a/services/core/java/com/android/server/telecom/TelecomLoaderService.java
+++ b/services/core/java/com/android/server/telecom/TelecomLoaderService.java
@@ -42,7 +42,7 @@
 import com.android.server.LocalServices;
 import com.android.server.SystemService;
 import com.android.server.pm.UserManagerService;
-import com.android.server.pm.permission.PermissionManagerServiceInternal;
+import com.android.server.pm.permission.LegacyPermissionManagerInternal;
 
 /**
  * Starts the telecom component by binding to its ITelecomService implementation. Telecom is setup
@@ -65,8 +65,8 @@
                 ServiceManager.addService(Context.TELECOM_SERVICE, telecomService.asBinder());
 
                 synchronized (mLock) {
-                    final PermissionManagerServiceInternal permissionManager =
-                            LocalServices.getService(PermissionManagerServiceInternal.class);
+                    final LegacyPermissionManagerInternal permissionManager =
+                            LocalServices.getService(LegacyPermissionManagerInternal.class);
                     if (mDefaultSimCallManagerRequests != null) {
                         if (mDefaultSimCallManagerRequests != null) {
                             TelecomManager telecomManager =
@@ -165,8 +165,8 @@
 
 
     private void registerDefaultAppProviders() {
-        final PermissionManagerServiceInternal permissionManager =
-                LocalServices.getService(PermissionManagerServiceInternal.class);
+        final LegacyPermissionManagerInternal permissionManager =
+                LocalServices.getService(LegacyPermissionManagerInternal.class);
 
         // Set a callback for the permission grant policy to query the default sms app.
         permissionManager.setSmsAppPackagesProvider(userId -> {
@@ -244,15 +244,16 @@
     }
 
     private void updateSimCallManagerPermissions(int userId) {
-        final PermissionManagerServiceInternal permissionManager =
-                LocalServices.getService(PermissionManagerServiceInternal.class);
+        final LegacyPermissionManagerInternal permissionManager =
+                LocalServices.getService(LegacyPermissionManagerInternal.class);
         TelecomManager telecomManager =
             (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE);
         PhoneAccountHandle phoneAccount = telecomManager.getSimCallManager(userId);
         if (phoneAccount != null) {
             Slog.i(TAG, "updating sim call manager permissions for userId:" + userId);
             String packageName = phoneAccount.getComponentName().getPackageName();
-            permissionManager.grantDefaultPermissionsToDefaultSimCallManager(packageName, userId);
+            permissionManager.grantDefaultPermissionsToDefaultSimCallManager(packageName,
+                    userId);
         }
     }
 }
diff --git a/services/core/java/com/android/server/textclassifier/OWNERS b/services/core/java/com/android/server/textclassifier/OWNERS
new file mode 100644
index 0000000..46b3cb8
--- /dev/null
+++ b/services/core/java/com/android/server/textclassifier/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/service/textclassifier/OWNERS
diff --git a/services/core/java/com/android/server/timedetector/OWNERS b/services/core/java/com/android/server/timedetector/OWNERS
new file mode 100644
index 0000000..09447a97
--- /dev/null
+++ b/services/core/java/com/android/server/timedetector/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/app/timezone/OWNERS
diff --git a/services/core/java/com/android/server/timezone/OWNERS b/services/core/java/com/android/server/timezone/OWNERS
new file mode 100644
index 0000000..09447a97
--- /dev/null
+++ b/services/core/java/com/android/server/timezone/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/app/timezone/OWNERS
diff --git a/services/core/java/com/android/server/timezonedetector/OWNERS b/services/core/java/com/android/server/timezonedetector/OWNERS
new file mode 100644
index 0000000..09447a97
--- /dev/null
+++ b/services/core/java/com/android/server/timezonedetector/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/app/timezone/OWNERS
diff --git a/services/core/java/com/android/server/trust/OWNERS b/services/core/java/com/android/server/trust/OWNERS
new file mode 100644
index 0000000..b039c4b
--- /dev/null
+++ b/services/core/java/com/android/server/trust/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/app/trust/OWNERS
diff --git a/services/core/java/com/android/server/tv/OWNERS b/services/core/java/com/android/server/tv/OWNERS
new file mode 100644
index 0000000..305027c
--- /dev/null
+++ b/services/core/java/com/android/server/tv/OWNERS
@@ -0,0 +1 @@
+include /media/java/android/media/tv/OWNERS
diff --git a/services/core/java/com/android/server/uri/OWNERS b/services/core/java/com/android/server/uri/OWNERS
new file mode 100644
index 0000000..cdc07ed
--- /dev/null
+++ b/services/core/java/com/android/server/uri/OWNERS
@@ -0,0 +1,3 @@
[email protected]
[email protected]
[email protected]
diff --git a/services/core/java/com/android/server/vibrator/OWNERS b/services/core/java/com/android/server/vibrator/OWNERS
new file mode 100644
index 0000000..7e7335d
--- /dev/null
+++ b/services/core/java/com/android/server/vibrator/OWNERS
@@ -0,0 +1 @@
[email protected]
diff --git a/services/core/java/com/android/server/wallpaper/OWNERS b/services/core/java/com/android/server/wallpaper/OWNERS
new file mode 100644
index 0000000..8ff0f74
--- /dev/null
+++ b/services/core/java/com/android/server/wallpaper/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/service/wallpaper/OWNERS
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index e88f8e3..0678a5e 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -2298,10 +2298,6 @@
                             .setSubtype(getConfiguration().orientation)
                             .addTaggedData(MetricsEvent.FIELD_DISPLAY_ID, getDisplayId()));
         }
-
-        if (mPinnedStackControllerLocked != null) {
-            mPinnedStackControllerLocked.onDisplayInfoChanged(getDisplayInfo());
-        }
     }
 
     /**
diff --git a/services/core/java/com/android/server/wm/PinnedStackController.java b/services/core/java/com/android/server/wm/PinnedStackController.java
index fd42b24..8fe2481 100644
--- a/services/core/java/com/android/server/wm/PinnedStackController.java
+++ b/services/core/java/com/android/server/wm/PinnedStackController.java
@@ -127,7 +127,6 @@
         try {
             listener.asBinder().linkToDeath(mPinnedStackListenerDeathHandler, 0);
             mPinnedStackListener = listener;
-            notifyDisplayInfoChanged(mDisplayInfo);
             notifyImeVisibilityChanged(mIsImeShowing, mImeHeight);
             notifyMovementBoundsChanged(false /* fromImeAdjustment */);
             notifyActionsChanged(mActions);
@@ -171,23 +170,6 @@
         }
     }
 
-    private void setDisplayInfo(DisplayInfo displayInfo) {
-        mDisplayInfo.copyFrom(displayInfo);
-        notifyDisplayInfoChanged(mDisplayInfo);
-    }
-
-    /**
-     * In the case where the display rotation is changed but there is no stack, we can't depend on
-     * onTaskStackBoundsChanged() to be called.  But we still should update our known display info
-     * with the new state so that we can update SystemUI.
-     */
-    void onDisplayInfoChanged(DisplayInfo displayInfo) {
-        synchronized (mService.mGlobalLock) {
-            setDisplayInfo(displayInfo);
-            notifyMovementBoundsChanged(false /* fromImeAdjustment */);
-        }
-    }
-
     /**
      * Sets the Ime state and height.
      */
@@ -288,18 +270,6 @@
         }
     }
 
-    /**
-     * Notifies listeners that the PIP animation is about to happen.
-     */
-    private void notifyDisplayInfoChanged(DisplayInfo displayInfo) {
-        if (mPinnedStackListener == null) return;
-        try {
-            mPinnedStackListener.onDisplayInfoChanged(displayInfo);
-        } catch (RemoteException e) {
-            Slog.e(TAG_WM, "Error delivering DisplayInfo changed event.", e);
-        }
-    }
-
     void dump(String prefix, PrintWriter pw) {
         pw.println(prefix + "PinnedStackController");
         pw.println(prefix + "  mIsImeShowing=" + mIsImeShowing);
diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java
index 5da668c..16c7226 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimationController.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java
@@ -850,7 +850,7 @@
         return w != null && w.mAttrs.type == TYPE_BASE_APPLICATION &&
                 ((w.mActivityRecord != null && mTargetActivityRecord == w.mActivityRecord)
                         || isAnimatingTask(w.getTask()))
-                && isTargetOverWallpaper();
+                && isTargetOverWallpaper() && w.isOnScreen();
     }
 
     /**
diff --git a/services/core/java/com/android/server/wm/SurfaceAnimator.java b/services/core/java/com/android/server/wm/SurfaceAnimator.java
index 7df2b40..6e0efbf 100644
--- a/services/core/java/com/android/server/wm/SurfaceAnimator.java
+++ b/services/core/java/com/android/server/wm/SurfaceAnimator.java
@@ -26,7 +26,6 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.util.DebugUtils;
 import android.util.Slog;
 import android.util.proto.ProtoOutputStream;
 import android.view.SurfaceControl;
@@ -388,7 +387,7 @@
         if (DEBUG_ANIM) Slog.i(TAG, "Reparenting to leash");
         final SurfaceControl.Builder builder = animatable.makeAnimationLeash()
                 .setParent(animatable.getAnimationLeashParent())
-                .setName(surface + " - animation-leash")
+                .setName(surface + " - animation-leash of " + animationTypeToString(type))
                 // TODO(b/151665759) Defer reparent calls
                 // We want the leash to be visible immediately because the transaction which shows
                 // the leash may be deferred but the reparent will not. This will cause the leashed
@@ -430,8 +429,7 @@
 
     void dump(PrintWriter pw, String prefix) {
         pw.print(prefix); pw.print("mLeash="); pw.print(mLeash);
-        pw.print(" mAnimationType=" + DebugUtils.valueToString(SurfaceAnimator.class,
-                "ANIMATION_TYPE_", mAnimationType));
+        pw.print(" mAnimationType=" + animationTypeToString(mAnimationType));
         pw.println(mAnimationStartDelayed ? " mAnimationStartDelayed=true" : "");
         pw.print(prefix); pw.print("Animation: "); pw.println(mAnimation);
         if (mAnimation != null) {
@@ -513,6 +511,23 @@
     @interface AnimationType {}
 
     /**
+     * Converts {@link AnimationType} to String.
+     */
+    private static String animationTypeToString(@AnimationType int type) {
+        switch (type) {
+            case ANIMATION_TYPE_NONE: return "none";
+            case ANIMATION_TYPE_APP_TRANSITION: return "app_transition";
+            case ANIMATION_TYPE_SCREEN_ROTATION: return "screen_rotation";
+            case ANIMATION_TYPE_DIMMER: return "dimmer";
+            case ANIMATION_TYPE_RECENTS: return "recents_animation";
+            case ANIMATION_TYPE_WINDOW_ANIMATION: return "window_animation";
+            case ANIMATION_TYPE_INSETS_CONTROL: return "insets_animation";
+            case ANIMATION_TYPE_FIXED_TRANSFORM: return "fixed_rotation";
+            default: return "unknown type:" + type;
+        }
+    }
+
+    /**
      * Callback to be passed into {@link AnimationAdapter#startAnimation} to be invoked by the
      * component that is running the animation when the animation is finished.
      */
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 4b65ce0f..00f545c 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -224,7 +224,6 @@
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
-import org.xmlpull.v1.XmlSerializer;
 
 import java.io.FileDescriptor;
 import java.io.IOException;
@@ -4108,7 +4107,7 @@
         if (top == null) return null;
         final ActivityRecord rootActivity = top.getRootActivity();
         return (rootActivity == null || rootActivity.pictureInPictureArgs.empty())
-                ? null : rootActivity.pictureInPictureArgs;
+                ? null : new PictureInPictureParams(rootActivity.pictureInPictureArgs);
     }
 
     void maybeUpdateLetterboxBounds(
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotController.java b/services/core/java/com/android/server/wm/TaskSnapshotController.java
index 616a789..b2f3062 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotController.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotController.java
@@ -369,7 +369,8 @@
         SurfaceControl[] excludeLayers;
         final WindowState imeWindow = task.getDisplayContent().mInputMethodWindow;
         // Exclude IME window snapshot when IME isn't proper to attach to app.
-        if (imeWindow != null && !task.getDisplayContent().isImeAttachedToApp()) {
+        if (imeWindow != null && imeWindow.getSurfaceControl() != null
+                && !task.getDisplayContent().isImeAttachedToApp()) {
             excludeLayers = new SurfaceControl[1];
             excludeLayers[0] = imeWindow.getSurfaceControl();
         } else {
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index c318fad..bc8699e 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -770,6 +770,9 @@
             }
             mPendingSeamlessRotate = new SeamlessRotator(oldRotation, rotation, getDisplayInfo(),
                     false /* applyFixedTransformationHint */);
+            // The surface position is going to be unrotated according to the last position.
+            // Make sure the source position is up-to-date.
+            mLastSurfacePosition.set(mSurfacePosition.x, mSurfacePosition.y);
             mPendingSeamlessRotate.unrotate(transaction, this);
             getDisplayContent().getDisplayRotation().markForSeamlessRotation(this,
                     true /* seamlesslyRotated */);
diff --git a/services/core/jni/OWNERS b/services/core/jni/OWNERS
index 6f74885..7fc5565 100644
--- a/services/core/jni/OWNERS
+++ b/services/core/jni/OWNERS
@@ -12,3 +12,18 @@
 per-file com_android_server_HardwarePropertiesManagerService.cpp = [email protected], [email protected]
 per-file com_android_server_power_PowerManagerService.* = [email protected], [email protected]
 
+per-file Android.bp = file:platform/build/soong:/OWNERS
+per-file com_android_server_Usb* = file:/services/usb/OWNERS
+per-file com_android_server_Vibrator* = file:/services/core/java/com/android/server/vibrator/OWNERS
+per-file com_android_server_hdmi_* = file:/core/java/android/hardware/hdmi/OWNERS
+per-file com_android_server_input_* = file:/core/java/android/hardware/input/OWNERS
+per-file com_android_server_lights_* = file:/services/core/java/com/android/server/lights/OWNERS
+per-file com_android_server_location_* = file:/location/java/android/location/OWNERS
+per-file com_android_server_locksettings_* = file:/services/core/java/com/android/server/locksettings/OWNERS
+per-file com_android_server_net_* = file:/services/core/java/com/android/server/net/OWNERS
+per-file com_android_server_pm_* = file:/services/core/java/com/android/server/pm/OWNERS
+per-file com_android_server_power_* = file:/services/core/java/com/android/server/power/OWNERS
+per-file com_android_server_se_* = file:/core/java/android/se/OWNERS
+per-file com_android_server_security_* = file:/core/java/android/security/OWNERS
+per-file com_android_server_tv_* = file:/media/java/android/media/tv/OWNERS
+per-file com_android_server_vibrator_* = file:/services/core/java/com/android/server/vibrator/OWNERS
diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp
index 13450be..404b182 100644
--- a/services/core/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/core/jni/com_android_server_input_InputManagerService.cpp
@@ -149,6 +149,14 @@
     jmethodID getAffineTransform;
 } gTouchCalibrationClassInfo;
 
+static struct {
+    jclass clazz;
+    jmethodID constructor;
+    jmethodID keyAt;
+    jmethodID valueAt;
+    jmethodID size;
+} gSparseArrayClassInfo;
+
 // --- Global functions ---
 
 template<typename T>
@@ -1705,19 +1713,73 @@
             patternObj, nullptr));
     jint* amplitudes = static_cast<jint*>(env->GetPrimitiveArrayCritical(amplitudesObj, nullptr));
 
-    std::vector<VibrationElement> elements(patternSize);
+    VibrationSequence sequence(patternSize);
+    std::vector<int32_t> vibrators = im->getInputManager()->getReader()->getVibratorIds(deviceId);
     for (size_t i = 0; i < patternSize; i++) {
         // VibrationEffect.validate guarantees duration > 0.
         std::chrono::milliseconds duration(patternMillis[i]);
-        elements[i].duration = std::min(duration, MAX_VIBRATE_PATTERN_DELAY_MILLIS);
-        // TODO: (b/161629089) apply channel specific amplitudes from development API.
-        elements[i].channels = {static_cast<uint8_t>(amplitudes[i]),
-                                static_cast<uint8_t>(amplitudes[i])};
+        VibrationElement element(CHANNEL_SIZE);
+        element.duration = std::min(duration, MAX_VIBRATE_PATTERN_DELAY_MILLIS);
+        // Vibrate on both channels
+        for (int32_t channel = 0; channel < vibrators.size(); channel++) {
+            element.addChannel(vibrators[channel], static_cast<uint8_t>(amplitudes[i]));
+        }
+        sequence.addElement(element);
     }
     env->ReleasePrimitiveArrayCritical(patternObj, patternMillis, JNI_ABORT);
     env->ReleasePrimitiveArrayCritical(amplitudesObj, amplitudes, JNI_ABORT);
 
-    im->getInputManager()->getReader()->vibrate(deviceId, elements, repeat, token);
+    im->getInputManager()->getReader()->vibrate(deviceId, sequence, repeat, token);
+}
+
+static void nativeVibrateCombined(JNIEnv* env, jclass /* clazz */, jlong ptr, jint deviceId,
+                                  jlongArray patternObj, jobject amplitudesObj, jint repeat,
+                                  jint token) {
+    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
+
+    size_t patternSize = env->GetArrayLength(patternObj);
+
+    if (patternSize > MAX_VIBRATE_PATTERN_SIZE) {
+        ALOGI("Skipped requested vibration because the pattern size is %zu "
+              "which is more than the maximum supported size of %d.",
+              patternSize, MAX_VIBRATE_PATTERN_SIZE);
+        return; // limit to reasonable size
+    }
+    const jlong* patternMillis = env->GetLongArrayElements(patternObj, nullptr);
+
+    std::array<jint*, CHANNEL_SIZE> amplitudesArray;
+    std::array<jint, CHANNEL_SIZE> vibratorIdArray;
+    jint amplSize = env->CallIntMethod(amplitudesObj, gSparseArrayClassInfo.size);
+    if (amplSize > CHANNEL_SIZE) {
+        ALOGE("Can not fit into input device vibration element.");
+        return;
+    }
+
+    for (int i = 0; i < amplSize; i++) {
+        vibratorIdArray[i] = env->CallIntMethod(amplitudesObj, gSparseArrayClassInfo.keyAt, i);
+        jintArray arr = static_cast<jintArray>(
+                env->CallObjectMethod(amplitudesObj, gSparseArrayClassInfo.valueAt, i));
+        amplitudesArray[i] = env->GetIntArrayElements(arr, nullptr);
+        if (env->GetArrayLength(arr) != patternSize) {
+            ALOGE("Amplitude length not equal to pattern length!");
+            return;
+        }
+    }
+
+    VibrationSequence sequence(patternSize);
+    for (size_t i = 0; i < patternSize; i++) {
+        VibrationElement element(CHANNEL_SIZE);
+        // VibrationEffect.validate guarantees duration > 0.
+        std::chrono::milliseconds duration(patternMillis[i]);
+        element.duration = std::min(duration, MAX_VIBRATE_PATTERN_DELAY_MILLIS);
+        for (int32_t channel = 0; channel < CHANNEL_SIZE; channel++) {
+            element.addChannel(vibratorIdArray[channel],
+                               static_cast<uint8_t>(amplitudesArray[channel][i]));
+        }
+        sequence.addElement(element);
+    }
+
+    im->getInputManager()->getReader()->vibrate(deviceId, sequence, repeat, token);
 }
 
 static void nativeCancelVibrate(JNIEnv* /* env */,
@@ -1727,6 +1789,23 @@
     im->getInputManager()->getReader()->cancelVibrate(deviceId, token);
 }
 
+static bool nativeIsVibrating(JNIEnv* /* env */, jclass /* clazz */, jlong ptr, jint deviceId) {
+    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
+
+    return im->getInputManager()->getReader()->isVibrating(deviceId);
+}
+
+static jintArray nativeGetVibratorIds(JNIEnv* env, jclass clazz, jlong ptr, jint deviceId) {
+    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
+    std::vector<int32_t> vibrators = im->getInputManager()->getReader()->getVibratorIds(deviceId);
+
+    jintArray vibIdArray = env->NewIntArray(vibrators.size());
+    if (vibIdArray != nullptr) {
+        env->SetIntArrayRegion(vibIdArray, 0, vibrators.size(), vibrators.data());
+    }
+    return vibIdArray;
+}
+
 static void nativeReloadKeyboardLayouts(JNIEnv* /* env */,
         jclass /* clazz */, jlong ptr) {
     NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
@@ -1872,7 +1951,11 @@
         {"nativeSetInteractive", "(JZ)V", (void*)nativeSetInteractive},
         {"nativeReloadCalibration", "(J)V", (void*)nativeReloadCalibration},
         {"nativeVibrate", "(JI[J[III)V", (void*)nativeVibrate},
+        {"nativeVibrateCombined", "(JI[JLandroid/util/SparseArray;II)V",
+         (void*)nativeVibrateCombined},
         {"nativeCancelVibrate", "(JII)V", (void*)nativeCancelVibrate},
+        {"nativeIsVibrating", "(JI)Z", (void*)nativeIsVibrating},
+        {"nativeGetVibratorIds", "(JI)[I", (void*)nativeGetVibratorIds},
         {"nativeReloadKeyboardLayouts", "(J)V", (void*)nativeReloadKeyboardLayouts},
         {"nativeReloadDeviceAliases", "(J)V", (void*)nativeReloadDeviceAliases},
         {"nativeDump", "(J)Ljava/lang/String;", (void*)nativeDump},
@@ -2048,6 +2131,15 @@
     GET_METHOD_ID(gTouchCalibrationClassInfo.getAffineTransform, gTouchCalibrationClassInfo.clazz,
             "getAffineTransform", "()[F");
 
+    // SparseArray
+    FIND_CLASS(gSparseArrayClassInfo.clazz, "android/util/SparseArray");
+    gSparseArrayClassInfo.clazz = jclass(env->NewGlobalRef(gSparseArrayClassInfo.clazz));
+    GET_METHOD_ID(gSparseArrayClassInfo.constructor, gSparseArrayClassInfo.clazz, "<init>", "()V");
+    GET_METHOD_ID(gSparseArrayClassInfo.keyAt, gSparseArrayClassInfo.clazz, "keyAt", "(I)I");
+    GET_METHOD_ID(gSparseArrayClassInfo.valueAt, gSparseArrayClassInfo.clazz, "valueAt",
+                  "(I)Ljava/lang/Object;");
+    GET_METHOD_ID(gSparseArrayClassInfo.size, gSparseArrayClassInfo.clazz, "size", "()I");
+
     return 0;
 }
 
diff --git a/services/core/jni/gnss/OWNERS b/services/core/jni/gnss/OWNERS
new file mode 100644
index 0000000..5ac60284
--- /dev/null
+++ b/services/core/jni/gnss/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/location/OWNERS
diff --git a/services/core/xsd/platform-compat-schema/OWNERS b/services/core/xsd/platform-compat-schema/OWNERS
new file mode 100644
index 0000000..f8c3520
--- /dev/null
+++ b/services/core/xsd/platform-compat-schema/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/compat/OWNERS
diff --git a/services/devicepolicy/OWNERS b/services/devicepolicy/OWNERS
new file mode 100644
index 0000000..e95633a
--- /dev/null
+++ b/services/devicepolicy/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/app/admin/OWNERS
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java b/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java
index ce61d50..22976c30 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java
@@ -22,6 +22,8 @@
 
 import com.android.server.SystemService;
 
+import java.util.List;
+
 /**
  * Defines the required interface for IDevicePolicyManager implemenation.
  *
@@ -101,4 +103,9 @@
     public boolean canProfileOwnerResetPasswordWhenLocked(int userId) {
         return false;
     }
+
+    public List<String> getKeyPairGrants(String callerPackage, String alias) {
+        // STOPSHIP: implement delegation code in ArcDevicePolicyManagerWrapperService & nuke this.
+        return null;
+    }
 }
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 6f22f113..6d2cb9c 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -1017,10 +1017,8 @@
         return mSafetyChecker == null || mSafetyChecker.isDevicePolicyOperationSafe(operation);
     }
 
-    /**
-     * Used by {@code cmd device_policy} to set the result of the next safety operation check.
-     */
-    void setNextOperationSafety(@DevicePolicyOperation int operation, boolean safe) {
+    @Override
+    public void setNextOperationSafety(@DevicePolicyOperation int operation, boolean safe) {
         Preconditions.checkCallAuthorization(
                 hasCallingOrSelfPermission(permission.MANAGE_DEVICE_ADMINS));
         Slog.i(LOG_TAG, "setNextOperationSafety(" + DevicePolicyManager.operationToString(operation)
@@ -2330,7 +2328,8 @@
                     + admin.info.getTagForPolicy(reqPolicy));
         } else {
             throw new SecurityException("No active admin owned by uid "
-                    + callingUid + " for policy #" + reqPolicy);
+                    + callingUid + " for policy #" + reqPolicy + (permission == null ? ""
+                    : ", which doesn't have " + permission));
         }
     }
 
@@ -2390,6 +2389,7 @@
      * If not provided, iterate over all of the active admins in the DevicePolicyData for that user
      * and return the one with the uid specified as parameter, and has the policy specified.
      */
+    @Nullable
     private ActiveAdmin getActiveAdminWithPolicyForUidLocked(ComponentName who, int reqPolicy,
             int uid) {
         ensureLocked();
@@ -5192,6 +5192,44 @@
         return false;
     }
 
+    @Override
+    public List<String> getKeyPairGrants(String callerPackage, String alias) {
+        final CallerIdentity caller = getCallerIdentity(callerPackage);
+        Preconditions.checkCallAuthorization(canManageCertificates(caller));
+
+        return mInjector.binderWithCleanCallingIdentity(() -> {
+            try (KeyChainConnection keyChainConnection =
+                         KeyChain.bindAsUser(mContext, caller.getUserHandle())) {
+                final List<String> result = new ArrayList<>();
+                final int[] granteeUids = keyChainConnection.getService().getGrants(alias);
+                final PackageManager pm = mInjector.getPackageManager(caller.getUserId());
+
+                // TODO: Return Set<Set<String>> when AIDL supports it: b/136048684
+                // Public API returns a set of sets, where each internal set contains all package
+                // names corresponding to the same UID. For now a set of sets is marshalled as a
+                // null-separated list.
+                for (final int uid : granteeUids) {
+                    final String[] packages = pm.getPackagesForUid(uid);
+                    if (packages == null) {
+                        Slog.wtf(LOG_TAG, "No packages found for uid " + uid);
+                        continue;
+                    }
+                    if (!result.isEmpty()) {
+                        result.add(null);
+                    }
+                    result.addAll(Arrays.asList(packages));
+                }
+                return result;
+            } catch (RemoteException e) {
+                Log.e(LOG_TAG, "Querying keypair grants", e);
+            } catch (InterruptedException e) {
+                Log.w(LOG_TAG, "Interrupted while querying keypair grants", e);
+                Thread.currentThread().interrupt();
+            }
+            return Collections.emptyList();
+        });
+    }
+
     /**
      * Enforce one the following conditions are met:
      * (1) The device has a Device Owner, and one of the following holds:
@@ -6098,10 +6136,14 @@
 
         final ActiveAdmin admin;
         synchronized (getLockObject()) {
-            admin = getActiveAdminForCallerLocked(null, DeviceAdminInfo.USES_POLICY_WIPE_DATA);
+            admin = getActiveAdminWithPolicyForUidLocked(/* who= */ null,
+                    DeviceAdminInfo.USES_POLICY_WIPE_DATA, caller.getUid());
         }
-        Preconditions.checkCallAuthorization(admin != null,
-                "No active admin for user %d", caller.getUserId());
+
+        Preconditions.checkCallAuthorization(
+                (admin != null) || hasCallingOrSelfPermission(permission.MASTER_CLEAR),
+                "No active admin for user %d and caller %d does not hold MASTER_CLEAR permission",
+                caller.getUserId(), caller.getUid());
 
         if (TextUtils.isEmpty(wipeReasonForUser)) {
             if (calledByProfileOwnerOnOrgOwnedDevice && !calledOnParentInstance) {
@@ -6112,7 +6154,10 @@
             }
         }
 
-        int userId = admin.getUserHandle().getIdentifier();
+        int userId = admin != null ? admin.getUserHandle().getIdentifier()
+                : caller.getUserId();
+        Slog.i(LOG_TAG, String.format("wipeDataWithReason(%s): admin=%s, user=%d",
+                wipeReasonForUser, admin, userId));
         if (calledByProfileOwnerOnOrgOwnedDevice) {
             // When wipeData is called on the parent instance, it implies wiping the entire device.
             if (calledOnParentInstance) {
@@ -6135,20 +6180,35 @@
                 });
             }
         }
-
-        DevicePolicyEventLogger
+        DevicePolicyEventLogger event = DevicePolicyEventLogger
                 .createEvent(DevicePolicyEnums.WIPE_DATA_WITH_REASON)
-                .setAdmin(admin.info.getComponent())
                 .setInt(flags)
                 .setStrings(calledOnParentInstance ? CALLED_FROM_PARENT : NOT_CALLED_FROM_PARENT)
-                .write();
+                ;
+        final String adminName;
+        final ComponentName adminComp;
+        if (admin != null) {
+            adminComp = admin.info.getComponent();
+            adminName = adminComp.flattenToShortString();
+            event.setAdmin(adminComp);
+        } else {
+            adminComp = null;
+            adminName = mInjector.getPackageManager().getPackagesForUid(caller.getUid())[0];
+            Slog.i(LOG_TAG, "Logging wipeData() event admin as " + adminName);
+            event.setAdmin(adminName);
+            if (mInjector.userManagerIsHeadlessSystemUserMode()) {
+                // On headless system user mode, the call is meant to factory reset the whole
+                // device, otherwise the caller could simply remove the current user.
+                userId = UserHandle.USER_SYSTEM;
+            }
+        }
+        event.write();
+
         String internalReason = String.format(
                 "DevicePolicyManager.wipeDataWithReason() from %s, organization-owned? %s",
-                admin.info.getComponent().flattenToShortString(),
-                calledByProfileOwnerOnOrgOwnedDevice);
+                adminName, calledByProfileOwnerOnOrgOwnedDevice);
 
-        wipeDataNoLock(
-                admin.info.getComponent(), flags, internalReason, wipeReasonForUser, userId);
+        wipeDataNoLock(adminComp, flags, internalReason, wipeReasonForUser, userId);
     }
 
     private void wipeDataNoLock(ComponentName admin, int flags, String internalReason,
diff --git a/services/incremental/OWNERS b/services/incremental/OWNERS
new file mode 100644
index 0000000..d825dfd
--- /dev/null
+++ b/services/incremental/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/pm/OWNERS
diff --git a/services/people/OWNERS b/services/people/OWNERS
new file mode 100644
index 0000000..7ac9b73
--- /dev/null
+++ b/services/people/OWNERS
@@ -0,0 +1,2 @@
[email protected]
[email protected]
diff --git a/services/print/OWNERS b/services/print/OWNERS
new file mode 100644
index 0000000..2c7b881
--- /dev/null
+++ b/services/print/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/print/OWNERS
diff --git a/services/restrictions/OWNERS b/services/restrictions/OWNERS
new file mode 100644
index 0000000..95e614c8
--- /dev/null
+++ b/services/restrictions/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/service/restrictions/OWNERS
diff --git a/services/robotests/backup/OWNERS b/services/robotests/backup/OWNERS
new file mode 100644
index 0000000..d99779e
--- /dev/null
+++ b/services/robotests/backup/OWNERS
@@ -0,0 +1 @@
+include /services/backup/OWNERS
diff --git a/services/robotests/src/com/android/server/backup/OWNERS b/services/robotests/src/com/android/server/backup/OWNERS
new file mode 100644
index 0000000..d99779e
--- /dev/null
+++ b/services/robotests/src/com/android/server/backup/OWNERS
@@ -0,0 +1 @@
+include /services/backup/OWNERS
diff --git a/services/robotests/src/com/android/server/pm/OWNERS b/services/robotests/src/com/android/server/pm/OWNERS
new file mode 100644
index 0000000..d825dfd
--- /dev/null
+++ b/services/robotests/src/com/android/server/pm/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/pm/OWNERS
diff --git a/services/startop/OWNERS b/services/startop/OWNERS
new file mode 100644
index 0000000..bd3d829
--- /dev/null
+++ b/services/startop/OWNERS
@@ -0,0 +1 @@
+include /startop/OWNERS
diff --git a/services/tests/PackageManager/OWNERS b/services/tests/PackageManager/OWNERS
new file mode 100644
index 0000000..d825dfd
--- /dev/null
+++ b/services/tests/PackageManager/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/pm/OWNERS
diff --git a/services/tests/PackageManagerComponentOverrideTests/OWNERS b/services/tests/PackageManagerComponentOverrideTests/OWNERS
new file mode 100644
index 0000000..d825dfd
--- /dev/null
+++ b/services/tests/PackageManagerComponentOverrideTests/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/pm/OWNERS
diff --git a/services/tests/mockingservicestests/AndroidManifest.xml b/services/tests/mockingservicestests/AndroidManifest.xml
index 182fe9a..fbde1d2 100644
--- a/services/tests/mockingservicestests/AndroidManifest.xml
+++ b/services/tests/mockingservicestests/AndroidManifest.xml
@@ -27,6 +27,9 @@
     <uses-permission android:name="android.permission.MANAGE_APPOPS"/>
     <uses-permission android:name="android.permission.MONITOR_DEVICE_CONFIG_ACCESS"/>
 
+    <!-- needed by MasterClearReceiverTest to display a system dialog -->
+    <uses-permission android:name="android.permission.INTERNAL_SYSTEM_WINDOW"/>
+
     <application android:testOnly="true"
                  android:debuggable="true">
         <uses-library android:name="android.test.runner" />
diff --git a/services/tests/mockingservicestests/assets/AppOpsUpgradeTest/OWNERS b/services/tests/mockingservicestests/assets/AppOpsUpgradeTest/OWNERS
new file mode 100644
index 0000000..999ea0e
--- /dev/null
+++ b/services/tests/mockingservicestests/assets/AppOpsUpgradeTest/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/permission/OWNERS
diff --git a/services/tests/mockingservicestests/src/com/android/server/MasterClearReceiverTest.java b/services/tests/mockingservicestests/src/com/android/server/MasterClearReceiverTest.java
new file mode 100644
index 0000000..f01120e
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/MasterClearReceiverTest.java
@@ -0,0 +1,210 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server;
+
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
+
+import static com.google.common.truth.Truth.assertWithMessage;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.same;
+import static org.mockito.Mockito.never;
+
+import android.content.Context;
+import android.content.ContextWrapper;
+import android.content.Intent;
+import android.os.Looper;
+import android.os.RecoverySystem;
+import android.os.storage.StorageManager;
+import android.platform.test.annotations.Presubmit;
+import android.util.Log;
+import android.view.WindowManager;
+
+import androidx.test.InstrumentationRegistry;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoSession;
+import org.mockito.quality.Strictness;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Run it as {@code FrameworksMockingServicesTests:MasterClearReceiverTest}.
+ */
+@Presubmit
+public final class MasterClearReceiverTest {
+
+    private static final String TAG = MasterClearReceiverTest.class.getSimpleName();
+
+    private MockitoSession mSession;
+
+    // Cannot @Mock context because MasterClearReceiver shows an AlertDialog, which relies
+    // on resources - we'd need to mock them as well.
+    private final Context mContext = new ContextWrapper(
+            InstrumentationRegistry.getInstrumentation().getTargetContext()) {
+
+        @Override
+        public Object getSystemService(String name) {
+            Log.v(TAG, "getSystemService(): " + name);
+            return name.equals(Context.STORAGE_SERVICE) ? mSm : super.getSystemService(name);
+        }
+    };
+
+    private final MasterClearReceiver mReceiver = new MasterClearReceiver();
+
+    // Used to make sure that wipeAdoptableDisks() is called before rebootWipeUserData()
+    private boolean mWipeExternalDataCalled;
+
+    // Uset to block test until rebootWipeUserData() is called, as it might be asynchronous called
+    // in a different thread
+    private final CountDownLatch mRebootWipeUserDataLatch = new CountDownLatch(1);
+
+    @Mock
+    private StorageManager mSm;
+
+    @Mock
+    private WindowManager mWm;
+
+    @Before
+    public void startSession() {
+        mSession = mockitoSession()
+                .initMocks(this)
+                .mockStatic(RecoverySystem.class)
+                .strictness(Strictness.LENIENT)
+                .startMocking();
+    }
+
+    @After
+    public void finishSession() {
+        if (mSession == null) {
+            Log.w(TAG, "finishSession(): no session");
+            return;
+        }
+        mSession.finishMocking();
+    }
+
+    @Test
+    public void testNoExtras() throws Exception {
+        expectNoWipeExternalData();
+        expectRebootWipeUserData();
+
+        Intent intent = new Intent(Intent.ACTION_FACTORY_RESET);
+        mReceiver.onReceive(mContext, intent);
+
+        verifyRebootWipeUserData();
+        verifyNoWipeExternalData();
+    }
+
+    @Test
+    public void testWipeExternalDirectory() throws Exception {
+        expectWipeExternalData();
+        expectRebootWipeUserData();
+
+        Intent intent = new Intent(Intent.ACTION_FACTORY_RESET);
+        intent.putExtra(Intent.EXTRA_WIPE_EXTERNAL_STORAGE, true);
+        mReceiver.onReceive(mContext, intent);
+
+        verifyRebootWipeUserData();
+        verifyWipeExternalData();
+    }
+
+    @Test
+    public void testAllExtras() throws Exception {
+        expectWipeExternalData();
+        expectRebootWipeUserData();
+
+        Intent intent = new Intent(Intent.ACTION_FACTORY_RESET);
+        intent.putExtra(Intent.EXTRA_WIPE_EXTERNAL_STORAGE, true);
+        intent.putExtra("shutdown", true);
+        intent.putExtra(Intent.EXTRA_REASON, "Self destruct");
+        intent.putExtra(Intent.EXTRA_FORCE_FACTORY_RESET, true);
+        intent.putExtra(Intent.EXTRA_WIPE_ESIMS, true);
+        mReceiver.onReceive(mContext, intent);
+
+        verifyRebootWipeUserData(/* shutdown= */ true, /* reason= */ "Self destruct",
+                /* force= */ true, /* wipeEuicc= */ true);
+        verifyWipeExternalData();
+    }
+
+
+    private void expectNoWipeExternalData() {
+        // This is a trick to simplify how the order of methods are called: as wipeAdoptableDisks()
+        // should be called before rebootWipeUserData(), expectRebootWipeUserData() throws an
+        // exception if it's not called, so this method "emulates" a call when it's not neeeded.
+        //
+        // A more robust solution would be using internal counters for expected and actual mocked
+        // calls, so the expectXXX() methods would increment expected counter and the Answer
+        // implementations would increment the actual counter and check if they match, but that
+        // would be an overkill (and make the test logic more complicated).
+        mWipeExternalDataCalled = true;
+    }
+
+    private void expectRebootWipeUserData() {
+        doAnswer((inv) -> {
+            Log.i(TAG, inv.toString());
+            if (!mWipeExternalDataCalled) {
+                String error = "rebootWipeUserData() called before wipeAdoptableDisks()";
+                Log.e(TAG, error);
+                throw new IllegalStateException(error);
+            }
+            mRebootWipeUserDataLatch.countDown();
+            return null;
+        }).when(() -> RecoverySystem
+                .rebootWipeUserData(any(), anyBoolean(), any(), anyBoolean(), anyBoolean()));
+    }
+
+    private void expectWipeExternalData() {
+        Looper.prepare(); // needed by Dialog
+
+        doAnswer((inv) -> {
+            Log.i(TAG, inv.toString());
+            mWipeExternalDataCalled = true;
+            return null;
+        }).when(mSm).wipeAdoptableDisks();
+    }
+
+    private void verifyRebootWipeUserData() throws Exception  {
+        verifyRebootWipeUserData(/* shutdown= */ false, /* reason= */ null, /* force= */ false,
+                /* wipeEuicc= */ false);
+
+    }
+
+    private void verifyRebootWipeUserData(boolean shutdown, String reason, boolean force,
+            boolean wipeEuicc) throws Exception {
+        boolean called = mRebootWipeUserDataLatch.await(5, TimeUnit.SECONDS);
+        assertWithMessage("rebootWipeUserData not called in 5s").that(called).isTrue();
+
+        verify(()-> RecoverySystem.rebootWipeUserData(same(mContext), eq(shutdown), eq(reason),
+                eq(force), eq(wipeEuicc)));
+    }
+
+    private void verifyWipeExternalData() {
+        verify(mSm).wipeAdoptableDisks();
+    }
+
+    private void verifyNoWipeExternalData() {
+        verify(mSm, never()).wipeAdoptableDisks();
+    }
+}
diff --git a/services/tests/mockingservicestests/src/com/android/server/OWNERS b/services/tests/mockingservicestests/src/com/android/server/OWNERS
new file mode 100644
index 0000000..e779e21
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/OWNERS
@@ -0,0 +1 @@
+per-file *Alarm* = file:/apex/jobscheduler/OWNERS
diff --git a/services/tests/mockingservicestests/src/com/android/server/alarm/OWNERS b/services/tests/mockingservicestests/src/com/android/server/alarm/OWNERS
new file mode 100644
index 0000000..6f207fb1
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/alarm/OWNERS
@@ -0,0 +1 @@
+include /apex/jobscheduler/OWNERS
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/OWNERS b/services/tests/mockingservicestests/src/com/android/server/am/OWNERS
new file mode 100644
index 0000000..72c0a9e
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/am/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/am/OWNERS
diff --git a/services/tests/mockingservicestests/src/com/android/server/appop/OWNERS b/services/tests/mockingservicestests/src/com/android/server/appop/OWNERS
new file mode 100644
index 0000000..999ea0e
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/appop/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/permission/OWNERS
diff --git a/services/tests/mockingservicestests/src/com/android/server/blob/OWNERS b/services/tests/mockingservicestests/src/com/android/server/blob/OWNERS
new file mode 100644
index 0000000..65bb6b8
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/blob/OWNERS
@@ -0,0 +1 @@
+include /apex/blobstore/OWNERS
diff --git a/services/tests/mockingservicestests/src/com/android/server/display/OWNERS b/services/tests/mockingservicestests/src/com/android/server/display/OWNERS
new file mode 100644
index 0000000..6ce1ee4
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/display/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/display/OWNERS
diff --git a/services/tests/mockingservicestests/src/com/android/server/job/OWNERS b/services/tests/mockingservicestests/src/com/android/server/job/OWNERS
new file mode 100644
index 0000000..6f207fb1
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/job/OWNERS
@@ -0,0 +1 @@
+include /apex/jobscheduler/OWNERS
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 e331507..63b36fc 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
@@ -60,6 +60,7 @@
 import android.content.Context;
 import android.location.ILocationCallback;
 import android.location.ILocationListener;
+import android.location.LastLocationRequest;
 import android.location.Location;
 import android.location.LocationManagerInternal;
 import android.location.LocationManagerInternal.ProviderEnabledListener;
@@ -260,55 +261,77 @@
 
     @Test
     public void testGetLastLocation_Fine() {
-        assertThat(mManager.getLastLocation(IDENTITY, PERMISSION_FINE, false)).isNull();
+        assertThat(mManager.getLastLocation(new LastLocationRequest.Builder().build(), IDENTITY,
+                PERMISSION_FINE)).isNull();
 
         Location loc = createLocation(NAME, mRandom);
         mProvider.setProviderLocation(loc);
-        assertThat(mManager.getLastLocation(IDENTITY, PERMISSION_FINE, false)).isEqualTo(loc);
+        assertThat(mManager.getLastLocation(new LastLocationRequest.Builder().build(), IDENTITY,
+                PERMISSION_FINE)).isEqualTo(loc);
     }
 
     @Test
     public void testGetLastLocation_Coarse() {
-        assertThat(mManager.getLastLocation(IDENTITY, PERMISSION_FINE, false)).isNull();
+        assertThat(mManager.getLastLocation(new LastLocationRequest.Builder().build(), IDENTITY,
+                PERMISSION_FINE)).isNull();
 
         Location loc = createLocation(NAME, mRandom);
         mProvider.setProviderLocation(loc);
-        Location coarse = mManager.getLastLocation(IDENTITY, PERMISSION_COARSE, false);
+        Location coarse = mManager.getLastLocation(new LastLocationRequest.Builder().build(),
+                IDENTITY, PERMISSION_COARSE);
         assertThat(coarse).isNotEqualTo(loc);
         assertThat(coarse).isNearby(loc, 5000);
     }
 
     @Test
     public void testGetLastLocation_Bypass() {
-        assertThat(mManager.getLastLocation(IDENTITY, PERMISSION_FINE, false)).isNull();
-        assertThat(mManager.getLastLocation(IDENTITY, PERMISSION_FINE, true)).isNull();
+        assertThat(mManager.getLastLocation(new LastLocationRequest.Builder().build(), IDENTITY,
+                PERMISSION_FINE)).isNull();
+        assertThat(mManager.getLastLocation(
+                new LastLocationRequest.Builder().setLocationSettingsIgnored(true).build(),
+                IDENTITY, PERMISSION_FINE)).isNull();
 
         Location loc = createLocation(NAME, mRandom);
         mProvider.setProviderLocation(loc);
-        assertThat(mManager.getLastLocation(IDENTITY, PERMISSION_FINE, false)).isEqualTo(loc);
-        assertThat(mManager.getLastLocation(IDENTITY, PERMISSION_FINE, true)).isEqualTo(
+        assertThat(mManager.getLastLocation(new LastLocationRequest.Builder().build(), IDENTITY,
+                PERMISSION_FINE)).isEqualTo(loc);
+        assertThat(mManager.getLastLocation(
+                new LastLocationRequest.Builder().setLocationSettingsIgnored(true).build(),
+                IDENTITY, PERMISSION_FINE)).isEqualTo(
                 loc);
 
         mProvider.setProviderAllowed(false);
-        assertThat(mManager.getLastLocation(IDENTITY, PERMISSION_FINE, false)).isNull();
-        assertThat(mManager.getLastLocation(IDENTITY, PERMISSION_FINE, true)).isEqualTo(
+        assertThat(mManager.getLastLocation(new LastLocationRequest.Builder().build(), IDENTITY,
+                PERMISSION_FINE)).isNull();
+        assertThat(mManager.getLastLocation(
+                new LastLocationRequest.Builder().setLocationSettingsIgnored(true).build(),
+                IDENTITY, PERMISSION_FINE)).isEqualTo(
                 loc);
 
         loc = createLocation(NAME, mRandom);
         mProvider.setProviderLocation(loc);
-        assertThat(mManager.getLastLocation(IDENTITY, PERMISSION_FINE, false)).isNull();
-        assertThat(mManager.getLastLocation(IDENTITY, PERMISSION_FINE, true)).isEqualTo(
+        assertThat(mManager.getLastLocation(new LastLocationRequest.Builder().build(), IDENTITY,
+                PERMISSION_FINE)).isNull();
+        assertThat(mManager.getLastLocation(
+                new LastLocationRequest.Builder().setLocationSettingsIgnored(true).build(),
+                IDENTITY, PERMISSION_FINE)).isEqualTo(
                 loc);
 
         mProvider.setProviderAllowed(true);
-        assertThat(mManager.getLastLocation(IDENTITY, PERMISSION_FINE, false)).isNull();
-        assertThat(mManager.getLastLocation(IDENTITY, PERMISSION_FINE, true)).isEqualTo(
+        assertThat(mManager.getLastLocation(new LastLocationRequest.Builder().build(), IDENTITY,
+                PERMISSION_FINE)).isNull();
+        assertThat(mManager.getLastLocation(
+                new LastLocationRequest.Builder().setLocationSettingsIgnored(true).build(),
+                IDENTITY, PERMISSION_FINE)).isEqualTo(
                 loc);
 
         loc = createLocation(NAME, mRandom);
         mProvider.setProviderLocation(loc);
-        assertThat(mManager.getLastLocation(IDENTITY, PERMISSION_FINE, false)).isEqualTo(loc);
-        assertThat(mManager.getLastLocation(IDENTITY, PERMISSION_FINE, true)).isEqualTo(
+        assertThat(mManager.getLastLocation(new LastLocationRequest.Builder().build(), IDENTITY,
+                PERMISSION_FINE)).isEqualTo(loc);
+        assertThat(mManager.getLastLocation(
+                new LastLocationRequest.Builder().setLocationSettingsIgnored(true).build(),
+                IDENTITY, PERMISSION_FINE)).isEqualTo(
                 loc);
     }
 
@@ -320,10 +343,12 @@
 
         Location loc = createLocation(NAME, mRandom);
         mockProvider.setProviderLocation(loc);
-        assertThat(mManager.getLastLocation(IDENTITY, PERMISSION_FINE, false)).isEqualTo(loc);
+        assertThat(mManager.getLastLocation(new LastLocationRequest.Builder().build(), IDENTITY,
+                PERMISSION_FINE)).isEqualTo(loc);
 
         mManager.setMockProvider(null);
-        assertThat(mManager.getLastLocation(IDENTITY, PERMISSION_FINE, false)).isNull();
+        assertThat(mManager.getLastLocation(new LastLocationRequest.Builder().build(), IDENTITY,
+                PERMISSION_FINE)).isNull();
     }
 
     @Test
@@ -331,12 +356,14 @@
         Location loc1 = createLocation(NAME, mRandom);
         mManager.injectLastLocation(loc1, CURRENT_USER);
 
-        assertThat(mManager.getLastLocation(IDENTITY, PERMISSION_FINE, false)).isEqualTo(loc1);
+        assertThat(mManager.getLastLocation(new LastLocationRequest.Builder().build(), IDENTITY,
+                PERMISSION_FINE)).isEqualTo(loc1);
 
         Location loc2 = createLocation(NAME, mRandom);
         mManager.injectLastLocation(loc2, CURRENT_USER);
 
-        assertThat(mManager.getLastLocation(IDENTITY, PERMISSION_FINE, false)).isEqualTo(loc1);
+        assertThat(mManager.getLastLocation(new LastLocationRequest.Builder().build(), IDENTITY,
+                PERMISSION_FINE)).isEqualTo(loc1);
     }
 
     @Test
@@ -355,7 +382,8 @@
         Location loc = createLocation(NAME, mRandom);
         mProvider.setProviderLocation(loc);
 
-        assertThat(mPassive.getLastLocation(IDENTITY, PERMISSION_FINE, false)).isEqualTo(loc);
+        assertThat(mPassive.getLastLocation(new LastLocationRequest.Builder().build(), IDENTITY,
+                PERMISSION_FINE)).isEqualTo(loc);
     }
 
     @Test
diff --git a/services/tests/mockingservicestests/src/com/android/server/power/OWNERS b/services/tests/mockingservicestests/src/com/android/server/power/OWNERS
new file mode 100644
index 0000000..d68066b
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/power/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/power/OWNERS
diff --git a/services/tests/mockingservicestests/src/com/android/server/usage/OWNERS b/services/tests/mockingservicestests/src/com/android/server/usage/OWNERS
new file mode 100644
index 0000000..d3227de
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/usage/OWNERS
@@ -0,0 +1 @@
+include /services/usage/OWNERS
diff --git a/services/tests/mockingservicestests/src/com/android/server/wallpaper/OWNERS b/services/tests/mockingservicestests/src/com/android/server/wallpaper/OWNERS
new file mode 100644
index 0000000..8ff0f74
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/wallpaper/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/service/wallpaper/OWNERS
diff --git a/services/tests/servicestests/Android.bp b/services/tests/servicestests/Android.bp
index 89770fe3..6daa381 100644
--- a/services/tests/servicestests/Android.bp
+++ b/services/tests/servicestests/Android.bp
@@ -33,6 +33,7 @@
         "androidx.test.ext.truth",
         "androidx.test.runner",
         "androidx.test.rules",
+        "platform-compat-test-rules",
         "mockito-target-minus-junit4",
         "platform-test-annotations",
         "ShortcutManagerTestUtils",
diff --git a/services/tests/servicestests/apks/OWNERS b/services/tests/servicestests/apks/OWNERS
new file mode 100644
index 0000000..d825dfd
--- /dev/null
+++ b/services/tests/servicestests/apks/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/pm/OWNERS
diff --git a/services/tests/servicestests/assets/NetworkPolicy/OWNERS b/services/tests/servicestests/assets/NetworkPolicy/OWNERS
new file mode 100644
index 0000000..aa87958
--- /dev/null
+++ b/services/tests/servicestests/assets/NetworkPolicy/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/net/OWNERS
diff --git a/services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/OWNERS b/services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/OWNERS
new file mode 100644
index 0000000..aa87958
--- /dev/null
+++ b/services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/net/OWNERS
diff --git a/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java
index e609adc..ce3751a 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java
@@ -72,7 +72,7 @@
 import androidx.test.runner.AndroidJUnit4;
 
 import com.android.server.devicepolicy.MockUtils;
-import com.android.server.pm.permission.PermissionManagerServiceInternal;
+import com.android.server.pm.permission.LegacyPermissionManagerInternal;
 
 import com.google.android.collect.Lists;
 
@@ -133,10 +133,10 @@
     @Mock private UnaryOperator<List<ScoredNetwork>> mScanResultsFilter;
     @Mock private WifiInfo mWifiInfo;
     @Mock private NetworkScoreService.ScoringServiceConnection mServiceConnection;
-    @Mock private PermissionManagerServiceInternal mPermissionManagerInternal;
+    @Mock private LegacyPermissionManagerInternal mPermissionManagerInternal;
     @Captor private ArgumentCaptor<List<ScoredNetwork>> mScoredNetworkCaptor;
-    @Captor private
-    ArgumentCaptor<PermissionManagerServiceInternal.PackagesProvider> mPackagesProviderCaptor;
+    @Captor private ArgumentCaptor<LegacyPermissionManagerInternal.PackagesProvider>
+            mPackagesProviderCaptor;
 
     private ContentResolver mContentResolver;
     private NetworkScoreService mNetworkScoreService;
@@ -165,7 +165,7 @@
         mHandlerThread = new HandlerThread("NetworkScoreServiceTest");
         mHandlerThread.start();
         LocalServices.addService(
-                PermissionManagerServiceInternal.class, mPermissionManagerInternal);
+                LegacyPermissionManagerInternal.class, mPermissionManagerInternal);
         mNetworkScoreService = new NetworkScoreService(mContext, mNetworkScorerAppManager,
                 networkScorerAppData -> mServiceConnection, mHandlerThread.getLooper());
         WifiConfiguration configuration = new WifiConfiguration();
@@ -191,7 +191,7 @@
     @After
     public void tearDown() throws Exception {
         mHandlerThread.quitSafely();
-        LocalServices.removeServiceForTest(PermissionManagerServiceInternal.class);
+        LocalServices.removeServiceForTest(LegacyPermissionManagerInternal.class);
     }
 
     @Test
diff --git a/services/tests/servicestests/src/com/android/server/OWNERS b/services/tests/servicestests/src/com/android/server/OWNERS
new file mode 100644
index 0000000..6153db3
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/OWNERS
@@ -0,0 +1,6 @@
+per-file *Alarm* = file:/apex/jobscheduler/OWNERS
+per-file *AppOps* = file:/core/java/android/permission/OWNERS
+per-file *Bluetooth* = file:/core/java/android/bluetooth/OWNERS
+per-file *Gnss* = file:/services/core/java/com/android/server/location/OWNERS
+per-file *Network* = file:/services/core/java/com/android/server/net/OWNERS
+per-file *Vibrator* = file:/services/core/java/com/android/server/vibrator/OWNERS
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/OWNERS b/services/tests/servicestests/src/com/android/server/accessibility/OWNERS
new file mode 100644
index 0000000..b74281e
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/accessibility/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/view/accessibility/OWNERS
diff --git a/services/tests/servicestests/src/com/android/server/accounts/OWNERS b/services/tests/servicestests/src/com/android/server/accounts/OWNERS
new file mode 100644
index 0000000..df1b4f4
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/accounts/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/accounts/OWNERS
diff --git a/services/tests/servicestests/src/com/android/server/adb/OWNERS b/services/tests/servicestests/src/com/android/server/adb/OWNERS
new file mode 100644
index 0000000..b97f795
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/adb/OWNERS
@@ -0,0 +1 @@
+include platform/packages/modules/adb:/OWNERS
diff --git a/services/tests/servicestests/src/com/android/server/am/OWNERS b/services/tests/servicestests/src/com/android/server/am/OWNERS
new file mode 100644
index 0000000..72c0a9e
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/am/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/am/OWNERS
diff --git a/services/tests/servicestests/src/com/android/server/appop/OWNERS b/services/tests/servicestests/src/com/android/server/appop/OWNERS
new file mode 100644
index 0000000..999ea0e
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/appop/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/permission/OWNERS
diff --git a/services/tests/servicestests/src/com/android/server/appsearch/OWNERS b/services/tests/servicestests/src/com/android/server/appsearch/OWNERS
new file mode 100644
index 0000000..ebe9e4e
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/appsearch/OWNERS
@@ -0,0 +1 @@
+include /apex/appsearch/OWNERS
diff --git a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchImplTest.java b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchImplTest.java
index b929061..f38def8 100644
--- a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchImplTest.java
@@ -37,6 +37,7 @@
 import com.android.server.appsearch.proto.StringIndexingConfig;
 import com.android.server.appsearch.proto.TermMatchType;
 
+import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableSet;
 
 import org.junit.Before;
@@ -46,9 +47,7 @@
 
 import java.util.ArrayList;
 import java.util.Collections;
-import java.util.HashSet;
 import java.util.List;
-import java.util.Set;
 
 public class AppSearchImplTest {
     @Rule public TemporaryFolder mTemporaryFolder = new TemporaryFolder();
@@ -66,14 +65,15 @@
                                         + VisibilityStore.SCHEMA_TYPE)
                         .addProperty(
                                 new AppSearchSchema.PropertyConfig.Builder(
-                                                VisibilityStore.PLATFORM_HIDDEN_PROPERTY)
+                                                VisibilityStore.NOT_PLATFORM_SURFACEABLE_PROPERTY)
                                         .setDataType(
                                                 AppSearchSchema.PropertyConfig.DATA_TYPE_STRING)
                                         .setCardinality(
                                                 AppSearchSchema.PropertyConfig.CARDINALITY_REPEATED)
                                         .build())
                         .build();
-        mVisibilitySchemaProto = SchemaToProtoConverter.convert(visibilityAppSearchSchema);
+        mVisibilitySchemaProto =
+                SchemaToProtoConverter.toSchemaTypeConfigProto(visibilityAppSearchSchema);
     }
 
     /**
@@ -340,9 +340,13 @@
     @Test
     public void testOptimize() throws Exception {
         // Insert schema
-        Set<AppSearchSchema> schemas =
-                Collections.singleton(new AppSearchSchema.Builder("type").build());
-        mAppSearchImpl.setSchema("database", schemas, /*forceOverride=*/ false);
+        List<AppSearchSchema> schemas =
+                Collections.singletonList(new AppSearchSchema.Builder("type").build());
+        mAppSearchImpl.setSchema(
+                "database",
+                schemas,
+                /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
+                /*forceOverride=*/ false);
 
         // Insert enough documents.
         for (int i = 0;
@@ -351,7 +355,7 @@
                                 + AppSearchImpl.CHECK_OPTIMIZE_INTERVAL;
                 i++) {
             GenericDocument document =
-                    new GenericDocument.Builder("uri" + i, "type")
+                    new GenericDocument.Builder<>("uri" + i, "type")
                             .setNamespace("namespace")
                             .build();
             mAppSearchImpl.putDocument("database", document);
@@ -392,13 +396,17 @@
         SearchSpecProto.Builder searchSpecProto = SearchSpecProto.newBuilder().setQuery("");
 
         // Insert schema
-        Set<AppSearchSchema> schemas =
-                Collections.singleton(new AppSearchSchema.Builder("type").build());
-        mAppSearchImpl.setSchema("database", schemas, /*forceOverride=*/ false);
+        List<AppSearchSchema> schemas =
+                Collections.singletonList(new AppSearchSchema.Builder("type").build());
+        mAppSearchImpl.setSchema(
+                "database",
+                schemas,
+                /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
+                /*forceOverride=*/ false);
 
         // Insert document
         GenericDocument document =
-                new GenericDocument.Builder("uri", "type").setNamespace("namespace").build();
+                new GenericDocument.Builder<>("uri", "type").setNamespace("namespace").build();
         mAppSearchImpl.putDocument("database", document);
 
         // Rewrite SearchSpec
@@ -413,20 +421,28 @@
         SearchSpecProto.Builder searchSpecProto = SearchSpecProto.newBuilder().setQuery("");
 
         // Insert schema
-        Set<AppSearchSchema> schemas =
-                Set.of(
+        List<AppSearchSchema> schemas =
+                ImmutableList.of(
                         new AppSearchSchema.Builder("typeA").build(),
                         new AppSearchSchema.Builder("typeB").build());
-        mAppSearchImpl.setSchema("database1", schemas, /*forceOverride=*/ false);
-        mAppSearchImpl.setSchema("database2", schemas, /*forceOverride=*/ false);
+        mAppSearchImpl.setSchema(
+                "database1",
+                schemas,
+                /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
+                /*forceOverride=*/ false);
+        mAppSearchImpl.setSchema(
+                "database2",
+                schemas,
+                /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
+                /*forceOverride=*/ false);
 
         // Insert documents
         GenericDocument document1 =
-                new GenericDocument.Builder("uri", "typeA").setNamespace("namespace").build();
+                new GenericDocument.Builder<>("uri", "typeA").setNamespace("namespace").build();
         mAppSearchImpl.putDocument("database1", document1);
 
         GenericDocument document2 =
-                new GenericDocument.Builder("uri", "typeB").setNamespace("namespace").build();
+                new GenericDocument.Builder<>("uri", "typeB").setNamespace("namespace").build();
         mAppSearchImpl.putDocument("database2", document2);
 
         // Rewrite SearchSpec
@@ -477,10 +493,14 @@
 
     @Test
     public void testSetSchema() throws Exception {
-        Set<AppSearchSchema> schemas =
-                Collections.singleton(new AppSearchSchema.Builder("Email").build());
+        List<AppSearchSchema> schemas =
+                Collections.singletonList(new AppSearchSchema.Builder("Email").build());
         // Set schema Email to AppSearch database1
-        mAppSearchImpl.setSchema("database1", schemas, /*forceOverride=*/ false);
+        mAppSearchImpl.setSchema(
+                "database1",
+                schemas,
+                /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
+                /*forceOverride=*/ false);
 
         // Create expected schemaType proto.
         SchemaProto expectedProto =
@@ -500,35 +520,47 @@
     public void testSetSchema_existingSchemaRetainsVisibilitySetting() throws Exception {
         mAppSearchImpl.setSchema(
                 "database",
-                Collections.singleton(new AppSearchSchema.Builder("schema1").build()),
+                Collections.singletonList(new AppSearchSchema.Builder("schema1").build()),
+                /*schemasNotPlatformSurfaceable=*/ Collections.singletonList("schema1"),
                 /*forceOverride=*/ false);
-        mAppSearchImpl.setVisibility("database", Set.of("schema1"));
 
         // "schema1" is platform hidden now
-        assertThat(mAppSearchImpl.getVisibilityStoreLocked().getPlatformHiddenSchemas("database"))
+        assertThat(
+                        mAppSearchImpl
+                                .getVisibilityStoreLocked()
+                                .getSchemasNotPlatformSurfaceable("database"))
                 .containsExactly("database/schema1");
 
         // Add a new schema, and include the already-existing "schema1"
         mAppSearchImpl.setSchema(
                 "database",
-                Set.of(
+                ImmutableList.of(
                         new AppSearchSchema.Builder("schema1").build(),
                         new AppSearchSchema.Builder("schema2").build()),
+                /*schemasNotPlatformSurfaceable=*/ Collections.singletonList("schema1"),
                 /*forceOverride=*/ false);
 
         // Check that "schema1" is still platform hidden, but "schema2" is the default platform
         // visible.
-        assertThat(mAppSearchImpl.getVisibilityStoreLocked().getPlatformHiddenSchemas("database"))
+        assertThat(
+                        mAppSearchImpl
+                                .getVisibilityStoreLocked()
+                                .getSchemasNotPlatformSurfaceable("database"))
                 .containsExactly("database/schema1");
     }
 
     @Test
     public void testRemoveSchema() throws Exception {
-        Set<AppSearchSchema> schemas = new HashSet<>();
-        schemas.add(new AppSearchSchema.Builder("Email").build());
-        schemas.add(new AppSearchSchema.Builder("Document").build());
+        List<AppSearchSchema> schemas =
+                ImmutableList.of(
+                        new AppSearchSchema.Builder("Email").build(),
+                        new AppSearchSchema.Builder("Document").build());
         // Set schema Email and Document to AppSearch database1
-        mAppSearchImpl.setSchema("database1", schemas, /*forceOverride=*/ false);
+        mAppSearchImpl.setSchema(
+                "database1",
+                schemas,
+                /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
+                /*forceOverride=*/ false);
 
         // Create expected schemaType proto.
         SchemaProto expectedProto =
@@ -547,20 +579,27 @@
         assertThat(mAppSearchImpl.getSchemaProtoLocked().getTypesList())
                 .containsExactlyElementsIn(expectedTypes);
 
-        final Set<AppSearchSchema> finalSchemas =
-                Collections.singleton(new AppSearchSchema.Builder("Email").build());
+        final List<AppSearchSchema> finalSchemas =
+                Collections.singletonList(new AppSearchSchema.Builder("Email").build());
         // Check the incompatible error has been thrown.
         AppSearchException e =
                 expectThrows(
                         AppSearchException.class,
                         () ->
                                 mAppSearchImpl.setSchema(
-                                        "database1", finalSchemas, /*forceOverride=*/ false));
+                                        "database1",
+                                        finalSchemas,
+                                        /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
+                                        /*forceOverride=*/ false));
         assertThat(e).hasMessageThat().contains("Schema is incompatible");
         assertThat(e).hasMessageThat().contains("Deleted types: [database1/Document]");
 
         // ForceOverride to delete.
-        mAppSearchImpl.setSchema("database1", finalSchemas, /*forceOverride=*/ true);
+        mAppSearchImpl.setSchema(
+                "database1",
+                finalSchemas,
+                /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
+                /*forceOverride=*/ true);
 
         // Check Document schema is removed.
         expectedProto =
@@ -579,13 +618,22 @@
     @Test
     public void testRemoveSchema_differentDataBase() throws Exception {
         // Create schemas
-        Set<AppSearchSchema> schemas = new HashSet<>();
-        schemas.add(new AppSearchSchema.Builder("Email").build());
-        schemas.add(new AppSearchSchema.Builder("Document").build());
+        List<AppSearchSchema> schemas =
+                ImmutableList.of(
+                        new AppSearchSchema.Builder("Email").build(),
+                        new AppSearchSchema.Builder("Document").build());
 
         // Set schema Email and Document to AppSearch database1 and 2
-        mAppSearchImpl.setSchema("database1", schemas, /*forceOverride=*/ false);
-        mAppSearchImpl.setSchema("database2", schemas, /*forceOverride=*/ false);
+        mAppSearchImpl.setSchema(
+                "database1",
+                schemas,
+                /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
+                /*forceOverride=*/ false);
+        mAppSearchImpl.setSchema(
+                "database2",
+                schemas,
+                /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
+                /*forceOverride=*/ false);
 
         // Create expected schemaType proto.
         SchemaProto expectedProto =
@@ -610,8 +658,12 @@
                 .containsExactlyElementsIn(expectedTypes);
 
         // Save only Email to database1 this time.
-        schemas = Collections.singleton(new AppSearchSchema.Builder("Email").build());
-        mAppSearchImpl.setSchema("database1", schemas, /*forceOverride=*/ true);
+        schemas = Collections.singletonList(new AppSearchSchema.Builder("Email").build());
+        mAppSearchImpl.setSchema(
+                "database1",
+                schemas,
+                /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
+                /*forceOverride=*/ true);
 
         // Create expected schemaType list, database 1 should only contain Email but database 2
         // remains in same.
@@ -638,76 +690,82 @@
     public void testRemoveSchema_removedFromVisibilityStore() throws Exception {
         mAppSearchImpl.setSchema(
                 "database",
-                Collections.singleton(new AppSearchSchema.Builder("schema1").build()),
+                Collections.singletonList(new AppSearchSchema.Builder("schema1").build()),
+                /*schemasNotPlatformSurfaceable=*/ Collections.singletonList("schema1"),
                 /*forceOverride=*/ false);
-        mAppSearchImpl.setVisibility("database", Set.of("schema1"));
 
         // "schema1" is platform hidden now
-        assertThat(mAppSearchImpl.getVisibilityStoreLocked().getPlatformHiddenSchemas("database"))
+        assertThat(
+                        mAppSearchImpl
+                                .getVisibilityStoreLocked()
+                                .getSchemasNotPlatformSurfaceable("database"))
                 .containsExactly("database/schema1");
 
         // Remove "schema1" by force overriding
-        mAppSearchImpl.setSchema("database", Collections.emptySet(), /*forceOverride=*/ true);
+        mAppSearchImpl.setSchema(
+                "database",
+                Collections.emptyList(),
+                /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
+                /*forceOverride=*/ true);
 
         // Check that "schema1" is no longer considered platform hidden
-        assertThat(mAppSearchImpl.getVisibilityStoreLocked().getPlatformHiddenSchemas("database"))
+        assertThat(
+                        mAppSearchImpl
+                                .getVisibilityStoreLocked()
+                                .getSchemasNotPlatformSurfaceable("database"))
                 .isEmpty();
 
         // Add "schema1" back, it gets default visibility settings which means it's not platform
         // hidden.
         mAppSearchImpl.setSchema(
                 "database",
-                Collections.singleton(new AppSearchSchema.Builder("schema1").build()),
+                Collections.singletonList(new AppSearchSchema.Builder("schema1").build()),
+                /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
                 /*forceOverride=*/ false);
-        assertThat(mAppSearchImpl.getVisibilityStoreLocked().getPlatformHiddenSchemas("database"))
+        assertThat(
+                        mAppSearchImpl
+                                .getVisibilityStoreLocked()
+                                .getSchemasNotPlatformSurfaceable("database"))
                 .isEmpty();
     }
 
     @Test
-    public void testSetVisibility_defaultPlatformVisible() throws Exception {
+    public void testSetSchema_defaultPlatformVisible() throws Exception {
         mAppSearchImpl.setSchema(
                 "database",
-                Collections.singleton(new AppSearchSchema.Builder("Schema").build()),
+                Collections.singletonList(new AppSearchSchema.Builder("Schema").build()),
+                /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
                 /*forceOverride=*/ false);
-        assertThat(mAppSearchImpl.getVisibilityStoreLocked().getPlatformHiddenSchemas("database"))
+        assertThat(
+                        mAppSearchImpl
+                                .getVisibilityStoreLocked()
+                                .getSchemasNotPlatformSurfaceable("database"))
                 .isEmpty();
     }
 
     @Test
-    public void testSetVisibility_platformHidden() throws Exception {
+    public void testSetSchema_platformHidden() throws Exception {
         mAppSearchImpl.setSchema(
                 "database",
-                Collections.singleton(new AppSearchSchema.Builder("Schema").build()),
+                Collections.singletonList(new AppSearchSchema.Builder("Schema").build()),
+                /*schemasNotPlatformSurfaceable=*/ Collections.singletonList("Schema"),
                 /*forceOverride=*/ false);
-        mAppSearchImpl.setVisibility("database", Set.of("Schema"));
-        assertThat(mAppSearchImpl.getVisibilityStoreLocked().getPlatformHiddenSchemas("database"))
+        assertThat(
+                        mAppSearchImpl
+                                .getVisibilityStoreLocked()
+                                .getSchemasNotPlatformSurfaceable("database"))
                 .containsExactly("database/Schema");
     }
 
     @Test
-    public void testSetVisibility_unknownSchema() throws Exception {
-        mAppSearchImpl.setSchema(
-                "database",
-                Collections.singleton(new AppSearchSchema.Builder("Schema").build()),
-                /*forceOverride=*/ false);
-
-        // We'll throw an exception if a client tries to set visibility on a schema we don't know
-        // about.
-        AppSearchException e =
-                expectThrows(
-                        AppSearchException.class,
-                        () -> mAppSearchImpl.setVisibility("database", Set.of("UnknownSchema")));
-        assertThat(e).hasMessageThat().contains("Unknown schema(s)");
-    }
-
-    @Test
     public void testHasSchemaType() throws Exception {
         // Nothing exists yet
         assertThat(mAppSearchImpl.hasSchemaTypeLocked("database", "Schema")).isFalse();
 
         mAppSearchImpl.setSchema(
                 "database",
-                Collections.singleton(new AppSearchSchema.Builder("Schema").build()),
+                Collections.singletonList(new AppSearchSchema.Builder("Schema").build()),
+                /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
                 /*forceOverride=*/ false);
         assertThat(mAppSearchImpl.hasSchemaTypeLocked("database", "Schema")).isTrue();
 
@@ -723,7 +781,8 @@
         // Has database1
         mAppSearchImpl.setSchema(
                 "database1",
-                Collections.singleton(new AppSearchSchema.Builder("schema").build()),
+                Collections.singletonList(new AppSearchSchema.Builder("schema").build()),
+                /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
                 /*forceOverride=*/ false);
         assertThat(mAppSearchImpl.getDatabasesLocked())
                 .containsExactly(VisibilityStore.DATABASE_NAME, "database1");
@@ -731,7 +790,8 @@
         // Has both databases
         mAppSearchImpl.setSchema(
                 "database2",
-                Collections.singleton(new AppSearchSchema.Builder("schema").build()),
+                Collections.singletonList(new AppSearchSchema.Builder("schema").build()),
+                /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
                 /*forceOverride=*/ false);
         assertThat(mAppSearchImpl.getDatabasesLocked())
                 .containsExactly(VisibilityStore.DATABASE_NAME, "database1", "database2");
diff --git a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/VisibilityStoreTest.java b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/VisibilityStoreTest.java
index dfe2de6..a1f575a 100644
--- a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/VisibilityStoreTest.java
+++ b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/VisibilityStoreTest.java
@@ -41,34 +41,19 @@
     @Test
     public void testSetVisibility() throws Exception {
         mVisibilityStore.setVisibility(
-                "database", /*platformHiddenSchemas=*/ Set.of("schema1", "schema2"));
-        assertThat(mVisibilityStore.getPlatformHiddenSchemas("database"))
+                "database", /*schemasNotPlatformSurfaceable=*/ Set.of("schema1", "schema2"));
+        assertThat(mVisibilityStore.getSchemasNotPlatformSurfaceable("database"))
                 .containsExactly("schema1", "schema2");
 
         // New .setVisibility() call completely overrides previous visibility settings. So
         // "schema1" isn't preserved.
         mVisibilityStore.setVisibility(
-                "database", /*platformHiddenSchemas=*/ Set.of("schema1", "schema3"));
-        assertThat(mVisibilityStore.getPlatformHiddenSchemas("database"))
+                "database", /*schemasNotPlatformSurfaceable=*/ Set.of("schema1", "schema3"));
+        assertThat(mVisibilityStore.getSchemasNotPlatformSurfaceable("database"))
                 .containsExactly("schema1", "schema3");
 
         mVisibilityStore.setVisibility(
-                "database", /*platformHiddenSchemas=*/ Collections.emptySet());
-        assertThat(mVisibilityStore.getPlatformHiddenSchemas("database")).isEmpty();
-    }
-
-    @Test
-    public void testRemoveSchemas() throws Exception {
-        mVisibilityStore.setVisibility(
-                "database", /*platformHiddenSchemas=*/ Set.of("schema1", "schema2"));
-
-        // Removed just schema1
-        mVisibilityStore.updateSchemas("database", /*schemasToRemove=*/ Set.of("schema1"));
-        assertThat(mVisibilityStore.getPlatformHiddenSchemas("database"))
-                .containsExactly("schema2");
-
-        // Removed everything now
-        mVisibilityStore.updateSchemas("database", /*schemasToRemove=*/ Set.of("schema2"));
-        assertThat(mVisibilityStore.getPlatformHiddenSchemas("database")).isEmpty();
+                "database", /*schemasNotPlatformSurfaceable=*/ Collections.emptySet());
+        assertThat(mVisibilityStore.getSchemasNotPlatformSurfaceable("database")).isEmpty();
     }
 }
diff --git a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/converter/GenericDocumentToProtoConverterTest.java b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/converter/GenericDocumentToProtoConverterTest.java
index 98392a7..194be37 100644
--- a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/converter/GenericDocumentToProtoConverterTest.java
+++ b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/converter/GenericDocumentToProtoConverterTest.java
@@ -94,20 +94,24 @@
                 PropertyProto.newBuilder()
                         .setName("documentKey1")
                         .addDocumentValues(
-                                GenericDocumentToProtoConverter.convert(DOCUMENT_PROPERTIES_1)));
+                                GenericDocumentToProtoConverter.toDocumentProto(
+                                        DOCUMENT_PROPERTIES_1)));
         propertyProtoMap.put(
                 "documentKey2",
                 PropertyProto.newBuilder()
                         .setName("documentKey2")
                         .addDocumentValues(
-                                GenericDocumentToProtoConverter.convert(DOCUMENT_PROPERTIES_2)));
+                                GenericDocumentToProtoConverter.toDocumentProto(
+                                        DOCUMENT_PROPERTIES_2)));
         List<String> sortedKey = new ArrayList<>(propertyProtoMap.keySet());
         Collections.sort(sortedKey);
         for (String key : sortedKey) {
             documentProtoBuilder.addProperties(propertyProtoMap.get(key));
         }
         DocumentProto documentProto = documentProtoBuilder.build();
-        assertThat(GenericDocumentToProtoConverter.convert(document)).isEqualTo(documentProto);
-        assertThat(document).isEqualTo(GenericDocumentToProtoConverter.convert(documentProto));
+        assertThat(GenericDocumentToProtoConverter.toDocumentProto(document))
+                .isEqualTo(documentProto);
+        assertThat(document)
+                .isEqualTo(GenericDocumentToProtoConverter.toGenericDocument(documentProto));
     }
 }
diff --git a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/converter/SchemaToProtoConverterTest.java b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/converter/SchemaToProtoConverterTest.java
index dedfca4..88edcb8 100644
--- a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/converter/SchemaToProtoConverterTest.java
+++ b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/converter/SchemaToProtoConverterTest.java
@@ -89,7 +89,10 @@
                                                                 TermMatchType.Code.PREFIX)))
                         .build();
 
-        assertThat(SchemaToProtoConverter.convert(emailSchema)).isEqualTo(expectedEmailProto);
+        assertThat(SchemaToProtoConverter.toSchemaTypeConfigProto(emailSchema))
+                .isEqualTo(expectedEmailProto);
+        assertThat(SchemaToProtoConverter.toAppSearchSchema(expectedEmailProto))
+                .isEqualTo(emailSchema);
     }
 
     @Test
@@ -151,7 +154,9 @@
                                                                 TermMatchType.Code.UNKNOWN)))
                         .build();
 
-        assertThat(SchemaToProtoConverter.convert(musicRecordingSchema))
+        assertThat(SchemaToProtoConverter.toSchemaTypeConfigProto(musicRecordingSchema))
                 .isEqualTo(expectedMusicRecordingProto);
+        assertThat(SchemaToProtoConverter.toAppSearchSchema(expectedMusicRecordingProto))
+                .isEqualTo(musicRecordingSchema);
     }
 }
diff --git a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/converter/SnippetTest.java b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/converter/SnippetTest.java
index 518f532..7c68c6b 100644
--- a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/converter/SnippetTest.java
+++ b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/converter/SnippetTest.java
@@ -83,7 +83,7 @@
 
         // Making ResultReader and getting Snippet values.
         SearchResultPage searchResultPage =
-                SearchResultToProtoConverter.convertToSearchResultPage(searchResultProto);
+                SearchResultToProtoConverter.toSearchResultPage(searchResultProto);
         for (SearchResult result : searchResultPage.getResults()) {
             SearchResult.MatchInfo match = result.getMatches().get(0);
             assertThat(match.getPropertyPath()).isEqualTo(propertyKeyString);
@@ -131,7 +131,7 @@
                 SearchResultProto.newBuilder().addResults(resultProto).build();
 
         SearchResultPage searchResultPage =
-                SearchResultToProtoConverter.convertToSearchResultPage(searchResultProto);
+                SearchResultToProtoConverter.toSearchResultPage(searchResultProto);
         for (SearchResult result : searchResultPage.getResults()) {
             assertThat(result.getMatches()).isEmpty();
         }
@@ -196,7 +196,7 @@
 
         // Making ResultReader and getting Snippet values.
         SearchResultPage searchResultPage =
-                SearchResultToProtoConverter.convertToSearchResultPage(searchResultProto);
+                SearchResultToProtoConverter.toSearchResultPage(searchResultProto);
         for (SearchResult result : searchResultPage.getResults()) {
 
             SearchResult.MatchInfo match1 = result.getMatches().get(0);
diff --git a/services/tests/servicestests/src/com/android/server/attention/OWNERS b/services/tests/servicestests/src/com/android/server/attention/OWNERS
new file mode 100644
index 0000000..51fc9bd
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/attention/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/attention/OWNERS
diff --git a/services/tests/servicestests/src/com/android/server/backup/OWNERS b/services/tests/servicestests/src/com/android/server/backup/OWNERS
new file mode 100644
index 0000000..d99779e
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/backup/OWNERS
@@ -0,0 +1 @@
+include /services/backup/OWNERS
diff --git a/services/tests/servicestests/src/com/android/server/backup/utils/BackupEligibilityRulesTest.java b/services/tests/servicestests/src/com/android/server/backup/utils/BackupEligibilityRulesTest.java
index 444155d..738527e 100644
--- a/services/tests/servicestests/src/com/android/server/backup/utils/BackupEligibilityRulesTest.java
+++ b/services/tests/servicestests/src/com/android/server/backup/utils/BackupEligibilityRulesTest.java
@@ -18,14 +18,17 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
 import android.app.backup.BackupManager.OperationType;
+import android.compat.testing.PlatformCompatChangeRule;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.Property;
 import android.content.pm.PackageManagerInternal;
 import android.content.pm.PackageParser;
 import android.content.pm.Signature;
@@ -38,9 +41,15 @@
 import androidx.test.runner.AndroidJUnit4;
 
 import com.android.server.backup.UserBackupManagerService;
+import com.android.server.pm.parsing.pkg.AndroidPackage;
+
+import libcore.junit.util.compat.CoreCompatChangeRule.DisableCompatChanges;
+import libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges;
 
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.TestRule;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
@@ -50,17 +59,19 @@
 @RunWith(AndroidJUnit4.class)
 public class BackupEligibilityRulesTest {
     private static final String CUSTOM_BACKUP_AGENT_NAME = "custom.backup.agent";
-    private static final String TEST_PACKAGE_NAME = "test_package";
+    private static final String TEST_PACKAGE_NAME = "com.android.frameworks.servicestests";
 
     private static final Signature SIGNATURE_1 = generateSignature((byte) 1);
     private static final Signature SIGNATURE_2 = generateSignature((byte) 2);
     private static final Signature SIGNATURE_3 = generateSignature((byte) 3);
     private static final Signature SIGNATURE_4 = generateSignature((byte) 4);
 
+    @Rule public TestRule compatChangeRule = new PlatformCompatChangeRule();
+
     @Mock private PackageManagerInternal mMockPackageManagerInternal;
     @Mock private PackageManager mPackageManager;
-    private BackupEligibilityRules mBackupEligibilityRules;
 
+    private BackupEligibilityRules mBackupEligibilityRules;
     private int mUserId;
 
     @Before
@@ -225,7 +236,6 @@
             throws Exception {
         ApplicationInfo applicationInfo = getApplicationInfo(Process.SYSTEM_UID,
                 /* flags */ 0, CUSTOM_BACKUP_AGENT_NAME);
-
         BackupEligibilityRules eligibilityRules = getBackupEligibilityRules(
                 OperationType.MIGRATION);
         boolean isEligible = eligibilityRules.appIsEligibleForBackup(applicationInfo);
@@ -234,6 +244,82 @@
     }
 
     @Test
+    @EnableCompatChanges({BackupEligibilityRules.RESTRICT_ADB_BACKUP})
+    public void appIsEligibleForBackup_adbBackupNotAllowed_returnsFalseForAdbBackup()
+            throws Exception {
+        ApplicationInfo applicationInfo = getApplicationInfo(Process.FIRST_APPLICATION_UID,
+                /* flags */ ApplicationInfo.PRIVATE_FLAG_PRIVILEGED, CUSTOM_BACKUP_AGENT_NAME);
+        BackupEligibilityRules eligibilityRules = getBackupEligibilityRules(
+                OperationType.ADB_BACKUP);
+        when(mPackageManager.getProperty(eq(PackageManager.PROPERTY_ALLOW_ADB_BACKUP),
+                eq(TEST_PACKAGE_NAME))).thenReturn(getAdbBackupProperty(
+                        /* allowAdbBackup */ false));
+
+        boolean isEligible = eligibilityRules.appIsEligibleForBackup(applicationInfo);
+
+        assertThat(isEligible).isFalse();
+    }
+
+    @Test
+    @EnableCompatChanges({BackupEligibilityRules.RESTRICT_ADB_BACKUP})
+    public void appIsEligibleForBackup_adbBackupAllowed_returnsTrueForAdbBackup()
+            throws Exception {
+        ApplicationInfo applicationInfo = getApplicationInfo(Process.FIRST_APPLICATION_UID,
+                /* flags */ ApplicationInfo.PRIVATE_FLAG_PRIVILEGED, CUSTOM_BACKUP_AGENT_NAME);
+        BackupEligibilityRules eligibilityRules = getBackupEligibilityRules(
+                OperationType.ADB_BACKUP);
+        when(mPackageManager.getProperty(eq(PackageManager.PROPERTY_ALLOW_ADB_BACKUP),
+                eq(TEST_PACKAGE_NAME))).thenReturn(getAdbBackupProperty(
+                /* allowAdbBackup */ true));
+
+        boolean isEligible = eligibilityRules.appIsEligibleForBackup(applicationInfo);
+
+        assertThat(isEligible).isTrue();
+    }
+
+    @Test
+    @EnableCompatChanges({BackupEligibilityRules.RESTRICT_ADB_BACKUP})
+    public void appIsEligibleForBackup_debuggableNonPrivilegedApp_returnsTrueForAdbBackup()
+            throws Exception {
+        ApplicationInfo applicationInfo = getApplicationInfo(Process.FIRST_APPLICATION_UID,
+                /* flags */ ApplicationInfo.FLAG_DEBUGGABLE, CUSTOM_BACKUP_AGENT_NAME);
+        BackupEligibilityRules eligibilityRules = getBackupEligibilityRules(
+                OperationType.ADB_BACKUP);
+
+        boolean isEligible = eligibilityRules.appIsEligibleForBackup(applicationInfo);
+
+        assertThat(isEligible).isTrue();
+    }
+
+    @Test
+    @DisableCompatChanges({BackupEligibilityRules.RESTRICT_ADB_BACKUP})
+    public void appIsEligibleForBackup_allowBackupTrueBeforeS_returnsTrueForAdbBackup()
+            throws Exception {
+        ApplicationInfo applicationInfo = getApplicationInfo(Process.FIRST_APPLICATION_UID,
+                ApplicationInfo.FLAG_ALLOW_BACKUP, CUSTOM_BACKUP_AGENT_NAME);
+        BackupEligibilityRules eligibilityRules = getBackupEligibilityRules(
+                OperationType.ADB_BACKUP);
+
+        boolean isEligible = eligibilityRules.appIsEligibleForBackup(applicationInfo);
+
+        assertThat(isEligible).isTrue();
+    }
+
+    @Test
+    @DisableCompatChanges({BackupEligibilityRules.RESTRICT_ADB_BACKUP})
+    public void appIsEligibleForBackup_allowBackupFalseBeforeS_returnsFalseForAdbBackup()
+            throws Exception {
+        ApplicationInfo applicationInfo = getApplicationInfo(Process.FIRST_APPLICATION_UID,
+                /* flags */ 0, CUSTOM_BACKUP_AGENT_NAME);
+        BackupEligibilityRules eligibilityRules = getBackupEligibilityRules(
+                OperationType.ADB_BACKUP);
+
+        boolean isEligible = eligibilityRules.appIsEligibleForBackup(applicationInfo);
+
+        assertThat(isEligible).isFalse();
+    }
+
+    @Test
     public void appIsDisabled_stateDefaultManifestEnabled_returnsFalse() throws Exception {
         ApplicationInfo applicationInfo = new ApplicationInfo();
         applicationInfo.flags = 0;
@@ -789,10 +875,15 @@
     private static ApplicationInfo getApplicationInfo(int appUid, int flags,
             String backupAgentName) {
         ApplicationInfo applicationInfo = new ApplicationInfo();
-        applicationInfo.flags = 0;
+        applicationInfo.flags = flags;
         applicationInfo.packageName = TEST_PACKAGE_NAME;
         applicationInfo.uid = appUid;
         applicationInfo.backupAgentName = backupAgentName;
         return applicationInfo;
     }
+
+    private static Property getAdbBackupProperty(boolean allowAdbBackup) {
+        return new Property(PackageManager.PROPERTY_ALLOW_ADB_BACKUP, allowAdbBackup,
+                TEST_PACKAGE_NAME, /* className */ "");
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/compat/OWNERS b/services/tests/servicestests/src/com/android/server/compat/OWNERS
new file mode 100644
index 0000000..f8c3520
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/compat/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/compat/OWNERS
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/OWNERS b/services/tests/servicestests/src/com/android/server/devicepolicy/OWNERS
new file mode 100644
index 0000000..e95633a
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/app/admin/OWNERS
diff --git a/services/tests/servicestests/src/com/android/server/devicestate/OWNERS b/services/tests/servicestests/src/com/android/server/devicestate/OWNERS
new file mode 100644
index 0000000..d9b0e2e
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/devicestate/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/devicestate/OWNERS
diff --git a/services/tests/servicestests/src/com/android/server/display/OWNERS b/services/tests/servicestests/src/com/android/server/display/OWNERS
new file mode 100644
index 0000000..6ce1ee4
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/display/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/display/OWNERS
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/OWNERS b/services/tests/servicestests/src/com/android/server/hdmi/OWNERS
new file mode 100644
index 0000000..c3c47ed
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/hdmi/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/hardware/hdmi/OWNERS
diff --git a/services/tests/servicestests/src/com/android/server/input/OWNERS b/services/tests/servicestests/src/com/android/server/input/OWNERS
new file mode 100644
index 0000000..d701f23
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/input/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/hardware/input/OWNERS
diff --git a/services/tests/servicestests/src/com/android/server/inputmethod/OWNERS b/services/tests/servicestests/src/com/android/server/inputmethod/OWNERS
new file mode 100644
index 0000000..5deb2ce
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/inputmethod/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/view/inputmethod/OWNERS
diff --git a/services/tests/servicestests/src/com/android/server/integrity/OWNERS b/services/tests/servicestests/src/com/android/server/integrity/OWNERS
new file mode 100644
index 0000000..653d1c9
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/integrity/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/integrity/OWNERS
diff --git a/services/tests/servicestests/src/com/android/server/job/OWNERS b/services/tests/servicestests/src/com/android/server/job/OWNERS
new file mode 100644
index 0000000..6f207fb1
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/job/OWNERS
@@ -0,0 +1 @@
+include /apex/jobscheduler/OWNERS
diff --git a/services/tests/servicestests/src/com/android/server/lights/OWNERS b/services/tests/servicestests/src/com/android/server/lights/OWNERS
new file mode 100644
index 0000000..cb46a80
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/lights/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/lights/OWNERS
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsShellCommandTest.java b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsShellCommandTest.java
index 2205694..25dbc6b 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsShellCommandTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsShellCommandTest.java
@@ -16,6 +16,9 @@
 
 package com.android.server.locksettings;
 
+import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_HIGH;
+import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_LOW;
+import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_MEDIUM;
 import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC;
 import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_COMPLEX;
 import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_NUMERIC;
@@ -277,6 +280,94 @@
         verify(mLockPatternUtils, never()).setLockCredential(any(), any(), anyInt());
     }
 
+    @Test
+    public void testSetPin_nonCompliantWithComplexity() throws Exception {
+        when(mLockPatternUtils.isSecure(mUserId)).thenReturn(true);
+        when(mLockPatternUtils.isLockPatternEnabled(mUserId)).thenReturn(false);
+        when(mLockPatternUtils.isLockPasswordEnabled(mUserId)).thenReturn(true);
+        when(mLockPatternUtils.getKeyguardStoredPasswordQuality(mUserId)).thenReturn(
+                PASSWORD_QUALITY_NUMERIC);
+        when(mLockPatternUtils.checkCredential(
+                LockscreenCredential.createPin("1234"), mUserId, null)).thenReturn(true);
+        when(mLockPatternUtils.getRequestedPasswordMetrics(mUserId))
+                .thenReturn(metricsForAdminQuality(PASSWORD_QUALITY_UNSPECIFIED));
+        when(mLockPatternUtils.getRequestedPasswordComplexity(mUserId))
+                .thenReturn(PASSWORD_COMPLEXITY_MEDIUM);
+
+        assertEquals(-1, mCommand.exec(new Binder(), in, out, err,
+                new String[] { "set-pin", "--old", "1234", "4321" },
+                mShellCallback, mResultReceiver));
+
+        verify(mLockPatternUtils, never()).setLockCredential(any(), any(), anyInt());
+    }
+
+    @Test
+    public void testSetPin_compliantWithComplexity() throws Exception {
+        when(mLockPatternUtils.isSecure(mUserId)).thenReturn(true);
+        when(mLockPatternUtils.isLockPatternEnabled(mUserId)).thenReturn(false);
+        when(mLockPatternUtils.isLockPasswordEnabled(mUserId)).thenReturn(true);
+        when(mLockPatternUtils.getKeyguardStoredPasswordQuality(mUserId)).thenReturn(
+                PASSWORD_QUALITY_NUMERIC);
+        when(mLockPatternUtils.checkCredential(
+                LockscreenCredential.createPin("1234"), mUserId, null)).thenReturn(true);
+        when(mLockPatternUtils.getRequestedPasswordMetrics(mUserId))
+                .thenReturn(metricsForAdminQuality(PASSWORD_QUALITY_UNSPECIFIED));
+        when(mLockPatternUtils.getRequestedPasswordComplexity(mUserId))
+                .thenReturn(PASSWORD_COMPLEXITY_MEDIUM);
+
+        assertEquals(0, mCommand.exec(new Binder(), in, out, err,
+                new String[] { "set-pin", "--old", "1234", "4231" },
+                mShellCallback, mResultReceiver));
+
+        verify(mLockPatternUtils).setLockCredential(
+                LockscreenCredential.createPin("4231"),
+                LockscreenCredential.createPin("1234"),
+                mUserId);
+    }
+
+    @Test
+    public void testSetPattern_nonCompliantWithComplexity() throws Exception {
+        when(mLockPatternUtils.isSecure(mUserId)).thenReturn(true);
+        when(mLockPatternUtils.isLockPatternEnabled(mUserId)).thenReturn(true);
+        when(mLockPatternUtils.isLockPasswordEnabled(mUserId)).thenReturn(false);
+        when(mLockPatternUtils.checkCredential(
+                LockscreenCredential.createPattern(stringToPattern("1234")),
+                mUserId, null)).thenReturn(true);
+        when(mLockPatternUtils.getRequestedPasswordMetrics(mUserId))
+                .thenReturn(metricsForAdminQuality(PASSWORD_QUALITY_UNSPECIFIED));
+        when(mLockPatternUtils.getRequestedPasswordComplexity(mUserId))
+                .thenReturn(PASSWORD_COMPLEXITY_HIGH);
+
+        assertEquals(-1, mCommand.exec(new Binder(), in, out, err,
+                new String[] { "set-pattern", "--old", "1234", "4321" },
+                mShellCallback, mResultReceiver));
+
+        verify(mLockPatternUtils, never()).setLockCredential(any(), any(), anyInt());
+    }
+
+    @Test
+    public void testSetPattern_compliantWithComplexity() throws Exception {
+        when(mLockPatternUtils.isSecure(mUserId)).thenReturn(true);
+        when(mLockPatternUtils.isLockPatternEnabled(mUserId)).thenReturn(true);
+        when(mLockPatternUtils.isLockPasswordEnabled(mUserId)).thenReturn(false);
+        when(mLockPatternUtils.checkCredential(
+                LockscreenCredential.createPattern(stringToPattern("1234")),
+                mUserId, null)).thenReturn(true);
+        when(mLockPatternUtils.getRequestedPasswordMetrics(mUserId))
+                .thenReturn(metricsForAdminQuality(PASSWORD_QUALITY_UNSPECIFIED));
+        when(mLockPatternUtils.getRequestedPasswordComplexity(mUserId))
+                .thenReturn(PASSWORD_COMPLEXITY_LOW);
+
+        assertEquals(0, mCommand.exec(new Binder(), in, out, err,
+                new String[] { "set-pattern", "--old", "1234", "4321" },
+                mShellCallback, mResultReceiver));
+
+        verify(mLockPatternUtils).setLockCredential(
+                LockscreenCredential.createPattern(stringToPattern("4321")),
+                LockscreenCredential.createPattern(stringToPattern("1234")),
+                mUserId);
+    }
+
     private List<LockPatternView.Cell> stringToPattern(String str) {
         return LockPatternUtils.byteArrayToPattern(str.getBytes());
     }
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/OWNERS b/services/tests/servicestests/src/com/android/server/locksettings/OWNERS
new file mode 100644
index 0000000..0a8dc8c
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/locksettings/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/locksettings/OWNERS
diff --git a/services/tests/servicestests/src/com/android/server/net/IpConfigStoreTest.java b/services/tests/servicestests/src/com/android/server/net/IpConfigStoreTest.java
index 7767a28..9d300a6 100644
--- a/services/tests/servicestests/src/com/android/server/net/IpConfigStoreTest.java
+++ b/services/tests/servicestests/src/com/android/server/net/IpConfigStoreTest.java
@@ -20,11 +20,11 @@
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.fail;
 
+import android.net.InetAddresses;
 import android.net.IpConfiguration;
 import android.net.IpConfiguration.IpAssignment;
 import android.net.IpConfiguration.ProxySettings;
 import android.net.LinkAddress;
-import android.net.NetworkUtils;
 import android.net.ProxyInfo;
 import android.net.StaticIpConfiguration;
 import android.util.ArrayMap;
@@ -79,8 +79,8 @@
 
         StaticIpConfiguration staticIpConfiguration = new StaticIpConfiguration();
         staticIpConfiguration.ipAddress = new LinkAddress(IP_ADDR_1);
-        staticIpConfiguration.dnsServers.add(NetworkUtils.numericToInetAddress(DNS_IP_ADDR_1));
-        staticIpConfiguration.dnsServers.add(NetworkUtils.numericToInetAddress(DNS_IP_ADDR_2));
+        staticIpConfiguration.dnsServers.add(InetAddresses.parseNumericAddress(DNS_IP_ADDR_1));
+        staticIpConfiguration.dnsServers.add(InetAddresses.parseNumericAddress(DNS_IP_ADDR_2));
 
         ProxyInfo proxyInfo = new ProxyInfo("10.10.10.10", 88, "host1,host2");
 
diff --git a/services/tests/servicestests/src/com/android/server/net/OWNERS b/services/tests/servicestests/src/com/android/server/net/OWNERS
new file mode 100644
index 0000000..aa87958
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/net/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/net/OWNERS
diff --git a/services/tests/servicestests/src/com/android/server/om/OWNERS b/services/tests/servicestests/src/com/android/server/om/OWNERS
new file mode 100644
index 0000000..afb98d4
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/om/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/content/om/OWNERS
diff --git a/services/tests/servicestests/src/com/android/server/people/OWNERS b/services/tests/servicestests/src/com/android/server/people/OWNERS
new file mode 100644
index 0000000..3198a5e
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/people/OWNERS
@@ -0,0 +1 @@
+include /services/people/OWNERS
diff --git a/services/tests/servicestests/src/com/android/server/pm/OWNERS b/services/tests/servicestests/src/com/android/server/pm/OWNERS
new file mode 100644
index 0000000..d825dfd
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/pm/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/pm/OWNERS
diff --git a/services/tests/servicestests/src/com/android/server/policy/OWNERS b/services/tests/servicestests/src/com/android/server/policy/OWNERS
new file mode 100644
index 0000000..0862c05
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/policy/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/wm/OWNERS
diff --git a/services/tests/servicestests/src/com/android/server/power/OWNERS b/services/tests/servicestests/src/com/android/server/power/OWNERS
new file mode 100644
index 0000000..d68066b
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/power/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/power/OWNERS
diff --git a/services/tests/servicestests/src/com/android/server/powerstats/OWNERS b/services/tests/servicestests/src/com/android/server/powerstats/OWNERS
new file mode 100644
index 0000000..d68066b
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/powerstats/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/power/OWNERS
diff --git a/services/tests/servicestests/src/com/android/server/rollback/OWNERS b/services/tests/servicestests/src/com/android/server/rollback/OWNERS
new file mode 100644
index 0000000..d04a706
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/rollback/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/rollback/OWNERS
diff --git a/services/tests/servicestests/src/com/android/server/soundtrigger_middleware/OWNERS b/services/tests/servicestests/src/com/android/server/soundtrigger_middleware/OWNERS
new file mode 100644
index 0000000..816bc6b
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/soundtrigger_middleware/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/media/soundtrigger/OWNERS
diff --git a/services/tests/servicestests/src/com/android/server/stats/OWNERS b/services/tests/servicestests/src/com/android/server/stats/OWNERS
new file mode 100644
index 0000000..ee865b1
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/stats/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/stats/OWNERS
diff --git a/services/tests/servicestests/src/com/android/server/storage/OWNERS b/services/tests/servicestests/src/com/android/server/storage/OWNERS
new file mode 100644
index 0000000..6f9dbea
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/storage/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/os/storage/OWNERS
diff --git a/services/tests/servicestests/src/com/android/server/textclassifier/OWNERS b/services/tests/servicestests/src/com/android/server/textclassifier/OWNERS
new file mode 100644
index 0000000..46b3cb8
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/textclassifier/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/service/textclassifier/OWNERS
diff --git a/services/tests/servicestests/src/com/android/server/timedetector/OWNERS b/services/tests/servicestests/src/com/android/server/timedetector/OWNERS
new file mode 100644
index 0000000..09447a97
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/timedetector/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/app/timezone/OWNERS
diff --git a/services/tests/servicestests/src/com/android/server/timezone/OWNERS b/services/tests/servicestests/src/com/android/server/timezone/OWNERS
new file mode 100644
index 0000000..09447a97
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/timezone/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/app/timezone/OWNERS
diff --git a/services/tests/servicestests/src/com/android/server/timezonedetector/OWNERS b/services/tests/servicestests/src/com/android/server/timezonedetector/OWNERS
new file mode 100644
index 0000000..09447a97
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/timezonedetector/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/app/timezone/OWNERS
diff --git a/services/tests/servicestests/src/com/android/server/tv/OWNERS b/services/tests/servicestests/src/com/android/server/tv/OWNERS
new file mode 100644
index 0000000..305027c
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/tv/OWNERS
@@ -0,0 +1 @@
+include /media/java/android/media/tv/OWNERS
diff --git a/services/tests/servicestests/src/com/android/server/uri/OWNERS b/services/tests/servicestests/src/com/android/server/uri/OWNERS
new file mode 100644
index 0000000..ca5d5f98
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/uri/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/uri/OWNERS
diff --git a/services/tests/servicestests/src/com/android/server/usage/OWNERS b/services/tests/servicestests/src/com/android/server/usage/OWNERS
new file mode 100644
index 0000000..d3227de
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/usage/OWNERS
@@ -0,0 +1 @@
+include /services/usage/OWNERS
diff --git a/services/tests/servicestests/src/com/android/server/vibrator/OWNERS b/services/tests/servicestests/src/com/android/server/vibrator/OWNERS
new file mode 100644
index 0000000..cc63ceb
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/vibrator/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/vibrator/OWNERS
diff --git a/services/tests/servicestests/src/com/android/server/wallpaper/OWNERS b/services/tests/servicestests/src/com/android/server/wallpaper/OWNERS
new file mode 100644
index 0000000..8ff0f74
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/wallpaper/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/service/wallpaper/OWNERS
diff --git a/services/tests/servicestests/test-apps/JobTestApp/OWNERS b/services/tests/servicestests/test-apps/JobTestApp/OWNERS
new file mode 100644
index 0000000..6f207fb1
--- /dev/null
+++ b/services/tests/servicestests/test-apps/JobTestApp/OWNERS
@@ -0,0 +1 @@
+include /apex/jobscheduler/OWNERS
diff --git a/services/tests/servicestests/test-apps/PackageParserApp/OWNERS b/services/tests/servicestests/test-apps/PackageParserApp/OWNERS
new file mode 100644
index 0000000..d825dfd
--- /dev/null
+++ b/services/tests/servicestests/test-apps/PackageParserApp/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/pm/OWNERS
diff --git a/services/tests/servicestests/test-apps/PackageParsingTestManifests/OWNERS b/services/tests/servicestests/test-apps/PackageParsingTestManifests/OWNERS
new file mode 100644
index 0000000..d825dfd
--- /dev/null
+++ b/services/tests/servicestests/test-apps/PackageParsingTestManifests/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/pm/OWNERS
diff --git a/services/tests/uiservicestests/src/com/android/server/OWNERS b/services/tests/uiservicestests/src/com/android/server/OWNERS
new file mode 100644
index 0000000..05944c0
--- /dev/null
+++ b/services/tests/uiservicestests/src/com/android/server/OWNERS
@@ -0,0 +1 @@
+per-file UiModeManagerServiceTest.java = file:/packages/SystemUI/OWNERS
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java b/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java
index 32cb2a3..e510b4f 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java
@@ -1192,7 +1192,7 @@
         NotificationRecord r = getLightsNotification();
         mService.buzzBeepBlinkLocked(r);
         verifyNeverLights();
-        assertFalse(r.isInterruptive());
+        assertTrue(r.isInterruptive());
         assertEquals(-1, r.getLastAudiblyAlertedMs());
     }
 
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java
index 4a4d9bc..ec28baf 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java
@@ -249,13 +249,13 @@
                         backupPrimary.get(approvalLevel).get(userId),
                         Build.VERSION_CODES.N_MR1, userId);
             }
-            verifyExpectedApprovedEntries(service, true);
 
             for (int userId : backupSecondary.get(approvalLevel).keySet()) {
                 service.onSettingRestored(service.getConfig().secondarySettingName,
                         backupSecondary.get(approvalLevel).get(userId),
                         Build.VERSION_CODES.N_MR1, userId);
             }
+            // both sets of approved entries should be allowed
             verifyExpectedApprovedEntries(service);
             verifyExpectedApprovedEntries(service, backupPrimary.get(approvalLevel));
             verifyExpectedApprovedEntries(service, backupSecondary.get(approvalLevel));
@@ -638,8 +638,8 @@
     @Test
     public void testWriteXml_writesSetting() throws Exception {
         for (int approvalLevel : new int[] {APPROVAL_BY_COMPONENT, APPROVAL_BY_PACKAGE}) {
-            ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles,
-                    mIpm, approvalLevel);
+            ManagedServices service = new TestManagedServicesSettings(getContext(), mLock,
+                    mUserProfiles, mIpm, approvalLevel);
             loadXml(service);
 
             TypedXmlSerializer serializer = Xml.newFastSerializer();
@@ -662,6 +662,36 @@
     }
 
     @Test
+    public void testWriteXml_doesNotWriteSetting() throws Exception {
+        for (int approvalLevel : new int[] {APPROVAL_BY_COMPONENT, APPROVAL_BY_PACKAGE}) {
+            ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles,
+                    mIpm, approvalLevel);
+
+            for (int userId : mUserProfiles.getCurrentProfileIds().toArray()) {
+                Settings.Secure.putStringForUser(
+                        getContext().getContentResolver(),
+                        service.getConfig().secureSettingName, null, userId);
+            }
+            loadXml(service);
+
+            TypedXmlSerializer serializer = Xml.newFastSerializer();
+            ByteArrayOutputStream baos = new ByteArrayOutputStream();
+            serializer.setOutput(new BufferedOutputStream(baos), "utf-8");
+            serializer.startDocument(null, true);
+            service.writeXml(serializer, false, UserHandle.USER_ALL);
+            serializer.endDocument();
+            serializer.flush();
+
+            for (int userId : mUserProfiles.getCurrentProfileIds().toArray()) {
+                String actual = Settings.Secure.getStringForUser(
+                        getContext().getContentResolver(),
+                        service.getConfig().secureSettingName, userId);
+                assertTrue(TextUtils.isEmpty(actual));
+            }
+        }
+    }
+
+    @Test
     public void testWriteXml_writesUserSet() throws Exception {
         for (int approvalLevel : new int[] {APPROVAL_BY_COMPONENT, APPROVAL_BY_PACKAGE}) {
             ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles,
@@ -1415,11 +1445,11 @@
         xml.append("<" + ManagedServices.TAG_MANAGED_SERVICES + " "
                         + ManagedServices.ATT_USER_ID + "=\"99\" "
                         + ManagedServices.ATT_IS_PRIMARY + "=\"true\" "
-                        + ManagedServices.ATT_APPROVED_LIST + "=\"99\" />\n");
+                        + ManagedServices.ATT_APPROVED_LIST + "=\"990\" />\n");
         xml.append("<" + ManagedServices.TAG_MANAGED_SERVICES + " "
                 + ManagedServices.ATT_USER_ID + "=\"98\" "
                 + ManagedServices.ATT_IS_PRIMARY + "=\"false\" "
-                + ManagedServices.ATT_APPROVED_LIST + "=\"98\" />\n");
+                + ManagedServices.ATT_APPROVED_LIST + "=\"981\" />\n");
         xml.append("</" + xmlTag + ">");
 
         return xml.toString();
@@ -1483,7 +1513,7 @@
 
     private void assertContentsInAnyOrder(Collection<?> expected, Collection<?> actual) {
         assertNotNull(actual);
-        assertEquals(expected.size(), actual.size());
+        assertEquals(expected + " : " + actual, expected.size(), actual.size());
 
         for (Object o : expected) {
             assertTrue("Actual missing " + o, actual.contains(o));
@@ -1665,4 +1695,17 @@
             return null;
         }
     }
+
+    class TestManagedServicesSettings extends TestManagedServices {
+
+        public TestManagedServicesSettings(Context context, Object mutex, UserProfiles userProfiles,
+                IPackageManager pm, int approvedServiceType) {
+            super(context, mutex, userProfiles, pm, approvedServiceType);
+        }
+
+        @Override
+        public boolean shouldReflectToSettings() {
+            return true;
+        }
+    }
 }
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationAdjustmentExtractorTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationAdjustmentExtractorTest.java
index e658d17..824c05e 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationAdjustmentExtractorTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationAdjustmentExtractorTest.java
@@ -126,6 +126,7 @@
         return new Notification.Action.Builder(
                 Icon.createWithResource(getContext(), android.R.drawable.sym_def_app_icon),
                 "action",
-                PendingIntent.getBroadcast(getContext(), 0, new Intent("Action"), 0)).build();
+                PendingIntent.getBroadcast(getContext(), 0, new Intent("Action"),
+                    PendingIntent.FLAG_MUTABLE_UNAUDITED)).build();
     }
 }
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationIntrusivenessExtractorTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationIntrusivenessExtractorTest.java
index 00d93de..a9a3b2b 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationIntrusivenessExtractorTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationIntrusivenessExtractorTest.java
@@ -58,8 +58,11 @@
         NotificationChannel channel = new NotificationChannel("a", "a", IMPORTANCE_DEFAULT);
         final Notification.Builder builder = new Notification.Builder(getContext())
                 .setContentTitle("foo")
+                // TODO(b/174258141) Please replace FLAG_MUTABLE_UNAUDITED below
+                // with either FLAG_IMMUTABLE (recommended) or FLAG_MUTABLE.
                 .setFullScreenIntent(PendingIntent.getActivity(
-                        getContext(), 0, new Intent(""), 0), true)
+                        getContext(), 0, new Intent(""), PendingIntent.FLAG_MUTABLE_UNAUDITED),
+                        true)
                 .setSmallIcon(android.R.drawable.sym_def_app_icon);
 
         Notification n = builder.build();
@@ -76,8 +79,11 @@
         NotificationChannel channel = new NotificationChannel("a", "a", IMPORTANCE_DEFAULT);
         final Notification.Builder builder = new Notification.Builder(getContext())
                 .setContentTitle("foo")
+                // TODO(b/174258141) Please replace FLAG_MUTABLE_UNAUDITED below
+                // with either FLAG_IMMUTABLE (recommended) or FLAG_MUTABLE.
                 .setFullScreenIntent(PendingIntent.getActivity(
-                        getContext(), 0, new Intent(""), 0), true)
+                        getContext(), 0, new Intent(""), PendingIntent.FLAG_MUTABLE_UNAUDITED),
+                        true)
                 .setSmallIcon(android.R.drawable.sym_def_app_icon);
 
         Notification n = builder.build();
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenerServiceTest.java
index 9b37e76..c634706 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenerServiceTest.java
@@ -357,11 +357,13 @@
     private ArrayList<Notification.Action> getSmartActions(String key, int index) {
         ArrayList<Notification.Action> actions = new ArrayList<>();
         for (int i = 0; i < index; i++) {
+            // TODO(b/174935955) Please replace FLAG_MUTABLE_UNAUDITED below
+            // with either FLAG_IMMUTABLE (recommended) or FLAG_MUTABLE.
             PendingIntent intent = PendingIntent.getBroadcast(
                     getContext(),
                     index /*requestCode*/,
                     new Intent("ACTION_" + key),
-                    0 /*flags*/);
+                    PendingIntent.FLAG_MUTABLE_UNAUDITED /*flags*/);
             actions.add(new Notification.Action.Builder(null /*icon*/, key, intent).build());
         }
         return actions;
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index 762ec93..849477c 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -790,7 +790,10 @@
                 .setName("bubblebot")
                 .build();
         RemoteInput remoteInput = new RemoteInput.Builder("reply_key").setLabel("reply").build();
-        PendingIntent inputIntent = PendingIntent.getActivity(mContext, 0, new Intent(), 0);
+        // TODO(b/174965245) Please replace FLAG_MUTABLE_UNAUDITED below
+        // with either FLAG_IMMUTABLE (recommended) or FLAG_MUTABLE.
+        PendingIntent inputIntent = PendingIntent.getActivity(mContext, 0, new Intent(),
+                PendingIntent.FLAG_MUTABLE_UNAUDITED);
         Icon icon = Icon.createWithResource(mContext, android.R.drawable.sym_def_app_icon);
         Notification.Action replyAction = new Notification.Action.Builder(icon, "Reply",
                 inputIntent).addRemoteInput(remoteInput)
@@ -7366,7 +7369,10 @@
         NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
         ArrayList<Notification.Action> extraAction = new ArrayList<>();
         RemoteInput remoteInput = new RemoteInput.Builder("reply_key").setLabel("reply").build();
-        PendingIntent inputIntent = PendingIntent.getActivity(mContext, 0, new Intent(), 0);
+        // TODO(b/174965245) Please replace FLAG_MUTABLE_UNAUDITED below
+        // with either FLAG_IMMUTABLE (recommended) or FLAG_MUTABLE.
+        PendingIntent inputIntent = PendingIntent.getActivity(mContext, 0, new Intent(),
+                PendingIntent.FLAG_MUTABLE_UNAUDITED);
         Icon icon = Icon.createWithResource(mContext, android.R.drawable.sym_def_app_icon);
         Notification.Action replyAction = new Notification.Action.Builder(icon, "Reply",
                 inputIntent).addRemoteInput(remoteInput)
@@ -7396,7 +7402,10 @@
         NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
         ArrayList<Notification.Action> extraAction = new ArrayList<>();
         RemoteInput remoteInput = new RemoteInput.Builder("reply_key").setLabel("reply").build();
-        PendingIntent inputIntent = PendingIntent.getActivity(mContext, 0, new Intent(), 0);
+        // TODO(b/174965245) Please replace FLAG_MUTABLE_UNAUDITED below
+        // with either FLAG_IMMUTABLE (recommended) or FLAG_MUTABLE.
+        PendingIntent inputIntent = PendingIntent.getActivity(mContext, 0, new Intent(),
+                PendingIntent.FLAG_MUTABLE_UNAUDITED);
         Icon icon = Icon.createWithResource(mContext, android.R.drawable.sym_def_app_icon);
         Notification.Action replyAction = new Notification.Action.Builder(icon, "Reply",
                 inputIntent).addRemoteInput(remoteInput)
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/OWNERS b/services/tests/uiservicestests/src/com/android/server/notification/OWNERS
new file mode 100644
index 0000000..396fd12
--- /dev/null
+++ b/services/tests/uiservicestests/src/com/android/server/notification/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/notification/OWNERS
diff --git a/services/tests/uiservicestests/src/com/android/server/slice/OWNERS b/services/tests/uiservicestests/src/com/android/server/slice/OWNERS
new file mode 100644
index 0000000..3d0859f
--- /dev/null
+++ b/services/tests/uiservicestests/src/com/android/server/slice/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/app/slice/OWNERS
diff --git a/services/tests/uiservicestests/src/com/android/server/slice/SliceManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/slice/SliceManagerServiceTest.java
index a443695..dd0c162 100644
--- a/services/tests/uiservicestests/src/com/android/server/slice/SliceManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/slice/SliceManagerServiceTest.java
@@ -75,7 +75,6 @@
         LocalServices.addService(UsageStatsManagerInternal.class,
                 mock(UsageStatsManagerInternal.class));
         mContext.addMockSystemService(AppOpsManager.class, mock(AppOpsManager.class));
-        mContext.getTestablePermissions().setPermission(TEST_URI, PERMISSION_GRANTED);
 
         mContextSpy = spy(mContext);
         mService = spy(new SliceManagerService(mContextSpy, TestableLooper.get(this).getLooper()));
@@ -90,6 +89,7 @@
 
     @Test
     public void testAddPinCreatesPinned() throws RemoteException {
+        grantSlicePermission();
         doReturn("pkg").when(mService).getDefaultHome(anyInt());
 
         mService.pinSlice("pkg", TEST_URI, EMPTY_SPECS, mToken);
@@ -99,6 +99,7 @@
 
     @Test
     public void testRemovePinDestroysPinned() throws RemoteException {
+        grantSlicePermission();
         doReturn("pkg").when(mService).getDefaultHome(anyInt());
 
         mService.pinSlice("pkg", TEST_URI, EMPTY_SPECS, mToken);
@@ -130,11 +131,13 @@
 
     @Test(expected = IllegalStateException.class)
     public void testNoPinThrow() throws Exception {
+        grantSlicePermission();
         mService.getPinnedSpecs(TEST_URI, "pkg");
     }
 
     @Test
     public void testGetPinnedSpecs() throws Exception {
+        grantSlicePermission();
         SliceSpec[] specs = new SliceSpec[] {
             new SliceSpec("Something", 1) };
         mService.pinSlice("pkg", TEST_URI, specs, mToken);
@@ -143,4 +146,10 @@
         assertEquals(specs, mService.getPinnedSpecs(TEST_URI, "pkg"));
     }
 
+    private void grantSlicePermission() {
+        doReturn(PERMISSION_GRANTED).when(mService).checkSlicePermission(
+                eq(TEST_URI), anyString(), anyString(), anyInt(), anyInt(), any());
+        doReturn(PERMISSION_GRANTED).when(mService).checkAccess(
+                anyString(), eq(TEST_URI), anyInt(), anyInt());
+    }
 }
diff --git a/services/tests/wmtests/OWNERS b/services/tests/wmtests/OWNERS
new file mode 100644
index 0000000..0862c05
--- /dev/null
+++ b/services/tests/wmtests/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/wm/OWNERS
diff --git a/services/tests/wmtests/src/com/android/server/policy/KeyCombinationTests.java b/services/tests/wmtests/src/com/android/server/policy/KeyCombinationTests.java
new file mode 100644
index 0000000..75479de
--- /dev/null
+++ b/services/tests/wmtests/src/com/android/server/policy/KeyCombinationTests.java
@@ -0,0 +1,208 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.policy;
+
+import static android.view.KeyEvent.ACTION_DOWN;
+import static android.view.KeyEvent.ACTION_UP;
+import static android.view.KeyEvent.KEYCODE_BACK;
+import static android.view.KeyEvent.KEYCODE_POWER;
+import static android.view.KeyEvent.KEYCODE_VOLUME_DOWN;
+import static android.view.KeyEvent.KEYCODE_VOLUME_UP;
+
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
+
+import android.os.Handler;
+import android.os.Looper;
+import android.os.SystemClock;
+import android.view.KeyEvent;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Test class for {@link KeyCombinationManager}.
+ *
+ * Build/Install/Run:
+ *  atest KeyCombinationTests
+ */
+
+@SmallTest
+public class KeyCombinationTests {
+    private KeyCombinationManager mKeyCombinationManager;
+
+    private boolean mAction1Triggered = false;
+    private boolean mAction2Triggered = false;
+    private boolean mAction3Triggered = false;
+
+    private boolean mPreCondition = true;
+    private static final long SCHEDULE_TIME = 300;
+
+    @Before
+    public void setUp() {
+        mKeyCombinationManager = new KeyCombinationManager();
+        initKeyCombinationRules();
+    }
+
+    private void initKeyCombinationRules() {
+        // Rule 1 : power + volume_down trigger action immediately.
+        mKeyCombinationManager.addRule(
+                new KeyCombinationManager.TwoKeysCombinationRule(KEYCODE_VOLUME_DOWN,
+                        KEYCODE_POWER) {
+                    @Override
+                    void execute() {
+                        mAction1Triggered = true;
+                    }
+
+                    @Override
+                    void cancel() {
+                    }
+                });
+
+        // Rule 2 : volume_up + volume_down with condition.
+        mKeyCombinationManager.addRule(
+                new KeyCombinationManager.TwoKeysCombinationRule(KEYCODE_VOLUME_DOWN,
+                        KEYCODE_VOLUME_UP) {
+                    @Override
+                    boolean preCondition() {
+                        return mPreCondition;
+                    }
+
+                    @Override
+                    void execute() {
+                        mAction2Triggered = true;
+                    }
+
+                    @Override
+                    void cancel() {
+                    }
+                });
+
+        // Rule 3 : power + volume_up schedule and trigger action after timeout.
+        mKeyCombinationManager.addRule(
+                new KeyCombinationManager.TwoKeysCombinationRule(KEYCODE_VOLUME_UP, KEYCODE_POWER) {
+                    final Runnable mAction = new Runnable() {
+                        @Override
+                        public void run() {
+                            mAction3Triggered = true;
+                        }
+                    };
+                    final Handler mHandler = new Handler(Looper.getMainLooper());
+
+                    @Override
+                    void execute() {
+                        mHandler.postDelayed(mAction, SCHEDULE_TIME);
+                    }
+
+                    @Override
+                    void cancel() {
+                        mHandler.removeCallbacks(mAction);
+                    }
+                });
+    }
+
+    private void pressKeys(long firstKeyTime, int firstKeyCode, long secondKeyTime,
+            int secondKeyCode) {
+        pressKeys(firstKeyTime, firstKeyCode, secondKeyTime, secondKeyCode, 0);
+    }
+
+    private void pressKeys(long firstKeyTime, int firstKeyCode, long secondKeyTime,
+            int secondKeyCode, long pressTime) {
+        final KeyEvent firstKeyDown = new KeyEvent(firstKeyTime, firstKeyTime, ACTION_DOWN,
+                firstKeyCode, 0 /* repeat */, 0 /* metaState */);
+        final KeyEvent secondKeyDown = new KeyEvent(secondKeyTime, secondKeyTime, ACTION_DOWN,
+                secondKeyCode, 0 /* repeat */, 0 /* metaState */);
+
+        mKeyCombinationManager.interceptKey(firstKeyDown, true);
+        mKeyCombinationManager.interceptKey(secondKeyDown, true);
+
+        // keep press down.
+        try {
+            Thread.sleep(pressTime);
+        } catch (InterruptedException e) {
+            e.printStackTrace();
+        }
+
+        final KeyEvent firstKeyUp = new KeyEvent(firstKeyTime, firstKeyTime, ACTION_UP,
+                firstKeyCode, 0 /* repeat */, 0 /* metaState */);
+        final KeyEvent secondKeyUp = new KeyEvent(secondKeyTime, secondKeyTime, ACTION_UP,
+                secondKeyCode, 0 /* repeat */, 0 /* metaState */);
+
+        mKeyCombinationManager.interceptKey(firstKeyUp, true);
+        mKeyCombinationManager.interceptKey(secondKeyUp, true);
+    }
+
+    @Test
+    public void testTriggerRule() {
+        final long eventTime = SystemClock.uptimeMillis();
+        pressKeys(eventTime, KEYCODE_POWER, eventTime, KEYCODE_VOLUME_DOWN);
+        assertTrue(mAction1Triggered);
+
+        pressKeys(eventTime, KEYCODE_VOLUME_UP, eventTime, KEYCODE_VOLUME_DOWN);
+        assertTrue(mAction2Triggered);
+
+        pressKeys(eventTime, KEYCODE_POWER, eventTime, KEYCODE_VOLUME_UP, SCHEDULE_TIME + 50);
+        assertTrue(mAction3Triggered);
+    }
+
+    /**
+     *  Nothing should happen if there is no definition.
+     */
+    @Test
+    public void testNotTrigger_NoRule() {
+        final long eventTime = SystemClock.uptimeMillis();
+        pressKeys(eventTime, KEYCODE_BACK, eventTime, KEYCODE_VOLUME_DOWN);
+        assertFalse(mAction1Triggered);
+        assertFalse(mAction2Triggered);
+        assertFalse(mAction3Triggered);
+    }
+
+    /**
+     *  Nothing should happen if the interval of press time is too long.
+     */
+    @Test
+    public void testNotTrigger_Interval() {
+        final long eventTime = SystemClock.uptimeMillis();
+        final long earlyEventTime = eventTime - 200; // COMBINE_KEY_DELAY_MILLIS = 150;
+        pressKeys(earlyEventTime, KEYCODE_POWER, eventTime, KEYCODE_VOLUME_DOWN);
+        assertFalse(mAction1Triggered);
+    }
+
+    /**
+     *  Nothing should happen if the condition is false.
+     */
+    @Test
+    public void testNotTrigger_Condition() {
+        final long eventTime = SystemClock.uptimeMillis();
+        // we won't trigger action 2 because the condition is false.
+        mPreCondition = false;
+        pressKeys(eventTime, KEYCODE_VOLUME_UP, eventTime, KEYCODE_VOLUME_DOWN);
+        assertFalse(mAction2Triggered);
+    }
+
+    /**
+     *  Nothing should happen if the keys released too early.
+     */
+    @Test
+    public void testNotTrigger_EarlyRelease() {
+        final long eventTime = SystemClock.uptimeMillis();
+        pressKeys(eventTime, KEYCODE_POWER, eventTime, KEYCODE_VOLUME_UP);
+        assertFalse(mAction3Triggered);
+    }
+}
diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
index 5c39bd0..6dd23ba 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
@@ -423,6 +423,7 @@
 
         final WindowState homeWindow = createWindow(null, TYPE_BASE_APPLICATION, homeActivity,
                 "homeWindow");
+        makeWindowVisible(homeWindow);
         homeActivity.addWindow(homeWindow);
         homeWindow.getAttrs().flags |= FLAG_SHOW_WALLPAPER;
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotControllerTest.java
index 0bb2867..ec65085 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotControllerTest.java
@@ -30,6 +30,8 @@
 import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertSame;
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.when;
 
 import android.app.ActivityManager;
 import android.app.WindowConfiguration;
@@ -183,6 +185,24 @@
         }
     }
 
+    @UseTestDisplay(addWindows = {W_ACTIVITY, W_INPUT_METHOD})
+    @Test
+    public void testCreateTaskSnapshotWithExcludingIme() {
+        Task task = mAppWindow.mActivityRecord.getTask();
+        spyOn(task);
+        spyOn(mDisplayContent);
+        when(task.getDisplayContent().isImeAttachedToApp()).thenReturn(false);
+        // Intentionally set the SurfaceControl of input method window as null.
+        mDisplayContent.mInputMethodWindow.setSurfaceControl(null);
+        // Verify no NPE happens when calling createTaskSnapshot.
+        try {
+            mWm.mTaskSnapshotController.createTaskSnapshot(mAppWindow.mActivityRecord.getTask(),
+                    1f /* scaleFraction */, PixelFormat.UNKNOWN, null /* outTaskSize */);
+        } catch (NullPointerException e) {
+            fail("There should be no exception when calling createTaskSnapshot");
+        }
+    }
+
     @UseTestDisplay(addWindows = W_ACTIVITY)
     @Test
     public void testPrepareTaskSnapshot() {
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
index 227eba2..a57de09 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
@@ -19,9 +19,10 @@
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
 import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
-import static android.hardware.camera2.params.OutputConfiguration.ROTATION_90;
 import static android.view.InsetsState.ITYPE_STATUS_BAR;
 import static android.view.Surface.ROTATION_0;
+import static android.view.Surface.ROTATION_270;
+import static android.view.Surface.ROTATION_90;
 import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
 import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
 import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
@@ -480,33 +481,49 @@
         final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
         final SurfaceControl.Transaction t = spy(StubTransaction.class);
 
-        app.mHasSurface = true;
+        makeWindowVisible(app);
         app.mSurfaceControl = mock(SurfaceControl.class);
-        try {
-            app.getFrame().set(10, 20, 60, 80);
-            app.updateSurfacePosition(t);
+        final Rect frame = app.getFrame();
+        frame.set(10, 20, 60, 80);
+        app.updateSurfacePosition(t);
+        assertTrue(app.mLastSurfacePosition.equals(frame.left, frame.top));
+        app.seamlesslyRotateIfAllowed(t, ROTATION_0, ROTATION_90, true /* requested */);
+        assertTrue(app.mSeamlesslyRotated);
 
-            app.seamlesslyRotateIfAllowed(t, ROTATION_0, ROTATION_90, true);
+        // Verify we un-rotate the window state surface.
+        final Matrix matrix = new Matrix();
+        // Un-rotate 90 deg.
+        matrix.setRotate(270);
+        // Translate it back to origin.
+        matrix.postTranslate(0, mDisplayInfo.logicalWidth);
+        verify(t).setMatrix(eq(app.mSurfaceControl), eq(matrix), any(float[].class));
 
-            assertTrue(app.mSeamlesslyRotated);
+        // Verify we update the position as well.
+        final float[] curSurfacePos = {app.mLastSurfacePosition.x, app.mLastSurfacePosition.y};
+        matrix.mapPoints(curSurfacePos);
+        verify(t).setPosition(eq(app.mSurfaceControl), eq(curSurfacePos[0]), eq(curSurfacePos[1]));
 
-            // Verify we un-rotate the window state surface.
-            Matrix matrix = new Matrix();
-            // Un-rotate 90 deg
-            matrix.setRotate(270);
-            // Translate it back to origin
-            matrix.postTranslate(0, mDisplayInfo.logicalWidth);
-            verify(t).setMatrix(eq(app.mSurfaceControl), eq(matrix), any(float[].class));
+        app.finishSeamlessRotation(false /* timeout */);
+        assertFalse(app.mSeamlesslyRotated);
+        assertNull(app.mPendingSeamlessRotate);
 
-            // Verify we update the position as well.
-            float[] currentSurfacePos = {app.mLastSurfacePosition.x, app.mLastSurfacePosition.y};
-            matrix.mapPoints(currentSurfacePos);
-            verify(t).setPosition(eq(app.mSurfaceControl), eq(currentSurfacePos[0]),
-                    eq(currentSurfacePos[1]));
-        } finally {
-            app.mSurfaceControl = null;
-            app.mHasSurface = false;
-        }
+        // Simulate the case with deferred layout and animation.
+        app.resetSurfacePositionForAnimationLeash(t);
+        clearInvocations(t);
+        mWm.mWindowPlacerLocked.deferLayout();
+        app.updateSurfacePosition(t);
+        // Because layout is deferred, the position should keep the reset value.
+        assertTrue(app.mLastSurfacePosition.equals(0, 0));
+
+        app.seamlesslyRotateIfAllowed(t, ROTATION_0, ROTATION_270, true /* requested */);
+        // The last position must be updated so the surface can be unrotated properly.
+        assertTrue(app.mLastSurfacePosition.equals(frame.left, frame.top));
+        matrix.setRotate(90);
+        matrix.postTranslate(mDisplayInfo.logicalHeight, 0);
+        curSurfacePos[0] = frame.left;
+        curSurfacePos[1] = frame.top;
+        matrix.mapPoints(curSurfacePos);
+        verify(t).setPosition(eq(app.mSurfaceControl), eq(curSurfacePos[0]), eq(curSurfacePos[1]));
     }
 
     @Test
diff --git a/services/voiceinteraction/OWNERS b/services/voiceinteraction/OWNERS
new file mode 100644
index 0000000..ef1061b
--- /dev/null
+++ b/services/voiceinteraction/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/service/voice/OWNERS
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
index 06c23de..b5bb2a8 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
@@ -49,7 +49,6 @@
 import android.hardware.soundtrigger.SoundTrigger.ModuleProperties;
 import android.hardware.soundtrigger.SoundTrigger.RecognitionConfig;
 import android.media.permission.Identity;
-import android.media.permission.IdentityContext;
 import android.media.permission.PermissionUtil;
 import android.media.permission.SafeCloseable;
 import android.os.Binder;
@@ -92,7 +91,7 @@
 import com.android.server.SystemService;
 import com.android.server.UiThread;
 import com.android.server.pm.UserManagerInternal;
-import com.android.server.pm.permission.PermissionManagerServiceInternal;
+import com.android.server.pm.permission.LegacyPermissionManagerInternal;
 import com.android.server.soundtrigger.SoundTriggerInternal;
 import com.android.server.utils.TimingsTraceAndSlog;
 import com.android.server.wm.ActivityTaskManagerInternal;
@@ -141,10 +140,10 @@
         mUserManagerInternal = Objects.requireNonNull(
                 LocalServices.getService(UserManagerInternal.class));
 
-        PermissionManagerServiceInternal permissionManagerInternal = LocalServices.getService(
-                PermissionManagerServiceInternal.class);
+        LegacyPermissionManagerInternal permissionManagerInternal = LocalServices.getService(
+                LegacyPermissionManagerInternal.class);
         permissionManagerInternal.setVoiceInteractionPackagesProvider(
-                new PermissionManagerServiceInternal.PackagesProvider() {
+                new LegacyPermissionManagerInternal.PackagesProvider() {
             @Override
             public String[] getPackages(int userId) {
                 mServiceStub.initForUser(userId);
diff --git a/services/wifi/OWNERS b/services/wifi/OWNERS
new file mode 100644
index 0000000..2ae7065
--- /dev/null
+++ b/services/wifi/OWNERS
@@ -0,0 +1 @@
+include /wifi/OWNERS
diff --git a/telecomm/TEST_MAPPING b/telecomm/TEST_MAPPING
index c9903f9..1963ff3 100644
--- a/telecomm/TEST_MAPPING
+++ b/telecomm/TEST_MAPPING
@@ -23,7 +23,9 @@
           "exclude-annotation": "androidx.test.filters.FlakyTest"
         }
       ]
-    },
+    }
+  ],
+  "presubmit-large": [
     {
       "name": "CtsTelecomTestCases",
       "options": [
diff --git a/telecomm/java/android/telecom/ConnectionService.java b/telecomm/java/android/telecom/ConnectionService.java
index 6288bc1..b1ccb53 100755
--- a/telecomm/java/android/telecom/ConnectionService.java
+++ b/telecomm/java/android/telecom/ConnectionService.java
@@ -1988,8 +1988,10 @@
             connection.setAudioModeIsVoip(true);
         }
         connection.setTelecomCallId(callId);
+        PhoneAccountHandle phoneAccountHandle = connection.getPhoneAccountHandle() == null
+                            ? request.getAccountHandle() : connection.getPhoneAccountHandle();
         if (connection.getState() != Connection.STATE_DISCONNECTED) {
-            addConnection(request.getAccountHandle(), callId, connection);
+            addConnection(phoneAccountHandle, callId, connection);
         }
 
         Uri address = connection.getAddress();
@@ -2005,7 +2007,7 @@
                 callId,
                 request,
                 new ParcelableConnection(
-                        request.getAccountHandle(),
+                        phoneAccountHandle,
                         connection.getState(),
                         connection.getConnectionCapabilities(),
                         connection.getConnectionProperties(),
diff --git a/telecomm/java/android/telecom/OWNERS b/telecomm/java/android/telecom/OWNERS
new file mode 100644
index 0000000..6656a01
--- /dev/null
+++ b/telecomm/java/android/telecom/OWNERS
@@ -0,0 +1,6 @@
+# Bug component: 20868
+
[email protected]
[email protected]
[email protected]
[email protected]
diff --git a/telephony/common/com/android/internal/telephony/TelephonyPermissions.java b/telephony/common/com/android/internal/telephony/TelephonyPermissions.java
index 0c46394..4bb7cc4 100644
--- a/telephony/common/com/android/internal/telephony/TelephonyPermissions.java
+++ b/telephony/common/com/android/internal/telephony/TelephonyPermissions.java
@@ -244,7 +244,9 @@
      * <ul>
      *   <li>return true: if the caller has the READ_PRIVILEGED_PHONE_STATE permission, the calling
      *       package passes a DevicePolicyManager Device Owner / Profile Owner device identifier
-     *       access check, or the calling package has carrier privileges on any active subscription.
+     *       access check, or the calling package has carrier privileges on any active
+     *       subscription, or the calling package has the {@link
+     *       Manifest.permission#USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER} appop permission.
      *   <li>throw SecurityException: if the caller does not meet any of the requirements and is
      *       targeting Q or is targeting pre-Q and does not have the READ_PHONE_STATE permission
      *       or carrier privileges of any active subscription.
@@ -256,6 +258,10 @@
      */
     public static boolean checkCallingOrSelfReadDeviceIdentifiers(Context context, int subId,
             String callingPackage, @Nullable String callingFeatureId, String message) {
+        if (checkCallingOrSelfUseIccAuthWithDeviceIdentifier(context, callingPackage,
+                callingFeatureId, message)) {
+            return true;
+        }
         return checkPrivilegedReadPermissionOrCarrierPrivilegePermission(
                 context, subId, callingPackage, callingFeatureId, message, true);
     }
@@ -267,7 +273,9 @@
      * <ul>
      *   <li>return true: if the caller has the READ_PRIVILEGED_PHONE_STATE permission, the calling
      *       package passes a DevicePolicyManager Device Owner / Profile Owner device identifier
-     *       access check, or the calling package has carrier privileges on specified subscription.
+     *       access check, or the calling package has carrier privileges on specified subscription,
+     *       or the calling package has the {@link
+     *       Manifest.permission#USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER} appop permission.
      *   <li>throw SecurityException: if the caller does not meet any of the requirements and is
      *       targeting Q or is targeting pre-Q and does not have the READ_PHONE_STATE permission.
      *   <li>return false: if the caller is targeting pre-Q and does have the READ_PHONE_STATE
@@ -278,6 +286,10 @@
      */
     public static boolean checkCallingOrSelfReadSubscriberIdentifiers(Context context, int subId,
             String callingPackage, @Nullable String callingFeatureId, String message) {
+        if (checkCallingOrSelfUseIccAuthWithDeviceIdentifier(context, callingPackage,
+                callingFeatureId, message)) {
+            return true;
+        }
         return checkPrivilegedReadPermissionOrCarrierPrivilegePermission(
                 context, subId, callingPackage, callingFeatureId, message, false);
     }
@@ -385,6 +397,26 @@
     }
 
     /**
+     * Check whether the caller (or self, if not processing an IPC) has {@link
+     * Manifest.permission#USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER} AppOp permission.
+     *
+     * <p>With the permission, the caller can access device/subscriber identifiers and use ICC
+     * authentication like EAP-AKA.
+     */
+    public static boolean checkCallingOrSelfUseIccAuthWithDeviceIdentifier(Context context,
+            String callingPackage, String callingFeatureId, String message) {
+        // Cannot perform appop check if the calling package is null
+        if (callingPackage == null) {
+            return false;
+        }
+        int callingUid = Binder.getCallingUid();
+        AppOpsManager appOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
+        int opMode = appOps.noteOpNoThrow(AppOpsManager.OPSTR_USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER,
+                callingUid, callingPackage, callingFeatureId, message);
+        return opMode == AppOpsManager.MODE_ALLOWED;
+    }
+
+    /**
      * Check whether the app with the given pid/uid can read the call log.
      * @return {@code true} if the specified app has the read call log permission and AppOpp granted
      *      to it, {@code false} otherwise.
diff --git a/telephony/java/android/service/euicc/OWNERS b/telephony/java/android/service/euicc/OWNERS
new file mode 100644
index 0000000..6aa399d
--- /dev/null
+++ b/telephony/java/android/service/euicc/OWNERS
@@ -0,0 +1,5 @@
+# Bug component: 20868
+
[email protected]
[email protected]
[email protected]
diff --git a/telephony/java/android/service/sms/OWNERS b/telephony/java/android/service/sms/OWNERS
new file mode 100644
index 0000000..6aa399d
--- /dev/null
+++ b/telephony/java/android/service/sms/OWNERS
@@ -0,0 +1,5 @@
+# Bug component: 20868
+
[email protected]
[email protected]
[email protected]
diff --git a/telephony/java/android/telephony/OWNERS b/telephony/java/android/telephony/OWNERS
new file mode 100644
index 0000000..6aa399d
--- /dev/null
+++ b/telephony/java/android/telephony/OWNERS
@@ -0,0 +1,5 @@
+# Bug component: 20868
+
[email protected]
[email protected]
[email protected]
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 8c655ad..b48df71 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -2011,6 +2011,8 @@
      *     active subscription.
      *     <li>If the calling app is the default SMS role holder (see {@link
      *     RoleManager#isRoleHeld(String)}).
+     *     <li>If the calling app has been granted the
+     *      {@link Manifest.permission#USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER} permission.
      * </ul>
      *
      * <p>If the calling app does not meet one of these requirements then this method will behave
@@ -4021,6 +4023,8 @@
      *     <li>If the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
      *     <li>If the calling app is the default SMS role holder (see {@link
      *     RoleManager#isRoleHeld(String)}).
+     *     <li>If the calling app has been granted the
+     *     {@link Manifest.permission#USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER} permission.
      * </ul>
      *
      * <p>If the calling app does not meet one of these requirements then this method will behave
@@ -4045,33 +4049,8 @@
      * for a subscription.
      * Return null if it is unavailable.
      *
-     * <p>Starting with API level 29, persistent device identifiers are guarded behind additional
-     * restrictions, and apps are recommended to use resettable identifiers (see <a
-     * href="/training/articles/user-data-ids">Best practices for unique identifiers</a>). This
-     * method can be invoked if one of the following requirements is met:
-     * <ul>
-     *     <li>If the calling app has been granted the READ_PRIVILEGED_PHONE_STATE permission; this
-     *     is a privileged permission that can only be granted to apps preloaded on the device.
-     *     <li>If the calling app is the device or profile owner and has been granted the
-     *     {@link Manifest.permission#READ_PHONE_STATE} permission. The profile owner is an app that
-     *     owns a managed profile on the device; for more details see <a
-     *     href="https://developer.android.com/work/managed-profiles">Work profiles</a>.
-     *     Profile owner access is deprecated and will be removed in a future release.
-     *     <li>If the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
-     *     <li>If the calling app is the default SMS role holder (see {@link
-     *     RoleManager#isRoleHeld(String)}).
-     * </ul>
-     *
-     * <p>If the calling app does not meet one of these requirements then this method will behave
-     * as follows:
-     *
-     * <ul>
-     *     <li>If the calling app's target SDK is API level 28 or lower and the app has the
-     *     READ_PHONE_STATE permission then null is returned.</li>
-     *     <li>If the calling app's target SDK is API level 28 or lower and the app does not have
-     *     the READ_PHONE_STATE permission, or if the calling app is targeting API level 29 or
-     *     higher, then a SecurityException is thrown.</li>
-     * </ul>
+     * See {@link #getSubscriberId()} for details on the required permissions and behavior
+     * when the caller does not hold sufficient permissions.
      *
      * @param subId whose subscriber id is returned
      * @hide
@@ -5596,57 +5575,6 @@
         }
     }
 
-    /**
-     * Registers a listener object to receive notification of changes
-     * in specified telephony states.
-     * <p>
-     * To register a listener, pass a {@link PhoneStateListener} and specify at least one telephony
-     * state of interest in the events argument.
-     *
-     * At registration, and when a specified telephony state changes, the telephony manager invokes
-     * the appropriate callback method on the listener object and passes the current (updated)
-     * values.
-     * <p>
-     * To un-register a listener, pass the listener object and set the events argument to
-     * {@link PhoneStateListener#LISTEN_NONE LISTEN_NONE} (0).
-     *
-     * If this TelephonyManager object has been created with {@link #createForSubscriptionId},
-     * applies to the given subId. Otherwise, applies to
-     * {@link SubscriptionManager#getDefaultSubscriptionId()}. To listen events for multiple subIds,
-     * pass a separate listener object to each TelephonyManager object created with
-     * {@link #createForSubscriptionId}.
-     *
-     * Note: if you call this method while in the middle of a binder transaction, you <b>must</b>
-     * call {@link android.os.Binder#clearCallingIdentity()} before calling this method. A
-     * {@link SecurityException} will be thrown otherwise.
-     *
-     * This API should be used sparingly -- large numbers of listeners will cause system
-     * instability. If a process has registered too many listeners without unregistering them, it
-     * may encounter an {@link IllegalStateException} when trying to register more listeners.
-     *
-     * @param events The telephony state(s) of interest to the listener,
-     *               as a bitwise-OR combination of {@link PhoneStateListener}
-     *               LISTEN_ flags.
-     * @param listener The {@link PhoneStateListener} object to register
-     *                 (or unregister)
-     * @deprecated Use {@link #registerPhoneStateListener(Executor, PhoneStateListener)}.
-     */
-    @Deprecated
-    public void listen(long events, @NonNull PhoneStateListener listener) {
-        mTelephonyRegistryMgr = mContext.getSystemService(TelephonyRegistryManager.class);
-        if (mTelephonyRegistryMgr != null) {
-            if (events != PhoneStateListener.LISTEN_NONE) {
-                mTelephonyRegistryMgr.registerPhoneStateListenerWithEvents(mSubId,
-                        getOpPackageName(), getAttributionTag(), listener,
-                        Long.valueOf(events).intValue(), getITelephony() != null);
-            } else {
-                unregisterPhoneStateListener(listener);
-            }
-        } else {
-            throw new IllegalStateException("telephony service is null.");
-        }
-    }
-
     /** @hide */
     @Retention(RetentionPolicy.SOURCE)
     @IntDef(prefix = {"ERI_"}, value = {
@@ -7230,8 +7158,13 @@
      * Returns the response of authentication for the default subscription.
      * Returns null if the authentication hasn't been successful
      *
-     * <p>Requires Permission: READ_PRIVILEGED_PHONE_STATE or that the calling
-     * app has carrier privileges (see {@link #hasCarrierPrivileges}).
+     * <p>Requires one of the following permissions:
+     * <ul>
+     *     <li>READ_PRIVILEGED_PHONE_STATE
+     *     <li>the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
+     *     <li>the calling app has been granted the
+     *     {@link Manifest.permission#USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER} permission.
+     * </ul>
      *
      * @param appType the icc application type, like {@link #APPTYPE_USIM}
      * @param authType the authentication type, {@link #AUTHTYPE_EAP_AKA} or
@@ -7256,7 +7189,8 @@
      * Returns the response of USIM Authentication for specified subId.
      * Returns null if the authentication hasn't been successful
      *
-     * <p>Requires that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
+     * <p>See {@link #getIccAuthentication(int, int, String)} for details on the required
+     * permissions.
      *
      * @param subId subscription ID used for authentication
      * @param appType the icc application type, like {@link #APPTYPE_USIM}
@@ -7279,7 +7213,8 @@
             IPhoneSubInfo info = getSubscriberInfoService();
             if (info == null)
                 return null;
-            return info.getIccSimChallengeResponse(subId, appType, authType, data);
+            return info.getIccSimChallengeResponse(subId, appType, authType, data,
+                    getOpPackageName(), getAttributionTag());
         } catch (RemoteException ex) {
             return null;
         } catch (NullPointerException ex) {
@@ -10027,6 +9962,16 @@
      */
     public static final int CARD_POWER_UP_PASS_THROUGH = 2;
 
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = {"CARD_POWER"},
+            value = {
+                    CARD_POWER_DOWN,
+                    CARD_POWER_UP,
+                    CARD_POWER_UP_PASS_THROUGH,
+            })
+    public @interface SimPowerState {}
+
     /**
      * Set SIM card power state.
      *
@@ -10037,12 +9982,17 @@
      * Callers should monitor for {@link TelephonyIntents#ACTION_SIM_STATE_CHANGED}
      * broadcasts to determine success or failure and timeout if needed.
      *
+     * @deprecated prefer {@link setSimPowerState(int, Executor, Consumer<Integer>)}.
+     * There is no guarantee that SIM power changes will trigger ACTION_SIM_STATE_CHANGED on new
+     * devices.
+     *
      * <p>Requires Permission:
      *   {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
      *
      * {@hide}
      **/
     @SystemApi
+    @Deprecated
     @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
     public void setSimPowerState(int state) {
         setSimPowerStateForSlot(getSlotIndex(), state);
@@ -10059,12 +10009,16 @@
      * Callers should monitor for {@link TelephonyIntents#ACTION_SIM_STATE_CHANGED}
      * broadcasts to determine success or failure and timeout if needed.
      *
+     * @deprecated prefer {@link setSimPowerStateForSlot(int, int, Executor, Consumer<Integer>)}.
+     * changes will trigger ACTION_SIM_STATE_CHANGED on new devices.
+     *
      * <p>Requires Permission:
      *   {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
      *
      * {@hide}
      **/
     @SystemApi
+    @Deprecated
     @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
     public void setSimPowerStateForSlot(int slotIndex, int state) {
         try {
@@ -10080,6 +10034,85 @@
     }
 
     /**
+     * Set SIM card power state.
+     *
+     * @param state  State of SIM (power down, power up, pass through)
+     * @see #CARD_POWER_DOWN
+     * @see #CARD_POWER_UP
+     * @see #CARD_POWER_UP_PASS_THROUGH
+     * @param executor The executor of where the callback will execute.
+     * @param callback Callback will be triggered once it succeeds or failed.
+     * @see #SET_SIM_POWER_STATE_SUCCESS
+     * @see #SET_SIM_POWER_STATE_ALREADY_IN_STATE
+     * @see #SET_SIM_POWER_STATE_MODEM_ERROR
+     * @see #SET_SIM_POWER_STATE_SIM_ERROR
+     * @see #SET_SIM_POWER_STATE_NOT_SUPPORTED
+     * @throws IllegalArgumentException if requested SIM state is invalid
+     *
+     * <p>Requires Permission:
+     *   {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
+     *
+     * {@hide}
+     **/
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+    public void setSimPowerState(@SimPowerState int state, @NonNull Executor executor,
+            @NonNull @SetSimPowerStateResult Consumer<Integer> callback) {
+        setSimPowerStateForSlot(getSlotIndex(), state, executor, callback);
+    }
+
+    /**
+     * Set SIM card power state.
+     *
+     * @param slotIndex SIM slot id
+     * @param state  State of SIM (power down, power up, pass through)
+     * @see #CARD_POWER_DOWN
+     * @see #CARD_POWER_UP
+     * @see #CARD_POWER_UP_PASS_THROUGH
+     * @param executor The executor of where the callback will execute.
+     * @param callback Callback will be triggered once it succeeds or failed.
+     * @see #SET_SIM_POWER_STATE_SUCCESS
+     * @see #SET_SIM_POWER_STATE_ALREADY_IN_STATE
+     * @see #SET_SIM_POWER_STATE_MODEM_ERROR
+     * @see #SET_SIM_POWER_STATE_SIM_ERROR
+     * @see #SET_SIM_POWER_STATE_NOT_SUPPORTED
+     * @throws IllegalArgumentException if requested SIM state is invalid
+     *
+     * <p>Requires Permission:
+     *   {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
+     *
+     * {@hide}
+     **/
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+    public void setSimPowerStateForSlot(int slotIndex, @SimPowerState int state,
+            @NonNull Executor executor,
+            @NonNull @SetSimPowerStateResult Consumer<Integer> callback) {
+        if (state != CARD_POWER_DOWN && state != CARD_POWER_UP
+                && state != CARD_POWER_UP_PASS_THROUGH) {
+            throw new IllegalArgumentException("requested SIM state is invalid");
+        }
+        try {
+            ITelephony telephony = getITelephony();
+            IIntegerConsumer internalCallback = new IIntegerConsumer.Stub() {
+                @Override
+                public void accept(int result) {
+                    executor.execute(() ->
+                            Binder.withCleanCallingIdentity(() -> callback.accept(result)));
+                }
+            };
+            if (telephony != null) {
+                telephony.setSimPowerStateForSlotWithCallback(slotIndex, state, internalCallback);
+            }
+        } catch (RemoteException e) {
+            Log.e(TAG, "Error calling ITelephony#setSimPowerStateForSlot", e);
+        } catch (SecurityException e) {
+            Log.e(TAG, "Permission error calling ITelephony#setSimPowerStateForSlot",
+                    e);
+        }
+    }
+
+    /**
      * Set baseband version for the default phone.
      *
      * @param version baseband version
@@ -11198,6 +11231,55 @@
     public @interface SetCarrierRestrictionResult {}
 
     /**
+     * The SIM power state was successfully set.
+     * @hide
+     */
+    @SystemApi
+    public static final int SET_SIM_POWER_STATE_SUCCESS = 0;
+
+    /**
+     * The SIM is already in the requested power state.
+     * @hide
+     */
+    @SystemApi
+    public static final int SET_SIM_POWER_STATE_ALREADY_IN_STATE = 1;
+
+    /**
+     * Failed to connect to the modem to make the power state request. This may happen if the
+     * modem has an error. The user may want to make the request again later.
+     * @hide
+     */
+    @SystemApi
+    public static final int SET_SIM_POWER_STATE_MODEM_ERROR = 2;
+
+    /**
+     * Failed to connect to the SIM to make the power state request. This may happen if the
+     * SIM has been removed. The user may want to make the request again later.
+     * @hide
+     */
+    @SystemApi
+    public static final int SET_SIM_POWER_STATE_SIM_ERROR = 3;
+
+    /**
+     * The modem version does not support synchronous power.
+     * @hide
+     */
+    @SystemApi
+    public static final int SET_SIM_POWER_STATE_NOT_SUPPORTED = 4;
+
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = {"SET_SIM_POWER_STATE_"},
+            value = {
+                    SET_SIM_POWER_STATE_SUCCESS,
+                    SET_SIM_POWER_STATE_ALREADY_IN_STATE,
+                    SET_SIM_POWER_STATE_MODEM_ERROR,
+                    SET_SIM_POWER_STATE_SIM_ERROR,
+                    SET_SIM_POWER_STATE_NOT_SUPPORTED
+            })
+    public @interface SetSimPowerStateResult {}
+
+    /**
      * Set the allowed carrier list and the excluded carrier list indicating the priority between
      * the two lists.
      * Requires system privileges.
diff --git a/telephony/java/android/telephony/cdma/OWNERS b/telephony/java/android/telephony/cdma/OWNERS
new file mode 100644
index 0000000..6aa399d
--- /dev/null
+++ b/telephony/java/android/telephony/cdma/OWNERS
@@ -0,0 +1,5 @@
+# Bug component: 20868
+
[email protected]
[email protected]
[email protected]
diff --git a/telephony/java/android/telephony/data/OWNERS b/telephony/java/android/telephony/data/OWNERS
new file mode 100644
index 0000000..932b35c
--- /dev/null
+++ b/telephony/java/android/telephony/data/OWNERS
@@ -0,0 +1,5 @@
+# Bug component: 20868
+
[email protected]
[email protected]
[email protected]
diff --git a/telephony/java/android/telephony/emergency/OWNERS b/telephony/java/android/telephony/emergency/OWNERS
new file mode 100644
index 0000000..fa07dce
--- /dev/null
+++ b/telephony/java/android/telephony/emergency/OWNERS
@@ -0,0 +1,5 @@
+# Bug component: 20868
+
[email protected]
[email protected]
[email protected]
diff --git a/telephony/java/android/telephony/euicc/OWNERS b/telephony/java/android/telephony/euicc/OWNERS
new file mode 100644
index 0000000..9e51a4b
--- /dev/null
+++ b/telephony/java/android/telephony/euicc/OWNERS
@@ -0,0 +1,6 @@
+# Bug component: 20868
+
[email protected]
[email protected]
[email protected]
[email protected]
diff --git a/telephony/java/android/telephony/gsm/OWNERS b/telephony/java/android/telephony/gsm/OWNERS
new file mode 100644
index 0000000..6aa399d
--- /dev/null
+++ b/telephony/java/android/telephony/gsm/OWNERS
@@ -0,0 +1,5 @@
+# Bug component: 20868
+
[email protected]
[email protected]
[email protected]
diff --git a/telephony/java/android/telephony/ims/ImsReasonInfo.java b/telephony/java/android/telephony/ims/ImsReasonInfo.java
index 184477a..c140249 100644
--- a/telephony/java/android/telephony/ims/ImsReasonInfo.java
+++ b/telephony/java/android/telephony/ims/ImsReasonInfo.java
@@ -1322,6 +1322,13 @@
      */
     public static final int EXTRA_CODE_CALL_RETRY_BY_SETTINGS = 3;
 
+    /**
+     * An extra that may be populated when the {@link #CODE_LOCAL_CALL_CS_RETRY_REQUIRED} result has
+     * been returned.
+     * <p>
+     * Try to connect the call using CS as emergency
+     */
+    public static final int EXTRA_CODE_CALL_RETRY_EMERGENCY = 4;
 
     // For main reason code
     /** @hide */
diff --git a/telephony/java/android/telephony/ims/OWNERS b/telephony/java/android/telephony/ims/OWNERS
new file mode 100644
index 0000000..0854c5d
--- /dev/null
+++ b/telephony/java/android/telephony/ims/OWNERS
@@ -0,0 +1,5 @@
+# Bug component: 20868
+
[email protected]
[email protected]
[email protected]
diff --git a/telephony/java/android/telephony/ims/aidl/IImsRcsFeature.aidl b/telephony/java/android/telephony/ims/aidl/IImsRcsFeature.aidl
index b47e3c7..10c50be 100644
--- a/telephony/java/android/telephony/ims/aidl/IImsRcsFeature.aidl
+++ b/telephony/java/android/telephony/ims/aidl/IImsRcsFeature.aidl
@@ -22,7 +22,6 @@
 import android.telephony.ims.aidl.IImsCapabilityCallback;
 import android.telephony.ims.aidl.IOptionsResponseCallback;
 import android.telephony.ims.aidl.IPublishResponseCallback;
-import android.telephony.ims.aidl.IRcsFeatureListener;
 import android.telephony.ims.aidl.ISubscribeResponseCallback;
 import android.telephony.ims.feature.CapabilityChangeRequest;
 
@@ -34,7 +33,6 @@
  */
 interface IImsRcsFeature {
     // Not oneway because we need to verify this completes before doing anything else.
-    void setListener(IRcsFeatureListener listener);
     int queryCapabilityStatus();
     // Inherited from ImsFeature
     int getFeatureState();
@@ -50,14 +48,4 @@
     oneway void subscribeForCapabilities(in List<Uri> uris, ISubscribeResponseCallback cb);
     oneway void sendOptionsCapabilityRequest(in Uri contactUri,
             in List<String> myCapabilities, IOptionsResponseCallback cb);
-    // RcsPresenceExchangeImplBase specific api
-    oneway void requestCapabilities(in List<Uri> uris, int operationToken);
-    oneway void updateCapabilities(in RcsContactUceCapability capabilities, int operationToken);
-    // RcsSipOptionsImplBase specific api
-    oneway void sendCapabilityRequest(in Uri contactUri,
-            in RcsContactUceCapability capabilities, int operationToken);
-    oneway void respondToCapabilityRequest(in String contactUri,
-            in RcsContactUceCapability ownCapabilities, int operationToken);
-    oneway void respondToCapabilityRequestWithError(in Uri contactUri, int code, in String reason,
-            int operationToken);
 }
diff --git a/telephony/java/android/telephony/ims/aidl/IRcsFeatureListener.aidl b/telephony/java/android/telephony/ims/aidl/IRcsFeatureListener.aidl
deleted file mode 100644
index 70cf651..0000000
--- a/telephony/java/android/telephony/ims/aidl/IRcsFeatureListener.aidl
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (c) 2018 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.telephony.ims.aidl;
-
-import android.net.Uri;
-import android.telephony.ims.RcsContactUceCapability;
-
-import java.util.List;
-
-/**
- * Listener interface for updates from the RcsFeature back to the framework.
- * {@hide}
- */
-interface IRcsFeatureListener {
-    //RcsCapabilityExchange specific
-    oneway void onCommandUpdate(int commandCode, int operationToken);
-    // RcsPresenceExchangeImplBase Specific
-    oneway void onNetworkResponse(int code, in String reason, int operationToken);
-    oneway void onCapabilityRequestResponsePresence(in List<RcsContactUceCapability> infos,
-    int operationToken);
-    oneway void onNotifyUpdateCapabilities(int publishTriggerType);
-    oneway void onUnpublish();
-    // RcsSipOptionsImplBase specific
-    oneway void onCapabilityRequestResponseOptions(int code, in String reason,
-            in RcsContactUceCapability info, int operationToken);
-    oneway void onRemoteCapabilityRequest(in Uri contactUri, in RcsContactUceCapability remoteInfo,
-            int operationToken);
-}
diff --git a/telephony/java/android/telephony/ims/aidl/OWNERS b/telephony/java/android/telephony/ims/aidl/OWNERS
new file mode 100644
index 0000000..0854c5d
--- /dev/null
+++ b/telephony/java/android/telephony/ims/aidl/OWNERS
@@ -0,0 +1,5 @@
+# Bug component: 20868
+
[email protected]
[email protected]
[email protected]
diff --git a/telephony/java/android/telephony/ims/compat/OWNERS b/telephony/java/android/telephony/ims/compat/OWNERS
new file mode 100644
index 0000000..0854c5d
--- /dev/null
+++ b/telephony/java/android/telephony/ims/compat/OWNERS
@@ -0,0 +1,5 @@
+# Bug component: 20868
+
[email protected]
[email protected]
[email protected]
diff --git a/telephony/java/android/telephony/ims/compat/feature/OWNERS b/telephony/java/android/telephony/ims/compat/feature/OWNERS
new file mode 100644
index 0000000..0854c5d
--- /dev/null
+++ b/telephony/java/android/telephony/ims/compat/feature/OWNERS
@@ -0,0 +1,5 @@
+# Bug component: 20868
+
[email protected]
[email protected]
[email protected]
diff --git a/telephony/java/android/telephony/ims/compat/stub/OWNERS b/telephony/java/android/telephony/ims/compat/stub/OWNERS
new file mode 100644
index 0000000..0854c5d
--- /dev/null
+++ b/telephony/java/android/telephony/ims/compat/stub/OWNERS
@@ -0,0 +1,5 @@
+# Bug component: 20868
+
[email protected]
[email protected]
[email protected]
diff --git a/telephony/java/android/telephony/ims/feature/OWNERS b/telephony/java/android/telephony/ims/feature/OWNERS
new file mode 100644
index 0000000..0854c5d
--- /dev/null
+++ b/telephony/java/android/telephony/ims/feature/OWNERS
@@ -0,0 +1,5 @@
+# Bug component: 20868
+
[email protected]
[email protected]
[email protected]
diff --git a/telephony/java/android/telephony/ims/feature/RcsFeature.java b/telephony/java/android/telephony/ims/feature/RcsFeature.java
index 5de2ddc..cde7067 100644
--- a/telephony/java/android/telephony/ims/feature/RcsFeature.java
+++ b/telephony/java/android/telephony/ims/feature/RcsFeature.java
@@ -19,17 +19,16 @@
 import android.annotation.CallbackExecutor;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.net.Uri;
 import android.os.RemoteException;
-import android.telephony.ims.RcsContactUceCapability;
 import android.telephony.ims.RcsUceAdapter;
 import android.telephony.ims.aidl.ICapabilityExchangeEventListener;
 import android.telephony.ims.aidl.IImsCapabilityCallback;
 import android.telephony.ims.aidl.IImsRcsFeature;
 import android.telephony.ims.aidl.IOptionsResponseCallback;
 import android.telephony.ims.aidl.IPublishResponseCallback;
-import android.telephony.ims.aidl.IRcsFeatureListener;
 import android.telephony.ims.aidl.ISubscribeResponseCallback;
 import android.telephony.ims.aidl.RcsOptionsResponseAidlWrapper;
 import android.telephony.ims.aidl.RcsPublishResponseAidlWrapper;
@@ -74,16 +73,6 @@
             mExecutor = executor;
         }
 
-        /**
-         * @deprecated This method is deprecated. Please call the method
-         * setCapabilityExchangeEventListener instead.
-         */
-        @Override
-        @Deprecated
-        public void setListener(IRcsFeatureListener listener) {
-            Log.w(LOG_TAG, "The method setListener is deprecated");
-        }
-
         @Override
         public int queryCapabilityStatus() throws RemoteException {
             return executeMethodAsyncForResult(
@@ -124,7 +113,7 @@
         // RcsCapabilityExchangeImplBase specific APIs
         @Override
         public void setCapabilityExchangeEventListener(
-                @NonNull ICapabilityExchangeEventListener listener) throws RemoteException {
+                @Nullable ICapabilityExchangeEventListener listener) throws RemoteException {
             executeMethodAsync(() -> mReference.setCapabilityExchangeEventListener(listener),
                     "setCapabilityExchangeEventListener");
         }
@@ -155,34 +144,6 @@
                     "sendOptionsCapabilityRequest");
         }
 
-        // RcsPresenceExchangeImplBase specific APIS
-        @Override
-        public void requestCapabilities(List<Uri> uris, int operationToken) throws RemoteException {
-            throw new RemoteException("Unsupported operation: requestCapabilities");
-        }
-        @Override
-        public void updateCapabilities(RcsContactUceCapability capabilities, int operationToken)
-                throws RemoteException {
-            throw new RemoteException("Unsupported operation: updateCapabilities");
-        }
-        // RcsSipOptionsImplBase specific APIS
-        @Override
-        public void sendCapabilityRequest(Uri contactUri, RcsContactUceCapability capabilities,
-                int operationToken) throws RemoteException {
-            throw new RemoteException("Unsupported operation: sendCapabilityRequest");
-        }
-        @Override
-        public void respondToCapabilityRequest(String contactUri,
-                RcsContactUceCapability ownCapabilities, int operationToken)
-                throws RemoteException {
-            throw new RemoteException("Unsupported operation: respondToCapabilityRequest");
-        }
-        @Override
-        public void respondToCapabilityRequestWithError(Uri contactUri, int code, String reason,
-                int operationToken) throws RemoteException {
-            throw new RemoteException("Unsupported operation: respondToCapabilityRequestWithError");
-        }
-
         // Call the methods with a clean calling identity on the executor and wait indefinitely for
         // the future to return.
         private void executeMethodAsync(Runnable r, String errorLogName)
diff --git a/telephony/java/android/telephony/ims/stub/OWNERS b/telephony/java/android/telephony/ims/stub/OWNERS
new file mode 100644
index 0000000..0854c5d
--- /dev/null
+++ b/telephony/java/android/telephony/ims/stub/OWNERS
@@ -0,0 +1,5 @@
+# Bug component: 20868
+
[email protected]
[email protected]
[email protected]
diff --git a/telephony/java/android/telephony/ims/stub/RcsCapabilityExchange.java b/telephony/java/android/telephony/ims/stub/RcsCapabilityExchange.java
deleted file mode 100644
index 0b13efb..0000000
--- a/telephony/java/android/telephony/ims/stub/RcsCapabilityExchange.java
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright (C) 2018 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.telephony.ims.stub;
-
-import android.annotation.IntDef;
-import android.os.RemoteException;
-import android.telephony.ims.ImsException;
-import android.telephony.ims.aidl.IRcsFeatureListener;
-import android.telephony.ims.feature.ImsFeature;
-import android.telephony.ims.feature.RcsFeature;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * Base class for different types of Capability exchange, presence using
- * {@link RcsPresenceExchangeImplBase} and SIP OPTIONS exchange using {@link RcsSipOptionsImplBase}.
- *
- * @hide
- */
-public class RcsCapabilityExchange {
-
-    /**  Service is unknown. */
-    public static final int COMMAND_CODE_SERVICE_UNKNOWN = 0;
-    /** The command completed successfully. */
-    public static final int COMMAND_CODE_SUCCESS = 1;
-    /** The command failed with an unknown error. */
-    public static final int COMMAND_CODE_GENERIC_FAILURE = 2;
-    /**  Invalid parameter(s). */
-    public static final int COMMAND_CODE_INVALID_PARAM = 3;
-    /**  Fetch error. */
-    public static final int COMMAND_CODE_FETCH_ERROR = 4;
-    /**  Request timed out. */
-    public static final int COMMAND_CODE_REQUEST_TIMEOUT = 5;
-    /**  Failure due to insufficient memory available. */
-    public static final int COMMAND_CODE_INSUFFICIENT_MEMORY = 6;
-    /**  Network connection is lost. */
-    public static final int COMMAND_CODE_LOST_NETWORK_CONNECTION = 7;
-    /**  Requested feature/resource is not supported. */
-    public static final int COMMAND_CODE_NOT_SUPPORTED = 8;
-    /**  Contact or resource is not found. */
-    public static final int COMMAND_CODE_NOT_FOUND = 9;
-    /**  Service is not available. */
-    public static final int COMMAND_CODE_SERVICE_UNAVAILABLE = 10;
-    /**  No Change in Capabilities */
-    public static final int COMMAND_CODE_NO_CHANGE_IN_CAP = 11;
-
-    /** @hide*/
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef(prefix = "COMMAND_CODE_", value = {
-            COMMAND_CODE_SERVICE_UNKNOWN,
-            COMMAND_CODE_SUCCESS,
-            COMMAND_CODE_GENERIC_FAILURE,
-            COMMAND_CODE_INVALID_PARAM,
-            COMMAND_CODE_FETCH_ERROR,
-            COMMAND_CODE_REQUEST_TIMEOUT,
-            COMMAND_CODE_INSUFFICIENT_MEMORY,
-            COMMAND_CODE_LOST_NETWORK_CONNECTION,
-            COMMAND_CODE_NOT_SUPPORTED,
-            COMMAND_CODE_NOT_FOUND,
-            COMMAND_CODE_SERVICE_UNAVAILABLE,
-            COMMAND_CODE_NO_CHANGE_IN_CAP
-    })
-    public @interface CommandCode {}
-
-
-    private RcsFeature mFeature;
-
-    /** @hide */
-    public final void initialize(RcsFeature feature) {
-        mFeature = feature;
-    }
-
-    /** @hide */
-    protected final IRcsFeatureListener getListener() throws ImsException {
-        throw new ImsException("This method is deprecated.",
-                ImsException.CODE_ERROR_UNSUPPORTED_OPERATION);
-    }
-
-    /**
-     * Provides the framework with an update as to whether or not a command completed successfully
-     * locally. This includes capabilities requests and updates from the network. If it does not
-     * complete successfully, then the framework may retry the command again later, depending on the
-     * error. If the command does complete successfully, the framework will then wait for network
-     * updates.
-     *
-     * @param code The result of the pending command. If {@link #COMMAND_CODE_SUCCESS}, further
-     *             updates will be sent for this command using the associated operationToken.
-     * @param operationToken the token associated with the pending command.
-     * @throws ImsException If this {@link RcsCapabilityExchange} instance is not currently
-     * connected to the framework. This can happen if the {@link RcsFeature} is not
-     * {@link ImsFeature#STATE_READY} and the {@link RcsFeature} has not received the
-     * {@link ImsFeature#onFeatureReady()} callback. This may also happen in rare cases when the
-     * Telephony stack has crashed.
-     */
-    public final void onCommandUpdate(@CommandCode int code, int operationToken)
-            throws ImsException {
-        try {
-            getListener().onCommandUpdate(code, operationToken);
-        } catch (RemoteException e) {
-            throw new ImsException(e.getMessage(), ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
-        }
-    }
-}
diff --git a/telephony/java/android/telephony/ims/stub/RcsPresenceExchangeImplBase.java b/telephony/java/android/telephony/ims/stub/RcsPresenceExchangeImplBase.java
deleted file mode 100644
index bb03448..0000000
--- a/telephony/java/android/telephony/ims/stub/RcsPresenceExchangeImplBase.java
+++ /dev/null
@@ -1,294 +0,0 @@
-/*
- * Copyright (C) 2018 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.telephony.ims.stub;
-
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-import android.net.Uri;
-import android.os.RemoteException;
-import android.telephony.ims.ImsException;
-import android.telephony.ims.RcsContactUceCapability;
-import android.telephony.ims.feature.ImsFeature;
-import android.telephony.ims.feature.RcsFeature;
-import android.util.Log;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.List;
-
-/**
- * Base implementation for RCS User Capability Exchange using Presence. Any ImsService implementing
- * this service must implement the stub methods {@link #requestCapabilities(List, int)}  and
- * {@link #updateCapabilities(RcsContactUceCapability, int)}.
- *
- * @hide
- */
-public class RcsPresenceExchangeImplBase extends RcsCapabilityExchange {
-
-    private static final String LOG_TAG = "RcsPresenceExchangeIB";
-
-    /**
-     * The request has resulted in any other 4xx/5xx/6xx that is not covered below. No retry will be
-     * attempted.
-     */
-    public static final int RESPONSE_SUBSCRIBE_GENERIC_FAILURE = -1;
-
-    /**
-     * The request has succeeded with a “200” message from the network.
-     */
-    public static final int RESPONSE_SUCCESS = 0;
-
-    /**
-     * The request has resulted in a “403” (User Not Registered) error from the network. Will retry
-     * capability polling with an exponential backoff.
-     */
-    public static final int RESPONSE_NOT_REGISTERED = 1;
-
-    /**
-     * The request has resulted in a “403” (not authorized (Requestor)) error from the network. No
-     * retry will be attempted.
-     */
-    public static final int RESPONSE_NOT_AUTHORIZED_FOR_PRESENCE = 2;
-
-    /**
-     * The request has resulted in a "403” (Forbidden) or other “403” error from the network and
-     * will be handled the same as “404” Not found. No retry will be attempted.
-     */
-    public static final int RESPONSE_FORBIDDEN = 3;
-
-    /**
-     * The request has resulted in a “404” (Not found) result from the network. No retry will be
-     * attempted.
-     */
-    public static final int RESPONSE_NOT_FOUND = 4;
-
-    /**
-     * The request has resulted in a “408” response. Retry after exponential backoff.
-     */
-    public static final int RESPONSE_SIP_REQUEST_TIMEOUT = 5;
-
-    /**
-     *  The network has responded with a “413” (Too Large) response from the network. Capability
-     *  request contains too many items and must be shrunk before the request will be accepted.
-     */
-    public static final int RESPONSE_SUBSCRIBE_TOO_LARGE = 6;
-
-    /**
-     * The request has resulted in a “423” response. Retry after exponential backoff.
-     */
-    public static final int RESPONSE_SIP_INTERVAL_TOO_SHORT = 7;
-
-    /**
-     * The request has resulted in a “503” response. Retry after exponential backoff.
-     */
-    public static final int RESPONSE_SIP_SERVICE_UNAVAILABLE = 8;
-
-    /** @hide*/
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef(prefix = "RESPONSE_", value = {
-            RESPONSE_SUBSCRIBE_GENERIC_FAILURE,
-            RESPONSE_SUCCESS,
-            RESPONSE_NOT_REGISTERED,
-            RESPONSE_NOT_AUTHORIZED_FOR_PRESENCE,
-            RESPONSE_FORBIDDEN,
-            RESPONSE_NOT_FOUND,
-            RESPONSE_SIP_REQUEST_TIMEOUT,
-            RESPONSE_SUBSCRIBE_TOO_LARGE,
-            RESPONSE_SIP_INTERVAL_TOO_SHORT,
-            RESPONSE_SIP_SERVICE_UNAVAILABLE
-    })
-    public @interface PresenceResponseCode {}
-
-
-    /** A capability update has been requested due to the Entity Tag (ETag) expiring. */
-    public static final int CAPABILITY_UPDATE_TRIGGER_ETAG_EXPIRED = 0;
-    /** A capability update has been requested due to moving to LTE with VoPS disabled. */
-    public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_LTE_VOPS_DISABLED = 1;
-    /** A capability update has been requested due to moving to LTE with VoPS enabled. */
-    public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_LTE_VOPS_ENABLED = 2;
-    /** A capability update has been requested due to moving to eHRPD. */
-    public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_EHRPD = 3;
-    /** A capability update has been requested due to moving to HSPA+. */
-    public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_HSPAPLUS = 4;
-    /** A capability update has been requested due to moving to 3G. */
-    public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_3G = 5;
-    /** A capability update has been requested due to moving to 2G. */
-    public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_2G = 6;
-    /** A capability update has been requested due to moving to WLAN */
-    public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_WLAN = 7;
-    /** A capability update has been requested due to moving to IWLAN */
-    public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_IWLAN = 8;
-    /** A capability update has been requested but the reason is unknown. */
-    public static final int CAPABILITY_UPDATE_TRIGGER_UNKNOWN = 9;
-    /** A capability update has been requested due to moving to 5G NR with VoPS disabled. */
-    public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_NR5G_VOPS_DISABLED = 10;
-    /** A capability update has been requested due to moving to 5G NR with VoPS enabled. */
-    public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_NR5G_VOPS_ENABLED = 11;
-
-    /** @hide*/
-    @IntDef(value = {
-            CAPABILITY_UPDATE_TRIGGER_ETAG_EXPIRED,
-            CAPABILITY_UPDATE_TRIGGER_MOVE_TO_LTE_VOPS_DISABLED,
-            CAPABILITY_UPDATE_TRIGGER_MOVE_TO_LTE_VOPS_ENABLED,
-            CAPABILITY_UPDATE_TRIGGER_MOVE_TO_EHRPD,
-            CAPABILITY_UPDATE_TRIGGER_MOVE_TO_HSPAPLUS,
-            CAPABILITY_UPDATE_TRIGGER_MOVE_TO_3G,
-            CAPABILITY_UPDATE_TRIGGER_MOVE_TO_2G,
-            CAPABILITY_UPDATE_TRIGGER_MOVE_TO_WLAN,
-            CAPABILITY_UPDATE_TRIGGER_MOVE_TO_IWLAN,
-            CAPABILITY_UPDATE_TRIGGER_UNKNOWN,
-            CAPABILITY_UPDATE_TRIGGER_MOVE_TO_NR5G_VOPS_DISABLED,
-            CAPABILITY_UPDATE_TRIGGER_MOVE_TO_NR5G_VOPS_ENABLED
-    }, prefix = "CAPABILITY_UPDATE_TRIGGER_")
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface StackPublishTriggerType {
-    }
-
-    /**
-     * Provide the framework with a subsequent network response update to
-     * {@link #updateCapabilities(RcsContactUceCapability, int)} and
-     * {@link #requestCapabilities(List, int)} operations.
-     *
-     * @param code The SIP response code sent from the network for the operation token specified.
-     * @param reason The optional reason response from the network. If the network provided no
-     *         reason with the code, the string should be empty.
-     * @param operationToken The token associated with the operation this service is providing a
-     *         response for.
-     * @throws ImsException If this {@link RcsPresenceExchangeImplBase} instance is not currently
-     * connected to the framework. This can happen if the {@link RcsFeature} is not
-     * {@link ImsFeature#STATE_READY} and the {@link RcsFeature} has not received the
-     * {@link ImsFeature#onFeatureReady()} callback. This may also happen in rare cases when the
-     * Telephony stack has crashed.
-     */
-    public final void onNetworkResponse(@PresenceResponseCode int code, @NonNull String reason,
-            int operationToken) throws ImsException {
-        try {
-            getListener().onNetworkResponse(code, reason, operationToken);
-        } catch (RemoteException e) {
-            throw new ImsException(e.getMessage(), ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
-        }
-    }
-
-    /**
-     * Provides the framework with the requested contacts’ capabilities requested by the framework
-     * using {@link #requestCapabilities(List, int)}.
-     *
-     * @throws ImsException If this {@link RcsPresenceExchangeImplBase} instance is not currently
-     * connected to the framework. This can happen if the {@link RcsFeature} is not
-     * {@link ImsFeature#STATE_READY} and the {@link RcsFeature} has not received the
-     * {@link ImsFeature#onFeatureReady()} callback. This may also happen in rare cases when the
-     * Telephony stack has crashed.
-     */
-    public final void onCapabilityRequestResponse(@NonNull List<RcsContactUceCapability> infos,
-            int operationToken) throws ImsException {
-        try {
-            getListener().onCapabilityRequestResponsePresence(infos, operationToken);
-        } catch (RemoteException e) {
-            throw new ImsException(e.getMessage(), ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
-        }
-    }
-
-    /**
-     * Trigger the framework to provide a capability update using
-     * {@link #updateCapabilities(RcsContactUceCapability, int)}.
-     * <p>
-     * This is typically used when trying to generate an initial PUBLISH for a new subscription to
-     * the network. The device will cache all presence publications after boot until this method is
-     * called once.
-     * @param publishTriggerType {@link StackPublishTriggerType} The reason for the capability
-     *         update request.
-     * @throws ImsException If this {@link RcsPresenceExchangeImplBase} instance is not currently
-     * connected to the framework. This can happen if the {@link RcsFeature} is not
-     * {@link ImsFeature#STATE_READY} and the {@link RcsFeature} has not received the
-     * {@link ImsFeature#onFeatureReady()} callback. This may also happen in rare cases when the
-     * Telephony stack has crashed.
-     */
-    public final void onNotifyUpdateCapabilites(@StackPublishTriggerType int publishTriggerType)
-            throws ImsException {
-        try {
-            getListener().onNotifyUpdateCapabilities(publishTriggerType);
-        } catch (RemoteException e) {
-            throw new ImsException(e.getMessage(), ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
-        }
-    }
-
-    /**
-     * Notify the framework that the device’s capabilities have been unpublished from the network.
-     *
-     * @throws ImsException If this {@link RcsPresenceExchangeImplBase} instance is not currently
-     * connected to the framework. This can happen if the {@link RcsFeature} is not
-     * {@link ImsFeature#STATE_READY} and the {@link RcsFeature} has not received the
-     * {@link ImsFeature#onFeatureReady()} callback. This may also happen in rare cases when the
-     * Telephony stack has crashed.
-     */
-    public final void onUnpublish() throws ImsException {
-        try {
-            getListener().onUnpublish();
-        } catch (RemoteException e) {
-            throw new ImsException(e.getMessage(), ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
-        }
-    }
-
-    /**
-     * The user capabilities of one or multiple contacts have been requested by the framework.
-     * <p>
-     * The implementer must follow up this call with an {@link #onCommandUpdate(int, int)} call to
-     * indicate whether or not this operation succeeded.  If this operation succeeds, network
-     * response updates should be sent to the framework using
-     * {@link #onNetworkResponse(int, String, int)}. When the operation is completed,
-     * {@link #onCapabilityRequestResponse(List, int)} should be called with the presence
-     * information for the contacts specified.
-     * @param uris A {@link List} of the {@link Uri}s that the framework is requesting the UCE
-     *             capabilities for.
-     * @param operationToken The token associated with this operation. Updates to this request using
-     *         {@link #onCommandUpdate(int, int)}, {@link #onNetworkResponse(int, String, int)}, and
-     *         {@link #onCapabilityRequestResponse(List, int)}  must use the same operation token
-     *         in response.
-     */
-    public void requestCapabilities(@NonNull List<Uri> uris, int operationToken) {
-        // Stub - to be implemented by service
-        Log.w(LOG_TAG, "requestCapabilities called with no implementation.");
-        try {
-            getListener().onCommandUpdate(COMMAND_CODE_NOT_SUPPORTED, operationToken);
-        } catch (RemoteException | ImsException e) {
-            // Do not do anything, this is a stub implementation.
-        }
-    }
-
-    /**
-     * The capabilities of this device have been updated and should be published to the network.
-     * <p>
-     * The implementer must follow up this call with an {@link #onCommandUpdate(int, int)} call to
-     * indicate whether or not this operation succeeded. If this operation succeeds, network
-     * response updates should be sent to the framework using
-     * {@link #onNetworkResponse(int, String, int)}.
-     * @param capabilities The capabilities for this device.
-     * @param operationToken The token associated with this operation. Any subsequent
-     *         {@link #onCommandUpdate(int, int)} or {@link #onNetworkResponse(int, String, int)}
-     *         calls regarding this update must use the same token.
-     */
-    public void updateCapabilities(@NonNull RcsContactUceCapability capabilities,
-            int operationToken) {
-        // Stub - to be implemented by service
-        Log.w(LOG_TAG, "updateCapabilities called with no implementation.");
-        try {
-            getListener().onCommandUpdate(COMMAND_CODE_NOT_SUPPORTED, operationToken);
-        } catch (RemoteException | ImsException e) {
-            // Do not do anything, this is a stub implementation.
-        }
-    }
-}
diff --git a/telephony/java/android/telephony/ims/stub/RcsSipOptionsImplBase.java b/telephony/java/android/telephony/ims/stub/RcsSipOptionsImplBase.java
deleted file mode 100644
index 2035fac..0000000
--- a/telephony/java/android/telephony/ims/stub/RcsSipOptionsImplBase.java
+++ /dev/null
@@ -1,208 +0,0 @@
-/*
- * Copyright (C) 2018 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.telephony.ims.stub;
-
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.net.Uri;
-import android.os.RemoteException;
-import android.telephony.ims.ImsException;
-import android.telephony.ims.RcsContactUceCapability;
-import android.telephony.ims.feature.ImsFeature;
-import android.telephony.ims.feature.RcsFeature;
-import android.util.Log;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * Base implementation for RCS User Capability Exchange using SIP OPTIONS.
- *
- * @hide
- */
-public class RcsSipOptionsImplBase extends RcsCapabilityExchange {
-
-    private static final String LOG_TAG = "RcsSipOptionsImplBase";
-
-    /**
-     * Indicates a SIP response from the remote user other than 200, 480, 408, 404, or 604.
-     */
-    public static final int RESPONSE_GENERIC_FAILURE = -1;
-
-    /**
-     * Indicates that the remote user responded with a 200 OK response.
-     */
-    public static final int RESPONSE_SUCCESS = 0;
-
-    /**
-     * Indicates that the remote user responded with a 480 TEMPORARY UNAVAILABLE response.
-     */
-    public static final int RESPONSE_TEMPORARILY_UNAVAILABLE = 1;
-
-    /**
-     * Indicates that the remote user responded with a 408 REQUEST TIMEOUT response.
-     */
-    public static final int RESPONSE_REQUEST_TIMEOUT = 2;
-
-    /**
-     * Indicates that the remote user responded with a 404 NOT FOUND response.
-     */
-    public static final int RESPONSE_NOT_FOUND = 3;
-
-    /**
-     * Indicates that the remote user responded with a 604 DOES NOT EXIST ANYWHERE response.
-     */
-    public static final int RESPONSE_DOES_NOT_EXIST_ANYWHERE = 4;
-
-    /**
-     * Indicates that the remote user responded with a 400 BAD REQUEST response.
-     */
-    public static final int RESPONSE_BAD_REQUEST = 5;
-
-    /** @hide*/
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef(prefix = "RESPONSE_", value = {
-            RESPONSE_GENERIC_FAILURE,
-            RESPONSE_SUCCESS,
-            RESPONSE_TEMPORARILY_UNAVAILABLE,
-            RESPONSE_REQUEST_TIMEOUT,
-            RESPONSE_NOT_FOUND,
-            RESPONSE_DOES_NOT_EXIST_ANYWHERE,
-            RESPONSE_BAD_REQUEST
-    })
-    public @interface SipResponseCode {}
-
-    /**
-     * Send the response of a SIP OPTIONS capability exchange to the framework. If {@code code} is
-     * {@link #RESPONSE_SUCCESS}, info must be non-null.
-     * @param code The SIP response code that was sent by the network in response to the request
-     *        sent by {@link #sendCapabilityRequest(Uri, RcsContactUceCapability, int)}.
-     * @param reason The optional SIP response reason sent by the network. If none was sent, this
-     *        should be an empty string.
-     * @param info the contact's UCE capabilities associated with the capability request.
-     * @param operationToken The token associated with the original capability request, set by
-     *        {@link #sendCapabilityRequest(Uri, RcsContactUceCapability, int)}.
-     * @throws ImsException If this {@link RcsSipOptionsImplBase} instance is not currently
-     * connected to the framework. This can happen if the {@link RcsFeature} is not
-     * {@link ImsFeature#STATE_READY} and the {@link RcsFeature} has not received the
-     * {@link ImsFeature#onFeatureReady()} callback. This may also happen in rare cases when the
-     * Telephony stack has crashed.
-     */
-    public final void onCapabilityRequestResponse(@SipResponseCode int code, @NonNull String reason,
-            @Nullable RcsContactUceCapability info, int operationToken) throws ImsException {
-        try {
-            getListener().onCapabilityRequestResponseOptions(code, reason, info, operationToken);
-        } catch (RemoteException e) {
-            throw new ImsException(e.getMessage(), ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
-        }
-    }
-
-    /**
-     * Inform the framework of a query for this device's UCE capabilities.
-     * <p>
-     * The framework will respond via the
-     * {@link #respondToCapabilityRequest(String, RcsContactUceCapability, int)} or
-     * {@link #respondToCapabilityRequestWithError(Uri, int, String, int)} method.
-     * @param contactUri The URI associated with the remote contact that is requesting capabilities.
-     * @param remoteInfo The remote contact's capability information.
-     * @param operationToken An unique operation token that you have generated that will be returned
-     *         by the framework in
-     *         {@link #respondToCapabilityRequest(String, RcsContactUceCapability, int)}.
-     * @throws ImsException If this {@link RcsSipOptionsImplBase} instance is not currently
-     * connected to the framework. This can happen if the {@link RcsFeature} is not
-     * {@link ImsFeature#STATE_READY} and the {@link RcsFeature} has not received the
-     * {@link ImsFeature#onFeatureReady()} callback. This may also happen in rare cases when the
-     * Telephony stack has crashed.
-     */
-    public final void onRemoteCapabilityRequest(@NonNull Uri contactUri,
-            @NonNull RcsContactUceCapability remoteInfo, int operationToken) throws ImsException {
-        try {
-            getListener().onRemoteCapabilityRequest(contactUri, remoteInfo, operationToken);
-        } catch (RemoteException e) {
-            throw new ImsException(e.getMessage(), ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
-        }
-    }
-
-    /**
-     * Push one's own capabilities to a remote user via the SIP OPTIONS presence exchange mechanism
-     * in order to receive the capabilities of the remote user in response.
-     * <p>
-     * The implementer must call
-     * {@link #onCapabilityRequestResponse(int, String, RcsContactUceCapability, int)} to send the
-     * response of this query back to the framework.
-     * @param contactUri The URI of the remote user that we wish to get the capabilities of.
-     * @param capabilities The capabilities of this device to send to the remote user.
-     * @param operationToken A token generated by the framework that will be passed through
-     * {@link #onCapabilityRequestResponse(int, String, RcsContactUceCapability, int)} when this
-     *         operation has succeeded.
-     */
-    public void sendCapabilityRequest(@NonNull Uri contactUri,
-            @NonNull RcsContactUceCapability capabilities, int operationToken) {
-        // Stub - to be implemented by service
-        Log.w(LOG_TAG, "sendCapabilityRequest called with no implementation.");
-        try {
-            getListener().onCommandUpdate(COMMAND_CODE_NOT_SUPPORTED, operationToken);
-        } catch (RemoteException | ImsException e) {
-            // Do not do anything, this is a stub implementation.
-        }
-    }
-
-    /**
-     * Respond to a remote capability request from the contact specified with the capabilities of
-     * this device.
-     * <p>
-     * The framework will use the same token and uri as what was passed in to
-     * {@link #onRemoteCapabilityRequest(Uri, RcsContactUceCapability, int)}.
-     * @param contactUri The URI of the remote contact.
-     * @param ownCapabilities The capabilities of this device.
-     * @param operationToken The token generated by the framework that this service obtained when
-     *         {@link #onRemoteCapabilityRequest(Uri, RcsContactUceCapability, int)} was called.
-     */
-    public void respondToCapabilityRequest(@NonNull String contactUri,
-            @NonNull RcsContactUceCapability ownCapabilities, int operationToken) {
-        // Stub - to be implemented by service
-        Log.w(LOG_TAG, "respondToCapabilityRequest called with no implementation.");
-        try {
-            getListener().onCommandUpdate(COMMAND_CODE_NOT_SUPPORTED, operationToken);
-        } catch (RemoteException | ImsException e) {
-            // Do not do anything, this is a stub implementation.
-        }
-    }
-
-    /**
-     * Respond to a remote capability request from the contact specified with the specified error.
-     * <p>
-     * The framework will use the same token and uri as what was passed in to
-     * {@link #onRemoteCapabilityRequest(Uri, RcsContactUceCapability, int)}.
-     * @param contactUri A URI containing the remote contact.
-     * @param code The SIP response code to respond with.
-     * @param reason A non-null String containing the reason associated with the SIP code.
-     * @param operationToken The token provided by the framework when
-     *         {@link #onRemoteCapabilityRequest(Uri, RcsContactUceCapability, int)} was called.
-     */
-    public void respondToCapabilityRequestWithError(@NonNull Uri contactUri,
-            @SipResponseCode int code, @NonNull String reason, int operationToken) {
-        // Stub - to be implemented by service
-        Log.w(LOG_TAG, "respondToCapabiltyRequestWithError called with no implementation.");
-        try {
-            getListener().onCommandUpdate(COMMAND_CODE_NOT_SUPPORTED, operationToken);
-        } catch (RemoteException | ImsException e) {
-            // Do not do anything, this is a stub implementation.
-        }
-    }
-}
diff --git a/telephony/java/android/telephony/mbms/OWNERS b/telephony/java/android/telephony/mbms/OWNERS
new file mode 100644
index 0000000..718e0a2
--- /dev/null
+++ b/telephony/java/android/telephony/mbms/OWNERS
@@ -0,0 +1,5 @@
+# Bug component: 20868
+
[email protected]
[email protected]
[email protected]
diff --git a/telephony/java/android/telephony/mbms/vendor/OWNERS b/telephony/java/android/telephony/mbms/vendor/OWNERS
new file mode 100644
index 0000000..718e0a2
--- /dev/null
+++ b/telephony/java/android/telephony/mbms/vendor/OWNERS
@@ -0,0 +1,5 @@
+# Bug component: 20868
+
[email protected]
[email protected]
[email protected]
diff --git a/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl b/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl
index 09f9b42..ce2017b 100644
--- a/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl
+++ b/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl
@@ -216,5 +216,6 @@
      * @param data authentication challenge data
      * @return challenge response
      */
-    String getIccSimChallengeResponse(int subId, int appType, int authType, String data);
+    String getIccSimChallengeResponse(int subId, int appType, int authType, String data,
+            String callingPackage, String callingFeatureId);
 }
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 66311ad..2da45ca 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -1676,10 +1676,19 @@
      * @param slotIndex SIM slot id
      * @param state  State of SIM (power down, power up, pass through)
      * @hide
-     * */
+     */
     void setSimPowerStateForSlot(int slotIndex, int state);
 
     /**
+     * Set SIM card power state.
+     * @param slotIndex SIM slot id
+     * @param state  State of SIM (power down, power up, pass through)
+     * @param callback callback to receive result info
+     * @hide
+     */
+    void setSimPowerStateForSlotWithCallback(int slotIndex, int state, IIntegerConsumer callback);
+
+    /**
      * Returns a list of Forbidden PLMNs from the specified SIM App
      * Returns null if the query fails.
      *
diff --git a/tests/ActivityManagerPerfTests/OWNERS b/tests/ActivityManagerPerfTests/OWNERS
new file mode 100644
index 0000000..72c0a9e
--- /dev/null
+++ b/tests/ActivityManagerPerfTests/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/am/OWNERS
diff --git a/tests/AmSlam/OWNERS b/tests/AmSlam/OWNERS
new file mode 100644
index 0000000..72c0a9e
--- /dev/null
+++ b/tests/AmSlam/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/am/OWNERS
diff --git a/tests/BackgroundDexOptServiceIntegrationTests/src/com/android/server/pm/BackgroundDexOptServiceIntegrationTests.java b/tests/BackgroundDexOptServiceIntegrationTests/src/com/android/server/pm/BackgroundDexOptServiceIntegrationTests.java
index 7d826f7..e05816e 100644
--- a/tests/BackgroundDexOptServiceIntegrationTests/src/com/android/server/pm/BackgroundDexOptServiceIntegrationTests.java
+++ b/tests/BackgroundDexOptServiceIntegrationTests/src/com/android/server/pm/BackgroundDexOptServiceIntegrationTests.java
@@ -264,9 +264,9 @@
             // Set time to future.
             setTimeFutureDays(deltaDays);
 
-            // Set filter to quicken.
-            compilePackageWithFilter(PACKAGE_NAME, "quicken");
-            Assert.assertEquals("quicken", getCompilerFilter(PACKAGE_NAME));
+            // Set filter to verify.
+            compilePackageWithFilter(PACKAGE_NAME, "verify");
+            Assert.assertEquals("verify", getCompilerFilter(PACKAGE_NAME));
 
             // Fill up storage to trigger low storage threshold.
             fillUpToLowStorage();
@@ -290,9 +290,9 @@
             // Set time to future.
             setTimeFutureDays(deltaDays);
 
-            // Set filter to quicken.
-            compilePackageWithFilter(PACKAGE_NAME, "quicken");
-            Assert.assertEquals("quicken", getCompilerFilter(PACKAGE_NAME));
+            // Set filter to speed-profile.
+            compilePackageWithFilter(PACKAGE_NAME, "speed-profile");
+            Assert.assertEquals("speed-profile", getCompilerFilter(PACKAGE_NAME));
 
             // Fill up storage to trigger low storage threshold.
             fillUpToLowStorage();
diff --git a/tests/BlobStoreTestUtils/OWNERS b/tests/BlobStoreTestUtils/OWNERS
new file mode 100644
index 0000000..65bb6b8
--- /dev/null
+++ b/tests/BlobStoreTestUtils/OWNERS
@@ -0,0 +1 @@
+include /apex/blobstore/OWNERS
diff --git a/tests/Camera2Tests/OWNERS b/tests/Camera2Tests/OWNERS
new file mode 100644
index 0000000..f48a95c
--- /dev/null
+++ b/tests/Camera2Tests/OWNERS
@@ -0,0 +1 @@
+include platform/frameworks/av:/camera/OWNERS
diff --git a/tests/CanvasCompare/OWNERS b/tests/CanvasCompare/OWNERS
new file mode 100644
index 0000000..c88a9f8
--- /dev/null
+++ b/tests/CanvasCompare/OWNERS
@@ -0,0 +1 @@
+include /libs/hwui/OWNERS
diff --git a/tests/Compatibility/OWNERS b/tests/Compatibility/OWNERS
new file mode 100644
index 0000000..f8c3520
--- /dev/null
+++ b/tests/Compatibility/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/compat/OWNERS
diff --git a/tests/DozeTest/OWNERS b/tests/DozeTest/OWNERS
new file mode 100644
index 0000000..2e96c97
--- /dev/null
+++ b/tests/DozeTest/OWNERS
@@ -0,0 +1 @@
+include /packages/SystemUI/OWNERS
diff --git a/tests/FixVibrateSetting/OWNERS b/tests/FixVibrateSetting/OWNERS
new file mode 100644
index 0000000..cc63ceb
--- /dev/null
+++ b/tests/FixVibrateSetting/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/vibrator/OWNERS
diff --git a/tests/FlickerTests/OWNERS b/tests/FlickerTests/OWNERS
new file mode 100644
index 0000000..0862c05
--- /dev/null
+++ b/tests/FlickerTests/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/wm/OWNERS
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ReOpenImeWindowTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ReOpenImeWindowTest.kt
index 7b5dc872..7bd96f5 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ReOpenImeWindowTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ReOpenImeWindowTest.kt
@@ -16,6 +16,7 @@
 
 package com.android.server.wm.flicker.ime
 
+import androidx.test.filters.FlakyTest
 import android.view.Surface
 import androidx.test.filters.RequiresDevice
 import androidx.test.platform.app.InstrumentationRegistry
@@ -42,6 +43,7 @@
 @RequiresDevice
 @RunWith(Parameterized::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
+@FlakyTest(bugId = 175027130)
 class ReOpenImeWindowTest(
     testName: String,
     flickerSpec: Flicker
diff --git a/tests/HugeBackup/OWNERS b/tests/HugeBackup/OWNERS
new file mode 100644
index 0000000..d99779e
--- /dev/null
+++ b/tests/HugeBackup/OWNERS
@@ -0,0 +1 @@
+include /services/backup/OWNERS
diff --git a/tests/HwAccelerationTest/OWNERS b/tests/HwAccelerationTest/OWNERS
new file mode 100644
index 0000000..c88a9f8
--- /dev/null
+++ b/tests/HwAccelerationTest/OWNERS
@@ -0,0 +1 @@
+include /libs/hwui/OWNERS
diff --git a/tests/Input/OWNERS b/tests/Input/OWNERS
new file mode 100644
index 0000000..d701f23
--- /dev/null
+++ b/tests/Input/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/hardware/input/OWNERS
diff --git a/tests/JobSchedulerPerfTests/OWNERS b/tests/JobSchedulerPerfTests/OWNERS
new file mode 100644
index 0000000..6f207fb1
--- /dev/null
+++ b/tests/JobSchedulerPerfTests/OWNERS
@@ -0,0 +1 @@
+include /apex/jobscheduler/OWNERS
diff --git a/tests/JobSchedulerTestApp/OWNERS b/tests/JobSchedulerTestApp/OWNERS
new file mode 100644
index 0000000..6f207fb1
--- /dev/null
+++ b/tests/JobSchedulerTestApp/OWNERS
@@ -0,0 +1 @@
+include /apex/jobscheduler/OWNERS
diff --git a/tests/LocationTracker/OWNERS b/tests/LocationTracker/OWNERS
new file mode 100644
index 0000000..5ac60284
--- /dev/null
+++ b/tests/LocationTracker/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/location/OWNERS
diff --git a/tests/LowStorageTest/OWNERS b/tests/LowStorageTest/OWNERS
new file mode 100644
index 0000000..6f9dbea
--- /dev/null
+++ b/tests/LowStorageTest/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/os/storage/OWNERS
diff --git a/tests/NetworkSecurityConfigTest/OWNERS b/tests/NetworkSecurityConfigTest/OWNERS
new file mode 100644
index 0000000..aa87958
--- /dev/null
+++ b/tests/NetworkSecurityConfigTest/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/net/OWNERS
diff --git a/tests/PackageWatchdog/OWNERS b/tests/PackageWatchdog/OWNERS
new file mode 100644
index 0000000..d04a706
--- /dev/null
+++ b/tests/PackageWatchdog/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/rollback/OWNERS
diff --git a/tests/PackageWatchdog/src/com/android/server/OWNERS b/tests/PackageWatchdog/src/com/android/server/OWNERS
new file mode 100644
index 0000000..5cf4dcf
--- /dev/null
+++ b/tests/PackageWatchdog/src/com/android/server/OWNERS
@@ -0,0 +1 @@
+per-file PackageWatchdogTest.java = file:/services/core/java/com/android/server/rollback/OWNERS
diff --git a/tests/PlatformCompatGating/OWNERS b/tests/PlatformCompatGating/OWNERS
new file mode 100644
index 0000000..f8c3520
--- /dev/null
+++ b/tests/PlatformCompatGating/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/compat/OWNERS
diff --git a/tests/RollbackTest/OWNERS b/tests/RollbackTest/OWNERS
new file mode 100644
index 0000000..d04a706
--- /dev/null
+++ b/tests/RollbackTest/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/rollback/OWNERS
diff --git a/tests/RollbackTest/TEST_MAPPING b/tests/RollbackTest/TEST_MAPPING
index 0f4c460..7f9f2dc 100644
--- a/tests/RollbackTest/TEST_MAPPING
+++ b/tests/RollbackTest/TEST_MAPPING
@@ -1,5 +1,5 @@
 {
-  "presubmit": [
+  "presubmit-large": [
     {
       "name": "RollbackTest"
     },
diff --git a/tests/SoundTriggerTestApp/OWNERS b/tests/SoundTriggerTestApp/OWNERS
new file mode 100644
index 0000000..816bc6b
--- /dev/null
+++ b/tests/SoundTriggerTestApp/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/media/soundtrigger/OWNERS
diff --git a/tests/SoundTriggerTests/OWNERS b/tests/SoundTriggerTests/OWNERS
new file mode 100644
index 0000000..816bc6b
--- /dev/null
+++ b/tests/SoundTriggerTests/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/media/soundtrigger/OWNERS
diff --git a/tests/StagedInstallTest/OWNERS b/tests/StagedInstallTest/OWNERS
new file mode 100644
index 0000000..d825dfd
--- /dev/null
+++ b/tests/StagedInstallTest/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/pm/OWNERS
diff --git a/tests/StatusBar/OWNERS b/tests/StatusBar/OWNERS
new file mode 100644
index 0000000..2e96c97
--- /dev/null
+++ b/tests/StatusBar/OWNERS
@@ -0,0 +1 @@
+include /packages/SystemUI/OWNERS
diff --git a/tests/TaskOrganizerTest/OWNERS b/tests/TaskOrganizerTest/OWNERS
new file mode 100644
index 0000000..0862c05
--- /dev/null
+++ b/tests/TaskOrganizerTest/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/wm/OWNERS
diff --git a/tests/TelephonyCommonTests/OWNERS b/tests/TelephonyCommonTests/OWNERS
new file mode 100644
index 0000000..640baf2
--- /dev/null
+++ b/tests/TelephonyCommonTests/OWNERS
@@ -0,0 +1 @@
+include /telephony/OWNERS
diff --git a/tests/UsageReportingTest/OWNERS b/tests/UsageReportingTest/OWNERS
new file mode 100644
index 0000000..d3227de
--- /dev/null
+++ b/tests/UsageReportingTest/OWNERS
@@ -0,0 +1 @@
+include /services/usage/OWNERS
diff --git a/tests/UsageStatsPerfTests/OWNERS b/tests/UsageStatsPerfTests/OWNERS
new file mode 100644
index 0000000..d3227de
--- /dev/null
+++ b/tests/UsageStatsPerfTests/OWNERS
@@ -0,0 +1 @@
+include /services/usage/OWNERS
diff --git a/tests/UsageStatsTest/OWNERS b/tests/UsageStatsTest/OWNERS
new file mode 100644
index 0000000..d3227de
--- /dev/null
+++ b/tests/UsageStatsTest/OWNERS
@@ -0,0 +1 @@
+include /services/usage/OWNERS
diff --git a/tests/UsbHostExternalManagmentTest/OWNERS b/tests/UsbHostExternalManagmentTest/OWNERS
new file mode 100644
index 0000000..f7b2a37
--- /dev/null
+++ b/tests/UsbHostExternalManagmentTest/OWNERS
@@ -0,0 +1 @@
+include /services/usb/OWNERS
diff --git a/tests/UsbManagerTests/OWNERS b/tests/UsbManagerTests/OWNERS
new file mode 100644
index 0000000..f7b2a37
--- /dev/null
+++ b/tests/UsbManagerTests/OWNERS
@@ -0,0 +1 @@
+include /services/usb/OWNERS
diff --git a/tests/UsbTests/OWNERS b/tests/UsbTests/OWNERS
new file mode 100644
index 0000000..f7b2a37
--- /dev/null
+++ b/tests/UsbTests/OWNERS
@@ -0,0 +1 @@
+include /services/usb/OWNERS
diff --git a/tests/VoiceInteraction/OWNERS b/tests/VoiceInteraction/OWNERS
new file mode 100644
index 0000000..ef1061b
--- /dev/null
+++ b/tests/VoiceInteraction/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/service/voice/OWNERS
diff --git a/tests/WindowAnimationJank/OWNERS b/tests/WindowAnimationJank/OWNERS
new file mode 100644
index 0000000..0862c05
--- /dev/null
+++ b/tests/WindowAnimationJank/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/wm/OWNERS
diff --git a/tests/WindowInsetsTests/OWNERS b/tests/WindowInsetsTests/OWNERS
new file mode 100644
index 0000000..0862c05
--- /dev/null
+++ b/tests/WindowInsetsTests/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/wm/OWNERS
diff --git a/tests/backup/OWNERS b/tests/backup/OWNERS
new file mode 100644
index 0000000..d99779e
--- /dev/null
+++ b/tests/backup/OWNERS
@@ -0,0 +1 @@
+include /services/backup/OWNERS
diff --git a/tests/benchmarks/src/com/android/server/net/OWNERS b/tests/benchmarks/src/com/android/server/net/OWNERS
new file mode 100644
index 0000000..aa87958
--- /dev/null
+++ b/tests/benchmarks/src/com/android/server/net/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/net/OWNERS
diff --git a/tests/net/common/java/android/net/LinkAddressTest.java b/tests/net/common/java/android/net/LinkAddressTest.java
index 60308e3..1eaf30c 100644
--- a/tests/net/common/java/android/net/LinkAddressTest.java
+++ b/tests/net/common/java/android/net/LinkAddressTest.java
@@ -68,8 +68,8 @@
 
     private static final String V4 = "192.0.2.1";
     private static final String V6 = "2001:db8::1";
-    private static final InetAddress V4_ADDRESS = NetworkUtils.numericToInetAddress(V4);
-    private static final InetAddress V6_ADDRESS = NetworkUtils.numericToInetAddress(V6);
+    private static final InetAddress V4_ADDRESS = InetAddresses.parseNumericAddress(V4);
+    private static final InetAddress V6_ADDRESS = InetAddresses.parseNumericAddress(V6);
 
     @Test
     public void testConstants() {
@@ -131,10 +131,10 @@
             ipv6Loopback = new LinkAddress(addrs.get(0));
         }
 
-        assertEquals(NetworkUtils.numericToInetAddress("127.0.0.1"), ipv4Loopback.getAddress());
+        assertEquals(InetAddresses.parseNumericAddress("127.0.0.1"), ipv4Loopback.getAddress());
         assertEquals(8, ipv4Loopback.getPrefixLength());
 
-        assertEquals(NetworkUtils.numericToInetAddress("::1"), ipv6Loopback.getAddress());
+        assertEquals(InetAddresses.parseNumericAddress("::1"), ipv6Loopback.getAddress());
         assertEquals(128, ipv6Loopback.getPrefixLength());
 
         // Null addresses are rejected.
diff --git a/tests/net/java/android/net/TcpKeepalivePacketDataTest.java b/tests/net/java/android/net/TcpKeepalivePacketDataTest.java
index 835a83e..c5b25bd 100644
--- a/tests/net/java/android/net/TcpKeepalivePacketDataTest.java
+++ b/tests/net/java/android/net/TcpKeepalivePacketDataTest.java
@@ -147,5 +147,11 @@
         assertEquals(resultData.rcvWndScale, wndScale);
         assertEquals(resultData.tos, tos);
         assertEquals(resultData.ttl, ttl);
+
+        final String expected = ""
+                + "android.net.TcpKeepalivePacketDataParcelable{srcAddress: [10, 0, 0, 1],"
+                + " srcPort: 1234, dstAddress: [10, 0, 0, 5], dstPort: 4321, seq: 286331153,"
+                + " ack: 572662306, rcvWnd: 48000, rcvWndScale: 2, tos: 4, ttl: 64}";
+        assertEquals(expected, resultData.toString());
     }
 }
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index 5d45737..b6f91c4 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -181,7 +181,6 @@
 import android.net.NetworkStackClient;
 import android.net.NetworkState;
 import android.net.NetworkTestResultParcelable;
-import android.net.NetworkUtils;
 import android.net.ProxyInfo;
 import android.net.ResolverParamsParcel;
 import android.net.RouteInfo;
@@ -1958,6 +1957,57 @@
     }
 
     @Test
+    public void testOwnerUidChangeBug() throws Exception {
+        // Owner UIDs are not visible without location permission.
+        setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
+                Manifest.permission.ACCESS_FINE_LOCATION);
+
+        final NetworkCapabilities ncTemplate = new NetworkCapabilities();
+        final int originalOwnerUid = Process.myUid();
+        ncTemplate.setOwnerUid(originalOwnerUid);
+
+        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, new LinkProperties(),
+                ncTemplate);
+        mWiFiNetworkAgent.connect(false);
+        waitForIdle();
+
+        // Send ConnectivityService an update to the mWiFiNetworkAgent's capabilities that changes
+        // its owner UID.
+        NetworkCapabilities agentCapabilities = mWiFiNetworkAgent.getNetworkCapabilities();
+        assertEquals(originalOwnerUid, agentCapabilities.getOwnerUid());
+        agentCapabilities.setOwnerUid(42);
+        mWiFiNetworkAgent.setNetworkCapabilities(agentCapabilities, true);
+        waitForIdle();
+
+        // Check that the owner UID is not updated.
+        NetworkCapabilities nc = mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork());
+        assertEquals(originalOwnerUid, nc.getOwnerUid());
+
+        // Make an unrelated change to the capabilities.
+        assertFalse(agentCapabilities.hasCapability(NET_CAPABILITY_NOT_CONGESTED));
+        agentCapabilities.addCapability(NET_CAPABILITY_NOT_CONGESTED);
+        mWiFiNetworkAgent.setNetworkCapabilities(agentCapabilities, true);
+        waitForIdle();
+
+        // Check that both the capability change and the owner UID have been modified.
+        // The owner UID is -1 because it is visible only to the UID that owns the network.
+        nc = mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork());
+        assertEquals(-1, nc.getOwnerUid());
+        assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_CONGESTED));
+
+        // Set the owner back to originalOwnerUid, update the capabilities, and check that it is
+        // visible again.
+        // TODO: should this even be possible?
+        agentCapabilities.setOwnerUid(originalOwnerUid);
+        agentCapabilities.removeCapability(NET_CAPABILITY_NOT_CONGESTED);
+        mWiFiNetworkAgent.setNetworkCapabilities(agentCapabilities, true);
+        waitForIdle();
+
+        nc = mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork());
+        assertEquals(originalOwnerUid, nc.getOwnerUid());
+    }
+
+    @Test
     public void testMultipleLingering() throws Exception {
         // This test would be flaky with the default 120ms timer: that is short enough that
         // lingered networks are torn down before assertions can be run. We don't want to mock the
@@ -2517,7 +2567,10 @@
 
     @Test
     public void testNoMutableNetworkRequests() throws Exception {
-        PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, new Intent("a"), 0);
+        // TODO(b/173157160) Please replace FLAG_MUTABLE_UNAUDITED below
+        // with either FLAG_IMMUTABLE (recommended) or FLAG_MUTABLE.
+        PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, new Intent("a"),
+                PendingIntent.FLAG_MUTABLE_UNAUDITED);
         NetworkRequest request1 = new NetworkRequest.Builder()
                 .addCapability(NET_CAPABILITY_VALIDATED)
                 .build();
@@ -3177,17 +3230,21 @@
         assertThrows(SecurityException.class, () ->
                 mCm.registerNetworkCallback(r, new NetworkCallback()));
 
+        // TODO(b/173157160) Please replace FLAG_MUTABLE_UNAUDITED below
+        // with either FLAG_IMMUTABLE (recommended) or FLAG_MUTABLE.
         assertThrows(SecurityException.class, () ->
                 mCm.registerNetworkCallback(r, PendingIntent.getService(
-                        mServiceContext, 0, new Intent(), 0)));
+                        mServiceContext, 0, new Intent(), PendingIntent.FLAG_MUTABLE_UNAUDITED)));
 
         // Requesting a Network with signal strength should get IllegalArgumentException.
         assertThrows(IllegalArgumentException.class, () ->
                 mCm.requestNetwork(r, new NetworkCallback()));
 
+        // TODO(b/173157160) Please replace FLAG_MUTABLE_UNAUDITED below
+        // with either FLAG_IMMUTABLE (recommended) or FLAG_MUTABLE.
         assertThrows(IllegalArgumentException.class, () ->
                 mCm.requestNetwork(r, PendingIntent.getService(
-                        mServiceContext, 0, new Intent(), 0)));
+                        mServiceContext, 0, new Intent(), PendingIntent.FLAG_MUTABLE_UNAUDITED)));
     }
 
     @Test
@@ -4651,12 +4708,16 @@
         }
         j = 0;
         while (j++ < INTENTS / 2) {
-            PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, new Intent("a" + j), 0);
+            // TODO(b/173157160) Please replace FLAG_MUTABLE_UNAUDITED below
+            // with either FLAG_IMMUTABLE (recommended) or FLAG_MUTABLE.
+            PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, new Intent("a" + j), PendingIntent.FLAG_MUTABLE_UNAUDITED);
             mCm.requestNetwork(networkRequest, pi);
             registered.add(pi);
         }
         while (j++ < INTENTS) {
-            PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, new Intent("b" + j), 0);
+            // TODO(b/173157160) Please replace FLAG_MUTABLE_UNAUDITED below
+            // with either FLAG_IMMUTABLE (recommended) or FLAG_MUTABLE.
+            PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, new Intent("b" + j), PendingIntent.FLAG_MUTABLE_UNAUDITED);
             mCm.registerNetworkCallback(networkRequest, pi);
             registered.add(pi);
         }
@@ -4670,11 +4731,15 @@
         );
         assertThrows(TooManyRequestsException.class, () ->
                 mCm.requestNetwork(networkRequest,
-                        PendingIntent.getBroadcast(mContext, 0, new Intent("c"), 0))
+                        // TODO(b/173157160) Please replace FLAG_MUTABLE_UNAUDITED below
+                        // with either FLAG_IMMUTABLE (recommended) or FLAG_MUTABLE.
+                        PendingIntent.getBroadcast(mContext, 0, new Intent("c"), PendingIntent.FLAG_MUTABLE_UNAUDITED))
         );
         assertThrows(TooManyRequestsException.class, () ->
                 mCm.registerNetworkCallback(networkRequest,
-                        PendingIntent.getBroadcast(mContext, 0, new Intent("d"), 0))
+                        // TODO(b/173157160) Please replace FLAG_MUTABLE_UNAUDITED below
+                        // with either FLAG_IMMUTABLE (recommended) or FLAG_MUTABLE.
+                        PendingIntent.getBroadcast(mContext, 0, new Intent("d"), PendingIntent.FLAG_MUTABLE_UNAUDITED))
         );
 
         for (Object o : registered) {
@@ -4703,16 +4768,20 @@
         waitForIdle();
 
         for (int i = 0; i < MAX_REQUESTS; i++) {
+            // TODO(b/173157160) Please replace FLAG_MUTABLE_UNAUDITED below
+            // with either FLAG_IMMUTABLE (recommended) or FLAG_MUTABLE.
             PendingIntent pendingIntent =
-                    PendingIntent.getBroadcast(mContext, 0, new Intent("e" + i), 0);
+                    PendingIntent.getBroadcast(mContext, 0, new Intent("e" + i), PendingIntent.FLAG_MUTABLE_UNAUDITED);
             mCm.requestNetwork(networkRequest, pendingIntent);
             mCm.unregisterNetworkCallback(pendingIntent);
         }
         waitForIdle();
 
         for (int i = 0; i < MAX_REQUESTS; i++) {
+            // TODO(b/173157160) Please replace FLAG_MUTABLE_UNAUDITED below
+            // with either FLAG_IMMUTABLE (recommended) or FLAG_MUTABLE.
             PendingIntent pendingIntent =
-                    PendingIntent.getBroadcast(mContext, 0, new Intent("f" + i), 0);
+                    PendingIntent.getBroadcast(mContext, 0, new Intent("f" + i), PendingIntent.FLAG_MUTABLE_UNAUDITED);
             mCm.registerNetworkCallback(networkRequest, pendingIntent);
             mCm.unregisterNetworkCallback(pendingIntent);
         }
@@ -4790,7 +4859,7 @@
         lp.setInterfaceName(WIFI_IFNAME);
         LinkAddress myIpv4Address = new LinkAddress("192.168.12.3/24");
         RouteInfo myIpv4DefaultRoute = new RouteInfo((IpPrefix) null,
-                NetworkUtils.numericToInetAddress("192.168.12.1"), lp.getInterfaceName());
+                InetAddresses.parseNumericAddress("192.168.12.1"), lp.getInterfaceName());
         lp.addLinkAddress(myIpv4Address);
         lp.addRoute(myIpv4DefaultRoute);
 
diff --git a/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java b/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java
index 529d03c..799bcc8 100644
--- a/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java
+++ b/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java
@@ -34,6 +34,7 @@
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.net.INetd;
+import android.net.InetAddresses;
 import android.net.IpSecAlgorithm;
 import android.net.IpSecConfig;
 import android.net.IpSecManager;
@@ -44,7 +45,6 @@
 import android.net.IpSecUdpEncapResponse;
 import android.net.LinkAddress;
 import android.net.Network;
-import android.net.NetworkUtils;
 import android.os.Binder;
 import android.os.INetworkManagementService;
 import android.os.ParcelFileDescriptor;
@@ -272,7 +272,7 @@
 
         IpSecSpiResponse spi =
                 mIpSecService.allocateSecurityParameterIndex(
-                        NetworkUtils.numericToInetAddress(remoteAddress).getHostAddress(),
+                        InetAddresses.parseNumericAddress(remoteAddress).getHostAddress(),
                         IpSecManager.INVALID_SECURITY_PARAMETER_INDEX,
                         new Binder());
         return spi.resourceId;
diff --git a/tests/notification/OWNERS b/tests/notification/OWNERS
new file mode 100644
index 0000000..396fd12
--- /dev/null
+++ b/tests/notification/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/notification/OWNERS
diff --git a/tests/permission/OWNERS b/tests/permission/OWNERS
new file mode 100644
index 0000000..999ea0e
--- /dev/null
+++ b/tests/permission/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/permission/OWNERS
diff --git a/tests/utils/DummyIME/OWNERS b/tests/utils/DummyIME/OWNERS
new file mode 100644
index 0000000..5deb2ce
--- /dev/null
+++ b/tests/utils/DummyIME/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/view/inputmethod/OWNERS
diff --git a/tests/utils/StubIME/OWNERS b/tests/utils/StubIME/OWNERS
new file mode 100644
index 0000000..5deb2ce
--- /dev/null
+++ b/tests/utils/StubIME/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/view/inputmethod/OWNERS
diff --git a/tests/utils/hostutils/src/com/android/tests/rollback/OWNERS b/tests/utils/hostutils/src/com/android/tests/rollback/OWNERS
new file mode 100644
index 0000000..d04a706
--- /dev/null
+++ b/tests/utils/hostutils/src/com/android/tests/rollback/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/rollback/OWNERS
diff --git a/tests/utils/testutils/java/com/android/server/accessibility/OWNERS b/tests/utils/testutils/java/com/android/server/accessibility/OWNERS
new file mode 100644
index 0000000..b74281e
--- /dev/null
+++ b/tests/utils/testutils/java/com/android/server/accessibility/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/view/accessibility/OWNERS
diff --git a/tests/utils/testutils/java/com/android/server/wm/OWNERS b/tests/utils/testutils/java/com/android/server/wm/OWNERS
new file mode 100644
index 0000000..0862c05
--- /dev/null
+++ b/tests/utils/testutils/java/com/android/server/wm/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/wm/OWNERS
diff --git a/tools/aapt/OWNERS b/tools/aapt/OWNERS
new file mode 100644
index 0000000..c232ccd
--- /dev/null
+++ b/tools/aapt/OWNERS
@@ -0,0 +1 @@
+include /tools/aapt2/OWNERS
diff --git a/tools/fonts/OWNERS b/tools/fonts/OWNERS
new file mode 100644
index 0000000..a538331
--- /dev/null
+++ b/tools/fonts/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/graphics/fonts/OWNERS
diff --git a/tools/incident_report/OWNERS b/tools/incident_report/OWNERS
new file mode 100644
index 0000000..f766115
--- /dev/null
+++ b/tools/incident_report/OWNERS
@@ -0,0 +1 @@
+include /cmds/incidentd/OWNERS
diff --git a/tools/incident_section_gen/OWNERS b/tools/incident_section_gen/OWNERS
new file mode 100644
index 0000000..f766115
--- /dev/null
+++ b/tools/incident_section_gen/OWNERS
@@ -0,0 +1 @@
+include /cmds/incidentd/OWNERS
diff --git a/tools/powerstats/OWNERS b/tools/powerstats/OWNERS
new file mode 100644
index 0000000..d68066b
--- /dev/null
+++ b/tools/powerstats/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/power/OWNERS
diff --git a/tools/stats_log_api_gen/OWNERS b/tools/stats_log_api_gen/OWNERS
new file mode 100644
index 0000000..41a0c95
--- /dev/null
+++ b/tools/stats_log_api_gen/OWNERS
@@ -0,0 +1 @@
[email protected]
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index 85b3170..271a739 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -1638,6 +1638,11 @@
         private String mConnectChoice;
 
         /**
+         * The RSSI when the user made the connectChoice.
+         */
+        private int mConnectChoiceRssi;
+
+        /**
          * Used to cache the temporary candidate during the network selection procedure. It will be
          * kept updating once a new scan result has a higher score than current one
          */
@@ -1748,6 +1753,23 @@
             mConnectChoice = newConnectChoice;
         }
 
+        /**
+         * Associate a RSSI with the user connect choice network.
+         * @param rssi signal strength
+         * @hide
+         */
+        public void setConnectChoiceRssi(int rssi) {
+            mConnectChoiceRssi = rssi;
+        }
+
+        /**
+         * @return returns the RSSI of the last time the user made the connect choice.
+         * @hide
+         */
+        public int getConnectChoiceRssi() {
+            return mConnectChoiceRssi;
+        }
+
         /** Get the current Quality network selection status as a String (for debugging). */
         @NonNull
         public String getNetworkStatusString() {
@@ -2051,6 +2073,7 @@
             setCandidate(source.getCandidate());
             setCandidateScore(source.getCandidateScore());
             setConnectChoice(source.getConnectChoice());
+            setConnectChoiceRssi(source.getConnectChoiceRssi());
             setHasEverConnected(source.hasEverConnected());
             setHasNeverDetectedCaptivePortal(source.hasNeverDetectedCaptivePortal());
         }
@@ -2068,6 +2091,7 @@
             if (getConnectChoice() != null) {
                 dest.writeInt(CONNECT_CHOICE_EXISTS);
                 dest.writeString(getConnectChoice());
+                dest.writeInt(getConnectChoiceRssi());
             } else {
                 dest.writeInt(CONNECT_CHOICE_NOT_EXISTS);
             }
@@ -2087,6 +2111,7 @@
             setNetworkSelectionBSSID(in.readString());
             if (in.readInt() == CONNECT_CHOICE_EXISTS) {
                 setConnectChoice(in.readString());
+                setConnectChoiceRssi(in.readInt());
             } else {
                 setConnectChoice(null);
             }
@@ -2398,6 +2423,8 @@
         }
         if (mNetworkSelectionStatus.getConnectChoice() != null) {
             sbuf.append(" connect choice: ").append(mNetworkSelectionStatus.getConnectChoice());
+            sbuf.append(" connect choice rssi: ")
+                    .append(mNetworkSelectionStatus.getConnectChoiceRssi());
         }
         sbuf.append(" hasEverConnected: ")
                 .append(mNetworkSelectionStatus.hasEverConnected()).append("\n");