Merge "[Bugfix][RemoteAnimation] Fix IndexOutOfBoundsException in onAnimationFinished of  RemoteAnimationController"
diff --git a/Android.bp b/Android.bp
index b0a1f93..287f271 100644
--- a/Android.bp
+++ b/Android.bp
@@ -298,6 +298,7 @@
         "contacts-provider-platform-compat-config",
     ],
     libs: [
+        "androidx.annotation_annotation",
         "app-compat-annotations",
         "ext",
         "framework-updatable-stubs-module_libs_api",
diff --git a/apct-tests/perftests/core/src/android/libcore/regression/ByteBufferBulkPerfTest.java b/apct-tests/perftests/core/src/android/libcore/regression/BulkPerfTest.java
similarity index 89%
rename from apct-tests/perftests/core/src/android/libcore/regression/ByteBufferBulkPerfTest.java
rename to apct-tests/perftests/core/src/android/libcore/regression/BulkPerfTest.java
index 8e57b28..855bb9a 100644
--- a/apct-tests/perftests/core/src/android/libcore/regression/ByteBufferBulkPerfTest.java
+++ b/apct-tests/perftests/core/src/android/libcore/regression/BulkPerfTest.java
@@ -36,10 +36,10 @@
 
 @RunWith(Parameterized.class)
 @LargeTest
-public class ByteBufferBulkPerfTest {
+public class BulkPerfTest {
     @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
 
-    @Parameters(name = "mAligned({0}), mSrcBufferType({1}), mDataBufferType({2}), mBufferSize({3})")
+    @Parameters(name = "mAlign({0}), mSBuf({1}), mDBuf({2}), mSize({3})")
     public static Collection<Object[]> data() {
         return Arrays.asList(
                 new Object[][] {
@@ -83,7 +83,7 @@
     }
 
     @Parameterized.Parameter(0)
-    public boolean mAligned;
+    public boolean mAlign;
 
     enum MyBufferType {
         DIRECT,
@@ -92,13 +92,13 @@
     }
 
     @Parameterized.Parameter(1)
-    public MyBufferType mSrcBufferType;
+    public MyBufferType mSBuf;
 
     @Parameterized.Parameter(2)
-    public MyBufferType mDataBufferType;
+    public MyBufferType mDBuf;
 
     @Parameterized.Parameter(3)
-    public int mBufferSize;
+    public int mSize;
 
     public static ByteBuffer newBuffer(boolean aligned, MyBufferType bufferType, int bsize)
             throws IOException {
@@ -126,13 +126,13 @@
     }
 
     @Test
-    public void timeByteBuffer_putByteBuffer() throws Exception {
-        ByteBuffer src = ByteBufferBulkPerfTest.newBuffer(mAligned, mSrcBufferType, mBufferSize);
-        ByteBuffer data = ByteBufferBulkPerfTest.newBuffer(mAligned, mDataBufferType, mBufferSize);
+    public void timePut() throws Exception {
+        ByteBuffer src = BulkPerfTest.newBuffer(mAlign, mSBuf, mSize);
+        ByteBuffer data = BulkPerfTest.newBuffer(mAlign, mDBuf, mSize);
         BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
         while (state.keepRunning()) {
-            src.position(mAligned ? 0 : 1);
-            data.position(mAligned ? 0 : 1);
+            src.position(mAlign ? 0 : 1);
+            data.position(mAlign ? 0 : 1);
             src.put(data);
         }
     }
diff --git a/apct-tests/perftests/core/src/android/libcore/regression/ExpensiveObjectsPerfTest.java b/apct-tests/perftests/core/src/android/libcore/regression/ExpensiveObjectsPerfTest.java
index 03c9d43..adcd571 100644
--- a/apct-tests/perftests/core/src/android/libcore/regression/ExpensiveObjectsPerfTest.java
+++ b/apct-tests/perftests/core/src/android/libcore/regression/ExpensiveObjectsPerfTest.java
@@ -158,14 +158,6 @@
     }
 
     @Test
-    public void timeNewSimpleDateFormat() {
-        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
-        while (state.keepRunning()) {
-            new SimpleDateFormat();
-        }
-    }
-
-    @Test
     public void timeClonedSimpleDateFormat() {
         SimpleDateFormat sdf = new SimpleDateFormat();
         BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
diff --git a/apct-tests/perftests/core/src/android/libcore/regression/IdnPerfTest.java b/apct-tests/perftests/core/src/android/libcore/regression/IdnPerfTest.java
new file mode 100644
index 0000000..c60930f
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/libcore/regression/IdnPerfTest.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.libcore.regression;
+
+import android.perftests.utils.BenchmarkState;
+import android.perftests.utils.PerfStatusReporter;
+import android.test.suitebuilder.annotation.LargeTest;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.net.IDN;
+
+@RunWith(AndroidJUnit4.class)
+@LargeTest
+public class IdnPerfTest {
+    @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
+
+    @Test
+    public void timeToUnicode() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            IDN.toASCII("fass.de");
+            IDN.toASCII("faß.de");
+            IDN.toASCII("fäß.de");
+            IDN.toASCII("a\u200Cb");
+            IDN.toASCII("öbb.at");
+            IDN.toASCII("abc・日本.co.jp");
+            IDN.toASCII("日本.co.jp");
+            IDN.toASCII("x\u0327\u0301.de");
+            IDN.toASCII("σόλοσ.gr");
+        }
+    }
+
+    @Test
+    public void timeToAscii() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            IDN.toUnicode("xn--fss-qla.de");
+            IDN.toUnicode("xn--n00d.com");
+            IDN.toUnicode("xn--bb-eka.at");
+            IDN.toUnicode("xn--og-09a.de");
+            IDN.toUnicode("xn--53h.de");
+            IDN.toUnicode("xn--iny-zx5a.de");
+            IDN.toUnicode("xn--abc-rs4b422ycvb.co.jp");
+            IDN.toUnicode("xn--wgv71a.co.jp");
+            IDN.toUnicode("xn--x-xbb7i.de");
+            IDN.toUnicode("xn--wxaikc6b.gr");
+            IDN.toUnicode("xn--wxaikc6b.xn--gr-gtd9a1b0g.de");
+        }
+    }
+}
diff --git a/apct-tests/perftests/core/src/android/libcore/regression/IntConstantDivisionPerfTest.java b/apct-tests/perftests/core/src/android/libcore/regression/IntConstantDivisionPerfTest.java
new file mode 100644
index 0000000..abcc972
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/libcore/regression/IntConstantDivisionPerfTest.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.libcore.regression;
+
+import android.perftests.utils.BenchmarkState;
+import android.perftests.utils.PerfStatusReporter;
+import android.test.suitebuilder.annotation.LargeTest;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@LargeTest
+public class IntConstantDivisionPerfTest {
+    @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
+
+    @Test
+    public void timeDivideIntByConstant2() {
+        int result = 1;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            result /= 2;
+        }
+    }
+
+    @Test
+    public void timeDivideIntByConstant8() {
+        int result = 1;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            result /= 8;
+        }
+    }
+
+    @Test
+    public void timeDivideIntByConstant10() {
+        int result = 1;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            result /= 10;
+        }
+    }
+
+    @Test
+    public void timeDivideIntByConstant100() {
+        int result = 1;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            result /= 100;
+        }
+    }
+
+    @Test
+    public void timeDivideIntByConstant100_HandOptimized() {
+        int result = 1;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            result = (int) ((0x51eb851fL * result) >>> 37);
+        }
+    }
+
+    @Test
+    public void timeDivideIntByConstant2048() {
+        int result = 1;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            result /= 2048;
+        }
+    }
+
+    @Test
+    public void timeDivideIntByVariable2() {
+        int result = 1;
+        int factor = 2;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            result /= factor;
+        }
+    }
+
+    @Test
+    public void timeDivideIntByVariable10() {
+        int result = 1;
+        int factor = 10;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            result /= factor;
+        }
+    }
+}
diff --git a/apct-tests/perftests/core/src/android/libcore/regression/IntConstantMultiplicationPerfTest.java b/apct-tests/perftests/core/src/android/libcore/regression/IntConstantMultiplicationPerfTest.java
new file mode 100644
index 0000000..c9f0616
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/libcore/regression/IntConstantMultiplicationPerfTest.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.libcore.regression;
+
+import android.perftests.utils.BenchmarkState;
+import android.perftests.utils.PerfStatusReporter;
+import android.test.suitebuilder.annotation.LargeTest;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@LargeTest
+public class IntConstantMultiplicationPerfTest {
+    @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
+
+    @Test
+    public void timeMultiplyIntByConstant6() {
+        int result = 1;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            result *= 6;
+        }
+    }
+
+    @Test
+    public void timeMultiplyIntByConstant7() {
+        int result = 1;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            result *= 7;
+        }
+    }
+
+    @Test
+    public void timeMultiplyIntByConstant8() {
+        int result = 1;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            result *= 8;
+        }
+    }
+
+    @Test
+    public void timeMultiplyIntByConstant8_Shift() {
+        int result = 1;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            result <<= 3;
+        }
+    }
+
+    @Test
+    public void timeMultiplyIntByConstant10() {
+        int result = 1;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            result *= 10;
+        }
+    }
+
+    @Test
+    public void timeMultiplyIntByConstant10_Shift() {
+        int result = 1;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            result = (result + (result << 2)) << 1;
+        }
+    }
+
+    @Test
+    public void timeMultiplyIntByConstant2047() {
+        int result = 1;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            result *= 2047;
+        }
+    }
+
+    @Test
+    public void timeMultiplyIntByConstant2048() {
+        int result = 1;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            result *= 2048;
+        }
+    }
+
+    @Test
+    public void timeMultiplyIntByConstant2049() {
+        int result = 1;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            result *= 2049;
+        }
+    }
+
+    @Test
+    public void timeMultiplyIntByVariable10() {
+        int result = 1;
+        int factor = 10;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            result *= factor;
+        }
+    }
+
+    @Test
+    public void timeMultiplyIntByVariable8() {
+        int result = 1;
+        int factor = 8;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            result *= factor;
+        }
+    }
+}
diff --git a/apct-tests/perftests/core/src/android/libcore/regression/IntConstantRemainderPerfTest.java b/apct-tests/perftests/core/src/android/libcore/regression/IntConstantRemainderPerfTest.java
new file mode 100644
index 0000000..78f744c
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/libcore/regression/IntConstantRemainderPerfTest.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.libcore.regression;
+
+import android.perftests.utils.BenchmarkState;
+import android.perftests.utils.PerfStatusReporter;
+import android.test.suitebuilder.annotation.LargeTest;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@LargeTest
+public class IntConstantRemainderPerfTest {
+    @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
+
+    @Test
+    public void timeRemainderIntByConstant2() {
+        int result = 1;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            result %= 2;
+        }
+    }
+
+    @Test
+    public void timeRemainderIntByConstant8() {
+        int result = 1;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            result %= 8;
+        }
+    }
+
+    @Test
+    public void timeRemainderIntByConstant10() {
+        int result = 1;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            result %= 10;
+        }
+    }
+
+    @Test
+    public void timeRemainderIntByConstant100() {
+        int result = 1;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            result %= 100;
+        }
+    }
+
+    @Test
+    public void timeRemainderIntByConstant2048() {
+        int result = 1;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            result %= 2048;
+        }
+    }
+
+    @Test
+    public void timeRemainderIntByVariable2() {
+        int result = 1;
+        int factor = 2;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            result %= factor;
+        }
+    }
+
+    @Test
+    public void timeRemainderIntByVariable10() {
+        int result = 1;
+        int factor = 10;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            result %= factor;
+        }
+    }
+}
diff --git a/apct-tests/perftests/core/src/android/libcore/regression/IntegerPerfTest.java b/apct-tests/perftests/core/src/android/libcore/regression/IntegerPerfTest.java
new file mode 100644
index 0000000..170bb58
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/libcore/regression/IntegerPerfTest.java
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.libcore.regression;
+
+import android.perftests.utils.BenchmarkState;
+import android.perftests.utils.PerfStatusReporter;
+
+import org.junit.Rule;
+import org.junit.Test;
+
+public class IntegerPerfTest {
+    @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
+
+    @Test
+    public void timeLongSignumBranch() {
+        int t = 0;
+        int i = 0;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            t += signum1(-(++i));
+            t += signum1(0);
+            t += signum1(i);
+        }
+    }
+
+    @Test
+    public void timeLongSignumBranchFree() {
+        int t = 0;
+        int i = 0;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            t += signum2(-(++i));
+            t += signum2(0);
+            t += signum2(i);
+        }
+    }
+
+    private static int signum1(long v) {
+        return v < 0 ? -1 : (v == 0 ? 0 : 1);
+    }
+
+    private static int signum2(long v) {
+        return ((int) (v >> 63)) | (int) (-v >>> 63); // Hacker's delight 2-7
+    }
+
+    @Test
+    public void timeLongBitCount_BitSet() {
+        int t = 0;
+        int i = 0;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            t += pop((long) ++i);
+        }
+    }
+
+    private static int pop(long l) {
+        int count = popX(l & 0xffffffffL);
+        count += popX(l >>> 32);
+        return count;
+    }
+
+    private static int popX(long x) {
+        // BEGIN android-note
+        // delegate to Integer.bitCount(i); consider using native code
+        // END android-note
+        x = x - ((x >>> 1) & 0x55555555);
+        x = (x & 0x33333333) + ((x >>> 2) & 0x33333333);
+        x = (x + (x >>> 4)) & 0x0f0f0f0f;
+        x = x + (x >>> 8);
+        x = x + (x >>> 16);
+        return (int) x & 0x0000003f;
+    }
+
+    @Test
+    public void timeLongBitCount_2Int() {
+        int t = 0;
+        int i = 0;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            t += pop2((long) ++i);
+        }
+    }
+
+    private static int pop2(long l) {
+        int count = Integer.bitCount((int) (l & 0xffffffffL));
+        count += Integer.bitCount((int) (l >>> 32));
+        return count;
+    }
+
+    @Test
+    public void timeLongBitCount_Long() {
+        int t = 0;
+        int i = 0;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            t += Long.bitCount((long) ++i);
+        }
+    }
+
+    /**
+     * Table for Seal's algorithm for Number of Trailing Zeros. Hacker's Delight online, Figure 5-18
+     * (http://www.hackersdelight.org/revisions.pdf) The entries whose value is -1 are never
+     * referenced.
+     */
+    private static final byte[] NTZ_TABLE = {
+        32, 0, 1, 12, 2, 6, -1, 13, 3, -1, 7, -1, -1, -1, -1, 14,
+        10, 4, -1, -1, 8, -1, -1, 25, -1, -1, -1, -1, -1, 21, 27, 15,
+        31, 11, 5, -1, -1, -1, -1, -1, 9, -1, -1, 24, -1, -1, 20, 26,
+        30, -1, -1, -1, -1, 23, -1, 19, 29, -1, 22, 18, 28, 17, 16, -1
+    };
+
+    private static int numberOfTrailingZerosHD(int i) {
+        // Seal's algorithm - Hacker's Delight 5-18
+        i &= -i;
+        i = (i << 4) + i; // x *= 17
+        i = (i << 6) + i; // x *= 65
+        i = (i << 16) - i; // x *= 65535
+        return NTZ_TABLE[i >>> 26];
+    }
+
+    private static int numberOfTrailingZerosOL(int i) {
+        return NTZ_TABLE[((i & -i) * 0x0450FBAF) >>> 26];
+    }
+
+    @Test
+    public void timeNumberOfTrailingZerosHD() {
+        int t = 0;
+        int i = 0;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            t += numberOfTrailingZerosHD(++i);
+        }
+    }
+
+    @Test
+    public void timeNumberOfTrailingZerosOL() {
+        int t = 0;
+        int i = 0;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            t += numberOfTrailingZerosOL(++i);
+        }
+    }
+
+    @Test
+    public void timeIntegerValueOf() throws Exception {
+        String[] intStrings =
+                new String[] {
+                    "0", "1", "12", "123", "1234", "12345", "123456", "1234567", "12345678"
+                };
+        int t = 0;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            for (int j = 0; j < intStrings.length; ++j) {
+                t += Integer.valueOf(intStrings[j]);
+            }
+        }
+    }
+}
diff --git a/apct-tests/perftests/core/src/android/libcore/regression/IntegralToStringPerfTest.java b/apct-tests/perftests/core/src/android/libcore/regression/IntegralToStringPerfTest.java
new file mode 100644
index 0000000..5129fcb
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/libcore/regression/IntegralToStringPerfTest.java
@@ -0,0 +1,229 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.libcore.regression;
+
+import android.perftests.utils.BenchmarkState;
+import android.perftests.utils.PerfStatusReporter;
+import android.test.suitebuilder.annotation.LargeTest;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@LargeTest
+public class IntegralToStringPerfTest {
+    @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
+
+    private static final int SMALL = 12;
+    private static final int MEDIUM = 12345;
+    private static final int LARGE = 12345678;
+
+    @Test
+    public void time_IntegerToString_small() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            Integer.toString(SMALL);
+        }
+    }
+
+    @Test
+    public void time_IntegerToString_medium() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            Integer.toString(MEDIUM);
+        }
+    }
+
+    @Test
+    public void time_IntegerToString_large() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            Integer.toString(LARGE);
+        }
+    }
+
+    @Test
+    public void time_IntegerToString2_small() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            Integer.toString(SMALL, 2);
+        }
+    }
+
+    @Test
+    public void time_IntegerToString2_medium() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            Integer.toString(MEDIUM, 2);
+        }
+    }
+
+    @Test
+    public void time_IntegerToString2_large() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            Integer.toString(LARGE, 2);
+        }
+    }
+
+    @Test
+    public void time_IntegerToString10_small() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            Integer.toString(SMALL, 10);
+        }
+    }
+
+    @Test
+    public void time_IntegerToString10_medium() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            Integer.toString(MEDIUM, 10);
+        }
+    }
+
+    @Test
+    public void time_IntegerToString10_large() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            Integer.toString(LARGE, 10);
+        }
+    }
+
+    @Test
+    public void time_IntegerToString16_small() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            Integer.toString(SMALL, 16);
+        }
+    }
+
+    @Test
+    public void time_IntegerToString16_medium() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            Integer.toString(MEDIUM, 16);
+        }
+    }
+
+    @Test
+    public void time_IntegerToString16_large() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            Integer.toString(LARGE, 16);
+        }
+    }
+
+    @Test
+    public void time_IntegerToBinaryString_small() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            Integer.toBinaryString(SMALL);
+        }
+    }
+
+    @Test
+    public void time_IntegerToBinaryString_medium() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            Integer.toBinaryString(MEDIUM);
+        }
+    }
+
+    @Test
+    public void time_IntegerToBinaryString_large() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            Integer.toBinaryString(LARGE);
+        }
+    }
+
+    @Test
+    public void time_IntegerToHexString_small() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            Integer.toHexString(SMALL);
+        }
+    }
+
+    @Test
+    public void time_IntegerToHexString_medium() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            Integer.toHexString(MEDIUM);
+        }
+    }
+
+    @Test
+    public void time_IntegerToHexString_large() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            Integer.toHexString(LARGE);
+        }
+    }
+
+    @Test
+    public void time_StringBuilder_small() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            new StringBuilder().append(SMALL);
+        }
+    }
+
+    @Test
+    public void time_StringBuilder_medium() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            new StringBuilder().append(MEDIUM);
+        }
+    }
+
+    @Test
+    public void time_StringBuilder_large() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            new StringBuilder().append(LARGE);
+        }
+    }
+
+    @Test
+    public void time_Formatter_small() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            String.format("%d", SMALL);
+        }
+    }
+
+    @Test
+    public void time_Formatter_medium() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            String.format("%d", MEDIUM);
+        }
+    }
+
+    @Test
+    public void time_Formatter_large() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            String.format("%d", LARGE);
+        }
+    }
+}
diff --git a/apct-tests/perftests/core/src/android/libcore/regression/KeyPairGeneratorPerfTest.java b/apct-tests/perftests/core/src/android/libcore/regression/KeyPairGeneratorPerfTest.java
new file mode 100644
index 0000000..6fe9059
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/libcore/regression/KeyPairGeneratorPerfTest.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.libcore.regression;
+
+import android.perftests.utils.BenchmarkState;
+import android.perftests.utils.PerfStatusReporter;
+import android.test.suitebuilder.annotation.LargeTest;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.SecureRandom;
+import java.util.Arrays;
+import java.util.Collection;
+
+@RunWith(Parameterized.class)
+@LargeTest
+public class KeyPairGeneratorPerfTest {
+    @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
+
+    @Parameters(name = "mAlgorithm={0}, mImplementation={1}")
+    public static Collection<Object[]> data() {
+        return Arrays.asList(
+                new Object[][] {
+                    {Algorithm.RSA, Implementation.BouncyCastle},
+                    {Algorithm.DSA, Implementation.BouncyCastle},
+                    {Algorithm.RSA, Implementation.OpenSSL}
+                });
+    }
+
+    @Parameterized.Parameter(0)
+    public Algorithm mAlgorithm;
+
+    @Parameterized.Parameter(1)
+    public Implementation mImplementation;
+
+    public enum Algorithm {
+        RSA,
+        DSA,
+    };
+
+    public enum Implementation {
+        OpenSSL,
+        BouncyCastle
+    };
+
+    private String mGeneratorAlgorithm;
+    private KeyPairGenerator mGenerator;
+    private SecureRandom mRandom;
+
+    @Before
+    public void setUp() throws Exception {
+        this.mGeneratorAlgorithm = mAlgorithm.toString();
+
+        final String provider;
+        if (mImplementation == Implementation.BouncyCastle) {
+            provider = "BC";
+        } else {
+            provider = "AndroidOpenSSL";
+        }
+
+        this.mGenerator = KeyPairGenerator.getInstance(mGeneratorAlgorithm, provider);
+        this.mRandom = SecureRandom.getInstance("SHA1PRNG");
+        this.mGenerator.initialize(1024);
+    }
+
+    @Test
+    public void time() throws Exception {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            KeyPair keyPair = mGenerator.generateKeyPair();
+        }
+    }
+}
diff --git a/apct-tests/perftests/core/src/android/libcore/regression/LoopingBackwardsPerfTest.java b/apct-tests/perftests/core/src/android/libcore/regression/LoopingBackwardsPerfTest.java
new file mode 100644
index 0000000..414764d
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/libcore/regression/LoopingBackwardsPerfTest.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.libcore.regression;
+
+import android.perftests.utils.BenchmarkState;
+import android.perftests.utils.PerfStatusReporter;
+import android.test.suitebuilder.annotation.LargeTest;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+import java.util.Arrays;
+import java.util.Collection;
+
+/**
+ * Testing the old canard that looping backwards is faster.
+ *
+ * @author Kevin Bourrillion
+ */
+@RunWith(Parameterized.class)
+@LargeTest
+public class LoopingBackwardsPerfTest {
+    @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
+
+    @Parameters(name = "mMax={0}")
+    public static Collection<Object[]> data() {
+        return Arrays.asList(new Object[][] {{2}, {20}, {2000}, {20000000}});
+    }
+
+    @Parameterized.Parameter(0)
+    public int mMax;
+
+    @Test
+    public void timeForwards() {
+        int fake = 0;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            for (int j = 0; j < mMax; j++) {
+                fake += j;
+            }
+        }
+    }
+
+    @Test
+    public void timeBackwards() {
+        int fake = 0;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            for (int j = mMax - 1; j >= 0; j--) {
+                fake += j;
+            }
+        }
+    }
+}
diff --git a/apct-tests/perftests/core/src/android/libcore/regression/MathPerfTest.java b/apct-tests/perftests/core/src/android/libcore/regression/MathPerfTest.java
new file mode 100644
index 0000000..4c2d7fb
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/libcore/regression/MathPerfTest.java
@@ -0,0 +1,551 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.libcore.regression;
+
+import android.perftests.utils.BenchmarkState;
+import android.perftests.utils.PerfStatusReporter;
+import android.test.suitebuilder.annotation.LargeTest;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Many of these tests are bogus in that the cost will vary wildly depending on inputs. For _my_
+ * current purposes, that's okay. But beware!
+ */
+@RunWith(AndroidJUnit4.class)
+@LargeTest
+public class MathPerfTest {
+    @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
+
+    private final double mDouble = 1.2;
+    private final float mFloat = 1.2f;
+    private final int mInt = 1;
+    private final long mLong = 1L;
+
+    // NOTE: To avoid the benchmarked function from being optimized away, we store the result
+    // and use it as the benchmark's return value. This is good enough for now but may not be in
+    // the future, a smart compiler could determine that the result value will depend on whether
+    // we get into the loop or not and turn the whole loop into an if statement.
+
+    @Test
+    public void timeAbsD() {
+        double result = mDouble;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            result = Math.abs(mDouble);
+        }
+    }
+
+    @Test
+    public void timeAbsF() {
+        float result = mFloat;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            result = Math.abs(mFloat);
+        }
+    }
+
+    @Test
+    public void timeAbsI() {
+        int result = mInt;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            result = Math.abs(mInt);
+        }
+    }
+
+    @Test
+    public void timeAbsL() {
+        long result = mLong;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            result = Math.abs(mLong);
+        }
+    }
+
+    @Test
+    public void timeAcos() {
+        double result = mDouble;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            result = Math.acos(mDouble);
+        }
+    }
+
+    @Test
+    public void timeAsin() {
+        double result = mDouble;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            result = Math.asin(mDouble);
+        }
+    }
+
+    @Test
+    public void timeAtan() {
+        double result = mDouble;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            result = Math.atan(mDouble);
+        }
+    }
+
+    @Test
+    public void timeAtan2() {
+        double result = mDouble;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            result = Math.atan2(3, 4);
+        }
+    }
+
+    @Test
+    public void timeCbrt() {
+        double result = mDouble;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            result = Math.cbrt(mDouble);
+        }
+    }
+
+    @Test
+    public void timeCeil() {
+        double result = mDouble;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            result = Math.ceil(mDouble);
+        }
+    }
+
+    @Test
+    public void timeCopySignD() {
+        double result = mDouble;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            result = Math.copySign(mDouble, mDouble);
+        }
+    }
+
+    @Test
+    public void timeCopySignF() {
+        float result = mFloat;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            result = Math.copySign(mFloat, mFloat);
+        }
+    }
+
+    @Test
+    public void timeCopySignD_strict() {
+        double result = mDouble;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            result = StrictMath.copySign(mDouble, mDouble);
+        }
+    }
+
+    @Test
+    public void timeCopySignF_strict() {
+        float result = mFloat;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            result = StrictMath.copySign(mFloat, mFloat);
+        }
+    }
+
+    @Test
+    public void timeCos() {
+        double result = mDouble;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            result = Math.cos(mDouble);
+        }
+    }
+
+    @Test
+    public void timeCosh() {
+        double result = mDouble;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            result = Math.cosh(mDouble);
+        }
+    }
+
+    @Test
+    public void timeExp() {
+        double result = mDouble;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            result = Math.exp(mDouble);
+        }
+    }
+
+    @Test
+    public void timeExpm1() {
+        double result = mDouble;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            result = Math.expm1(mDouble);
+        }
+    }
+
+    @Test
+    public void timeFloor() {
+        double result = mDouble;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            result = Math.floor(mDouble);
+        }
+    }
+
+    @Test
+    public void timeGetExponentD() {
+        int result = mInt;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            result = Math.getExponent(mDouble);
+        }
+    }
+
+    @Test
+    public void timeGetExponentF() {
+        int result = mInt;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            result = Math.getExponent(mFloat);
+        }
+    }
+
+    @Test
+    public void timeHypot() {
+        double result = mDouble;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            result = Math.hypot(mDouble, mDouble);
+        }
+    }
+
+    @Test
+    public void timeIEEEremainder() {
+        double result = mDouble;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            result = Math.IEEEremainder(mDouble, mDouble);
+        }
+    }
+
+    @Test
+    public void timeLog() {
+        double result = mDouble;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            result = Math.log(mDouble);
+        }
+    }
+
+    @Test
+    public void timeLog10() {
+        double result = mDouble;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            result = Math.log10(mDouble);
+        }
+    }
+
+    @Test
+    public void timeLog1p() {
+        double result = mDouble;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            result = Math.log1p(mDouble);
+        }
+    }
+
+    @Test
+    public void timeMaxD() {
+        double result = mDouble;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            result = Math.max(mDouble, mDouble);
+        }
+    }
+
+    @Test
+    public void timeMaxF() {
+        float result = mFloat;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            result = Math.max(mFloat, mFloat);
+        }
+    }
+
+    @Test
+    public void timeMaxI() {
+        int result = mInt;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            result = Math.max(mInt, mInt);
+        }
+    }
+
+    @Test
+    public void timeMaxL() {
+        long result = mLong;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            result = Math.max(mLong, mLong);
+        }
+    }
+
+    @Test
+    public void timeMinD() {
+        double result = mDouble;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            result = Math.min(mDouble, mDouble);
+        }
+    }
+
+    @Test
+    public void timeMinF() {
+        float result = mFloat;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            result = Math.min(mFloat, mFloat);
+        }
+    }
+
+    @Test
+    public void timeMinI() {
+        int result = mInt;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            result = Math.min(mInt, mInt);
+        }
+    }
+
+    @Test
+    public void timeMinL() {
+        long result = mLong;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            result = Math.min(mLong, mLong);
+        }
+    }
+
+    @Test
+    public void timeNextAfterD() {
+        double result = mDouble;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            result = Math.nextAfter(mDouble, mDouble);
+        }
+    }
+
+    @Test
+    public void timeNextAfterF() {
+        float result = mFloat;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            result = Math.nextAfter(mFloat, mFloat);
+        }
+    }
+
+    @Test
+    public void timeNextUpD() {
+        double result = mDouble;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            result = Math.nextUp(mDouble);
+        }
+    }
+
+    @Test
+    public void timeNextUpF() {
+        float result = mFloat;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            result = Math.nextUp(mFloat);
+        }
+    }
+
+    @Test
+    public void timePow() {
+        double result = mDouble;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            result = Math.pow(mDouble, mDouble);
+        }
+    }
+
+    @Test
+    public void timeRandom() {
+        double result = mDouble;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            result = Math.random();
+        }
+    }
+
+    @Test
+    public void timeRint() {
+        double result = mDouble;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            result = Math.rint(mDouble);
+        }
+    }
+
+    @Test
+    public void timeRoundD() {
+        long result = mLong;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            result = Math.round(mDouble);
+        }
+    }
+
+    @Test
+    public void timeRoundF() {
+        int result = mInt;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            result = Math.round(mFloat);
+        }
+    }
+
+    @Test
+    public void timeScalbD() {
+        double result = mDouble;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            result = Math.scalb(mDouble, 5);
+        }
+    }
+
+    @Test
+    public void timeScalbF() {
+        float result = mFloat;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            result = Math.scalb(mFloat, 5);
+        }
+    }
+
+    @Test
+    public void timeSignumD() {
+        double result = mDouble;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            result = Math.signum(mDouble);
+        }
+    }
+
+    @Test
+    public void timeSignumF() {
+        float result = mFloat;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            result = Math.signum(mFloat);
+        }
+    }
+
+    @Test
+    public void timeSin() {
+        double result = mDouble;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            result = Math.sin(mDouble);
+        }
+    }
+
+    @Test
+    public void timeSinh() {
+        double result = mDouble;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            result = Math.sinh(mDouble);
+        }
+    }
+
+    @Test
+    public void timeSqrt() {
+        double result = mDouble;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            result = Math.sqrt(mDouble);
+        }
+    }
+
+    @Test
+    public void timeTan() {
+        double result = mDouble;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            result = Math.tan(mDouble);
+        }
+    }
+
+    @Test
+    public void timeTanh() {
+        double result = mDouble;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            result = Math.tanh(mDouble);
+        }
+    }
+
+    @Test
+    public void timeToDegrees() {
+        double result = mDouble;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            result = Math.toDegrees(mDouble);
+        }
+    }
+
+    @Test
+    public void timeToRadians() {
+        double result = mDouble;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            result = Math.toRadians(mDouble);
+        }
+    }
+
+    @Test
+    public void timeUlpD() {
+        double result = mDouble;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            result = Math.ulp(mDouble);
+        }
+    }
+
+    @Test
+    public void timeUlpF() {
+        float result = mFloat;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            result = Math.ulp(mFloat);
+        }
+    }
+}
diff --git a/apct-tests/perftests/core/src/android/libcore/regression/MessageDigestPerfTest.java b/apct-tests/perftests/core/src/android/libcore/regression/MessageDigestPerfTest.java
new file mode 100644
index 0000000..279681b
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/libcore/regression/MessageDigestPerfTest.java
@@ -0,0 +1,209 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.libcore.regression;
+
+import android.perftests.utils.BenchmarkState;
+import android.perftests.utils.PerfStatusReporter;
+import android.test.suitebuilder.annotation.LargeTest;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+import java.nio.ByteBuffer;
+import java.security.MessageDigest;
+import java.util.Arrays;
+import java.util.Collection;
+
+@RunWith(Parameterized.class)
+@LargeTest
+public class MessageDigestPerfTest {
+    @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
+
+    @Parameters(name = "mAlgorithm={0}")
+    public static Collection<Object[]> data() {
+        return Arrays.asList(
+                new Object[][] {
+                    {Algorithm.MD5},
+                    {Algorithm.SHA1},
+                    {Algorithm.SHA256},
+                    {Algorithm.SHA384},
+                    {Algorithm.SHA512}
+                });
+    }
+
+    @Parameterized.Parameter(0)
+    public Algorithm mAlgorithm;
+
+    public String mProvider = "AndroidOpenSSL";
+
+    private static final int DATA_SIZE = 8192;
+    private static final byte[] DATA = new byte[DATA_SIZE];
+
+    static {
+        for (int i = 0; i < DATA_SIZE; i++) {
+            DATA[i] = (byte) i;
+        }
+    }
+
+    private static final int LARGE_DATA_SIZE = 256 * 1024;
+    private static final byte[] LARGE_DATA = new byte[LARGE_DATA_SIZE];
+
+    static {
+        for (int i = 0; i < LARGE_DATA_SIZE; i++) {
+            LARGE_DATA[i] = (byte) i;
+        }
+    }
+
+    private static final ByteBuffer SMALL_BUFFER = ByteBuffer.wrap(DATA);
+    private static final ByteBuffer SMALL_DIRECT_BUFFER = ByteBuffer.allocateDirect(DATA_SIZE);
+
+    static {
+        SMALL_DIRECT_BUFFER.put(DATA);
+        SMALL_DIRECT_BUFFER.flip();
+    }
+
+    private static final ByteBuffer LARGE_BUFFER = ByteBuffer.wrap(LARGE_DATA);
+    private static final ByteBuffer LARGE_DIRECT_BUFFER =
+            ByteBuffer.allocateDirect(LARGE_DATA_SIZE);
+
+    static {
+        LARGE_DIRECT_BUFFER.put(LARGE_DATA);
+        LARGE_DIRECT_BUFFER.flip();
+    }
+
+    public enum Algorithm {
+        MD5,
+        SHA1,
+        SHA256,
+        SHA384,
+        SHA512
+    };
+
+    @Test
+    public void time() throws Exception {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            MessageDigest digest =
+                    MessageDigest.getInstance(mAlgorithm.toString(), mProvider);
+            digest.update(DATA, 0, DATA_SIZE);
+            digest.digest();
+        }
+    }
+
+    @Test
+    public void timeLargeArray() throws Exception {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            MessageDigest digest =
+                    MessageDigest.getInstance(mAlgorithm.toString(), mProvider);
+            digest.update(LARGE_DATA, 0, LARGE_DATA_SIZE);
+            digest.digest();
+        }
+    }
+
+    @Test
+    public void timeSmallChunkOfLargeArray() throws Exception {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            MessageDigest digest =
+                    MessageDigest.getInstance(mAlgorithm.toString(), mProvider);
+            digest.update(LARGE_DATA, LARGE_DATA_SIZE / 2, DATA_SIZE);
+            digest.digest();
+        }
+    }
+
+    @Test
+    public void timeSmallByteBuffer() throws Exception {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            MessageDigest digest =
+                    MessageDigest.getInstance(mAlgorithm.toString(), mProvider);
+            SMALL_BUFFER.position(0);
+            SMALL_BUFFER.limit(SMALL_BUFFER.capacity());
+            digest.update(SMALL_BUFFER);
+            digest.digest();
+        }
+    }
+
+    @Test
+    public void timeSmallDirectByteBuffer() throws Exception {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            MessageDigest digest =
+                    MessageDigest.getInstance(mAlgorithm.toString(), mProvider);
+            SMALL_DIRECT_BUFFER.position(0);
+            SMALL_DIRECT_BUFFER.limit(SMALL_DIRECT_BUFFER.capacity());
+            digest.update(SMALL_DIRECT_BUFFER);
+            digest.digest();
+        }
+    }
+
+    @Test
+    public void timeLargeByteBuffer() throws Exception {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            MessageDigest digest =
+                    MessageDigest.getInstance(mAlgorithm.toString(), mProvider);
+            LARGE_BUFFER.position(0);
+            LARGE_BUFFER.limit(LARGE_BUFFER.capacity());
+            digest.update(LARGE_BUFFER);
+            digest.digest();
+        }
+    }
+
+    @Test
+    public void timeLargeDirectByteBuffer() throws Exception {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            MessageDigest digest =
+                    MessageDigest.getInstance(mAlgorithm.toString(), mProvider);
+            LARGE_DIRECT_BUFFER.position(0);
+            LARGE_DIRECT_BUFFER.limit(LARGE_DIRECT_BUFFER.capacity());
+            digest.update(LARGE_DIRECT_BUFFER);
+            digest.digest();
+        }
+    }
+
+    @Test
+    public void timeSmallChunkOfLargeByteBuffer() throws Exception {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            MessageDigest digest =
+                    MessageDigest.getInstance(mAlgorithm.toString(), mProvider);
+            LARGE_BUFFER.position(LARGE_BUFFER.capacity() / 2);
+            LARGE_BUFFER.limit(LARGE_BUFFER.position() + DATA_SIZE);
+            digest.update(LARGE_BUFFER);
+            digest.digest();
+        }
+    }
+
+    @Test
+    public void timeSmallChunkOfLargeDirectByteBuffer() throws Exception {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            MessageDigest digest =
+                    MessageDigest.getInstance(mAlgorithm.toString(), mProvider);
+            LARGE_DIRECT_BUFFER.position(LARGE_DIRECT_BUFFER.capacity() / 2);
+            LARGE_DIRECT_BUFFER.limit(LARGE_DIRECT_BUFFER.position() + DATA_SIZE);
+            digest.update(LARGE_DIRECT_BUFFER);
+            digest.digest();
+        }
+    }
+}
diff --git a/apct-tests/perftests/core/src/android/libcore/regression/MutableIntPerfTest.java b/apct-tests/perftests/core/src/android/libcore/regression/MutableIntPerfTest.java
new file mode 100644
index 0000000..37bd73c
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/libcore/regression/MutableIntPerfTest.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.libcore.regression;
+
+import android.perftests.utils.BenchmarkState;
+import android.perftests.utils.PerfStatusReporter;
+import android.test.suitebuilder.annotation.LargeTest;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.concurrent.atomic.AtomicInteger;
+
+@RunWith(Parameterized.class)
+@LargeTest
+public final class MutableIntPerfTest {
+    @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
+
+    enum Kind {
+        ARRAY() {
+            int[] mValue = new int[1];
+
+            @Override
+            void timeCreate(BenchmarkState state) {
+                while (state.keepRunning()) {
+                    mValue = new int[] {5};
+                }
+            }
+
+            @Override
+            void timeIncrement(BenchmarkState state) {
+                while (state.keepRunning()) {
+                    mValue[0]++;
+                }
+            }
+
+            @Override
+            int timeGet(BenchmarkState state) {
+                int sum = 0;
+                while (state.keepRunning()) {
+                    sum += mValue[0];
+                }
+                return sum;
+            }
+        },
+        ATOMIC() {
+            AtomicInteger mValue = new AtomicInteger();
+
+            @Override
+            void timeCreate(BenchmarkState state) {
+                while (state.keepRunning()) {
+                    mValue = new AtomicInteger(5);
+                }
+            }
+
+            @Override
+            void timeIncrement(BenchmarkState state) {
+                while (state.keepRunning()) {
+                    mValue.incrementAndGet();
+                }
+            }
+
+            @Override
+            int timeGet(BenchmarkState state) {
+                int sum = 0;
+                while (state.keepRunning()) {
+                    sum += mValue.intValue();
+                }
+                return sum;
+            }
+        };
+
+        abstract void timeCreate(BenchmarkState state);
+
+        abstract void timeIncrement(BenchmarkState state);
+
+        abstract int timeGet(BenchmarkState state);
+    }
+
+    @Parameters(name = "mKind={0}")
+    public static Collection<Object[]> data() {
+        return Arrays.asList(new Object[][] {{Kind.ARRAY}, {Kind.ATOMIC}});
+    }
+
+    @Parameterized.Parameter(0)
+    public Kind mKind;
+
+    @Test
+    public void timeCreate() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        mKind.timeCreate(state);
+    }
+
+    @Test
+    public void timeIncrement() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        mKind.timeIncrement(state);
+    }
+
+    @Test
+    public void timeGet() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        mKind.timeGet(state);
+    }
+}
diff --git a/apct-tests/perftests/core/src/android/libcore/regression/NumberFormatPerfTest.java b/apct-tests/perftests/core/src/android/libcore/regression/NumberFormatPerfTest.java
new file mode 100644
index 0000000..dae185e
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/libcore/regression/NumberFormatPerfTest.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.libcore.regression;
+
+import android.perftests.utils.BenchmarkState;
+import android.perftests.utils.PerfStatusReporter;
+import android.test.suitebuilder.annotation.LargeTest;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.text.NumberFormat;
+import java.util.Locale;
+
+@RunWith(AndroidJUnit4.class)
+@LargeTest
+public class NumberFormatPerfTest {
+    @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
+
+    private static Locale sLocale = Locale.getDefault(Locale.Category.FORMAT);
+
+    @Test
+    public void time_instantiation() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            NumberFormat.getInstance(sLocale);
+        }
+    }
+}
diff --git a/apct-tests/perftests/core/src/android/libcore/regression/PriorityQueuePerfTest.java b/apct-tests/perftests/core/src/android/libcore/regression/PriorityQueuePerfTest.java
new file mode 100644
index 0000000..8801a56
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/libcore/regression/PriorityQueuePerfTest.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.libcore.regression;
+
+import android.perftests.utils.BenchmarkState;
+import android.perftests.utils.PerfStatusReporter;
+import android.test.suitebuilder.annotation.LargeTest;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.PriorityQueue;
+import java.util.Random;
+
+@RunWith(Parameterized.class)
+@LargeTest
+public class PriorityQueuePerfTest {
+    @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
+
+    @Parameters(name = "mQueueSize={0}, mHitRate={1}")
+    public static Collection<Object[]> data() {
+        return Arrays.asList(
+                new Object[][] {
+                    {100, 0},
+                    {1000, 0},
+                    {10000, 0},
+                    {100, 25},
+                    {1000, 25},
+                    {10000, 25},
+                    {100, 50},
+                    {1000, 50},
+                    {10000, 50},
+                    {100, 75},
+                    {1000, 75},
+                    {10000, 75},
+                    {100, 100},
+                    {1000, 100},
+                    {10000, 100}
+                });
+    }
+
+    @Parameterized.Parameter(0)
+    public int mQueueSize;
+
+    @Parameterized.Parameter(1)
+    public int mHitRate;
+
+    private PriorityQueue<Integer> mPq;
+    private PriorityQueue<Integer> mUsepq;
+    private List<Integer> mSeekElements;
+    private Random mRandom = new Random(189279387L);
+
+    @Before
+    public void setUp() throws Exception {
+        mPq = new PriorityQueue<Integer>();
+        mUsepq = new PriorityQueue<Integer>();
+        mSeekElements = new ArrayList<Integer>();
+        List<Integer> allElements = new ArrayList<Integer>();
+        int numShared = (int) (mQueueSize * ((double) mHitRate / 100));
+        // the total number of elements we require to engineer a hit rate of mHitRate%
+        int totalElements = 2 * mQueueSize - numShared;
+        for (int i = 0; i < totalElements; i++) {
+            allElements.add(i);
+        }
+        // shuffle these elements so that we get a reasonable distribution of missed elements
+        Collections.shuffle(allElements, mRandom);
+        // add shared elements
+        for (int i = 0; i < numShared; i++) {
+            mPq.add(allElements.get(i));
+            mSeekElements.add(allElements.get(i));
+        }
+        // add priority queue only elements (these won't be touched)
+        for (int i = numShared; i < mQueueSize; i++) {
+            mPq.add(allElements.get(i));
+        }
+        // add non-priority queue elements (these will be misses)
+        for (int i = mQueueSize; i < totalElements; i++) {
+            mSeekElements.add(allElements.get(i));
+        }
+        mUsepq = new PriorityQueue<Integer>(mPq);
+        // shuffle again so that elements are accessed in a different pattern than they were
+        // inserted
+        Collections.shuffle(mSeekElements, mRandom);
+    }
+
+    @Test
+    public void timeRemove() {
+        boolean fake = false;
+        int elementsSize = mSeekElements.size();
+        // At most allow the queue to empty 10%.
+        int resizingThreshold = mQueueSize / 10;
+        int i = 0;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            // Reset queue every so often. This will be called more often for smaller
+            // mQueueSizes, but since a copy is linear, it will also cost proportionally
+            // less, and hopefully it will approximately balance out.
+            if (++i % resizingThreshold == 0) {
+                mUsepq = new PriorityQueue<Integer>(mPq);
+            }
+            fake = mUsepq.remove(mSeekElements.get(i % elementsSize));
+        }
+    }
+}
diff --git a/apct-tests/perftests/core/src/android/libcore/regression/PropertyAccessPerfTest.java b/apct-tests/perftests/core/src/android/libcore/regression/PropertyAccessPerfTest.java
new file mode 100644
index 0000000..21ccba5
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/libcore/regression/PropertyAccessPerfTest.java
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2011 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.libcore.regression;
+
+import android.perftests.utils.BenchmarkState;
+import android.perftests.utils.PerfStatusReporter;
+import android.test.suitebuilder.annotation.LargeTest;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+
+@RunWith(AndroidJUnit4.class)
+@LargeTest
+public final class PropertyAccessPerfTest {
+    @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
+
+    private View mView = new View();
+    private Method mSetX;
+    private GeneratedProperty mGeneratedSetter = new GeneratedSetter();
+    private GeneratedProperty mGeneratedField = new GeneratedField();
+    private Field mX;
+    private Object[] mArgsBomX = new Object[1];
+
+    @Before
+    public void setUp() throws Exception {
+        mSetX = View.class.getDeclaredMethod("mSetX", float.class);
+        mX = View.class.getDeclaredField("mX");
+    }
+
+    @Test
+    public void timeDirectSetter() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            mView.mSetX(0.1f);
+        }
+    }
+
+    @Test
+    public void timeDirectFieldSet() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            mView.mX = 0.1f;
+        }
+    }
+
+    @Test
+    public void timeDirectSetterAndBomXing() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            Float value = 0.1f;
+            mView.mSetX(value);
+        }
+    }
+
+    @Test
+    public void timeDirectFieldSetAndBomXing() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            Float value = 0.1f;
+            mView.mX = value;
+        }
+    }
+
+    @Test
+    public void timeReflectionSetterAndTwoBomXes() throws Exception {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            mSetX.invoke(mView, 0.1f);
+        }
+    }
+
+    @Test
+    public void timeReflectionSetterAndOneBomX() throws Exception {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            mArgsBomX[0] = 0.1f;
+            mSetX.invoke(mView, mArgsBomX);
+        }
+    }
+
+    @Test
+    public void timeReflectionFieldSet() throws Exception {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            mX.setFloat(mView, 0.1f);
+        }
+    }
+
+    @Test
+    public void timeGeneratedSetter() throws Exception {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            mGeneratedSetter.setFloat(mView, 0.1f);
+        }
+    }
+
+    @Test
+    public void timeGeneratedFieldSet() throws Exception {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            mGeneratedField.setFloat(mView, 0.1f);
+        }
+    }
+
+    static class View {
+        float mX;
+
+        public void mSetX(float mX) {
+            this.mX = mX;
+        }
+    }
+
+    interface GeneratedProperty {
+        void setFloat(View v, float f);
+    }
+
+    static class GeneratedSetter implements GeneratedProperty {
+        public void setFloat(View v, float f) {
+            v.mSetX(f);
+        }
+    }
+
+    static class GeneratedField implements GeneratedProperty {
+        public void setFloat(View v, float f) {
+            v.mX = f;
+        }
+    }
+}
diff --git a/apct-tests/perftests/core/src/android/libcore/regression/ProviderPerfTest.java b/apct-tests/perftests/core/src/android/libcore/regression/ProviderPerfTest.java
new file mode 100644
index 0000000..f7bcf12
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/libcore/regression/ProviderPerfTest.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2015 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.libcore.regression;
+
+import android.perftests.utils.BenchmarkState;
+import android.perftests.utils.PerfStatusReporter;
+import android.test.suitebuilder.annotation.LargeTest;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.security.Provider;
+import java.security.Security;
+
+import javax.crypto.Cipher;
+
+@RunWith(AndroidJUnit4.class)
+@LargeTest
+public class ProviderPerfTest {
+    @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
+
+    @Test
+    public void timeStableProviders() throws Exception {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            Cipher c = Cipher.getInstance("RSA");
+        }
+    }
+
+    @Test
+    public void timeWithNewProvider() throws Exception {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            Security.addProvider(new MockProvider());
+            try {
+                Cipher c = Cipher.getInstance("RSA");
+            } finally {
+                Security.removeProvider("Mock");
+            }
+        }
+    }
+
+    private static class MockProvider extends Provider {
+        MockProvider() {
+            super("Mock", 1.0, "Mock me!");
+        }
+    }
+}
diff --git a/apct-tests/perftests/core/src/android/libcore/regression/R.java b/apct-tests/perftests/core/src/android/libcore/regression/R.java
new file mode 100644
index 0000000..d1641b3
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/libcore/regression/R.java
@@ -0,0 +1,28 @@
+/*
+ * 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.
+ */
+
+package android.libcore.regression;
+
+/**
+ * This file is a subset of the frameworks' R.java (resource definition) file
+ * with references to android specific annotations stripped out.
+ */
+public final class R {
+    private R() {}
+
+    public final int mTextAppearanceLargePopupMenu = 0;
+    public static final int WEEK_NUMBER_COLOR = 0;
+}
diff --git a/apct-tests/perftests/core/src/android/libcore/regression/RandomPerfTest.java b/apct-tests/perftests/core/src/android/libcore/regression/RandomPerfTest.java
new file mode 100644
index 0000000..d8bff4c
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/libcore/regression/RandomPerfTest.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.libcore.regression;
+
+import android.perftests.utils.BenchmarkState;
+import android.perftests.utils.PerfStatusReporter;
+import android.test.suitebuilder.annotation.LargeTest;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.security.SecureRandom;
+import java.util.Random;
+
+@RunWith(AndroidJUnit4.class)
+@LargeTest
+public class RandomPerfTest {
+    @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
+
+    @Test
+    public void timeNewRandom() throws Exception {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            Random rng = new Random();
+            rng.nextInt();
+        }
+    }
+
+    @Test
+    public void timeReusedRandom() throws Exception {
+        Random rng = new Random();
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            rng.nextInt();
+        }
+    }
+
+    @Test
+    public void timeReusedSecureRandom() throws Exception {
+        SecureRandom rng = new SecureRandom();
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            rng.nextInt();
+        }
+    }
+
+    @Test
+    public void timeNewSecureRandom() throws Exception {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            SecureRandom rng = new SecureRandom();
+            rng.nextInt();
+        }
+    }
+}
diff --git a/apct-tests/perftests/core/src/android/libcore/regression/RealToStringPerfTest.java b/apct-tests/perftests/core/src/android/libcore/regression/RealToStringPerfTest.java
new file mode 100644
index 0000000..2542df9
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/libcore/regression/RealToStringPerfTest.java
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.libcore.regression;
+
+import android.perftests.utils.BenchmarkState;
+import android.perftests.utils.PerfStatusReporter;
+import android.test.suitebuilder.annotation.LargeTest;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@LargeTest
+public class RealToStringPerfTest {
+    @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
+
+    private static final float SMALL = -123.45f;
+    private static final float MEDIUM = -123.45e8f;
+    private static final float LARGE = -123.45e36f;
+
+    @Test
+    public void timeFloat_toString_NaN() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            Float.toString(Float.NaN);
+        }
+    }
+
+    @Test
+    public void timeFloat_toString_NEGATIVE_INFINITY() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            Float.toString(Float.NEGATIVE_INFINITY);
+        }
+    }
+
+    @Test
+    public void timeFloat_toString_POSITIVE_INFINITY() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            Float.toString(Float.POSITIVE_INFINITY);
+        }
+    }
+
+    @Test
+    public void timeFloat_toString_zero() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            Float.toString(0.0f);
+        }
+    }
+
+    @Test
+    public void timeFloat_toString_minusZero() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            Float.toString(-0.0f);
+        }
+    }
+
+    @Test
+    public void timeFloat_toString_small() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            Float.toString(SMALL);
+        }
+    }
+
+    @Test
+    public void timeFloat_toString_medium() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            Float.toString(MEDIUM);
+        }
+    }
+
+    @Test
+    public void timeFloat_toString_large() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            Float.toString(LARGE);
+        }
+    }
+
+    @Test
+    public void timeStringBuilder_small() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            new StringBuilder().append(SMALL);
+        }
+    }
+
+    @Test
+    public void timeStringBuilder_medium() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            new StringBuilder().append(MEDIUM);
+        }
+    }
+
+    @Test
+    public void timeStringBuilder_large() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            new StringBuilder().append(LARGE);
+        }
+    }
+
+    @Test
+    public void timeFormatter_small() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            String.format("%f", SMALL);
+        }
+    }
+
+    @Test
+    public void timeFormatter_medium() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            String.format("%f", MEDIUM);
+        }
+    }
+
+    @Test
+    public void timeFormatter_large() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            String.format("%f", LARGE);
+        }
+    }
+
+    @Test
+    public void timeFormatter_dot2f_small() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            String.format("%.2f", SMALL);
+        }
+    }
+
+    @Test
+    public void timeFormatter_dot2f_medium() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            String.format("%.2f", MEDIUM);
+        }
+    }
+
+    @Test
+    public void timeFormatter_dot2f_large() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            String.format("%.2f", LARGE);
+        }
+    }
+}
diff --git a/apct-tests/perftests/core/src/android/libcore/regression/ReflectionPerfTest.java b/apct-tests/perftests/core/src/android/libcore/regression/ReflectionPerfTest.java
new file mode 100644
index 0000000..b06662c
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/libcore/regression/ReflectionPerfTest.java
@@ -0,0 +1,296 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.libcore.regression;
+
+import android.perftests.utils.BenchmarkState;
+import android.perftests.utils.PerfStatusReporter;
+import android.test.suitebuilder.annotation.LargeTest;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+
+@RunWith(AndroidJUnit4.class)
+@LargeTest
+public class ReflectionPerfTest {
+    @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
+
+    @Test
+    public void timeObject_getClass() throws Exception {
+        C c = new C();
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            c.getClass();
+        }
+    }
+
+    @Test
+    public void timeClass_getField() throws Exception {
+        Class<?> klass = C.class;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            klass.getField("f");
+        }
+    }
+
+    @Test
+    public void timeClass_getDeclaredField() throws Exception {
+        Class<?> klass = C.class;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            klass.getDeclaredField("f");
+        }
+    }
+
+    @Test
+    public void timeClass_getConstructor() throws Exception {
+        Class<?> klass = C.class;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            klass.getConstructor();
+        }
+    }
+
+    @Test
+    public void timeClass_newInstance() throws Exception {
+        Class<?> klass = C.class;
+        Constructor constructor = klass.getConstructor();
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            constructor.newInstance();
+        }
+    }
+
+    @Test
+    public void timeClass_getMethod() throws Exception {
+        Class<?> klass = C.class;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            klass.getMethod("m");
+        }
+    }
+
+    @Test
+    public void timeClass_getDeclaredMethod() throws Exception {
+        Class<?> klass = C.class;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            klass.getDeclaredMethod("m");
+        }
+    }
+
+    @Test
+    public void timeField_setInt() throws Exception {
+        Class<?> klass = C.class;
+        Field f = klass.getDeclaredField("f");
+        C instance = new C();
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            f.setInt(instance, 1);
+        }
+    }
+
+    @Test
+    public void timeField_getInt() throws Exception {
+        Class<?> klass = C.class;
+        Field f = klass.getDeclaredField("f");
+        C instance = new C();
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            f.getInt(instance);
+        }
+    }
+
+    @Test
+    public void timeMethod_invokeV() throws Exception {
+        Class<?> klass = C.class;
+        Method m = klass.getDeclaredMethod("m");
+        C instance = new C();
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            m.invoke(instance);
+        }
+    }
+
+    @Test
+    public void timeMethod_invokeStaticV() throws Exception {
+        Class<?> klass = C.class;
+        Method m = klass.getDeclaredMethod("sm");
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            m.invoke(null);
+        }
+    }
+
+    @Test
+    public void timeMethod_invokeI() throws Exception {
+        Class<?> klass = C.class;
+        Method m = klass.getDeclaredMethod("setField", int.class);
+        C instance = new C();
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            m.invoke(instance, 1);
+        }
+    }
+
+    @Test
+    public void timeMethod_invokePreBoxedI() throws Exception {
+        Class<?> klass = C.class;
+        Method m = klass.getDeclaredMethod("setField", int.class);
+        C instance = new C();
+        Integer one = Integer.valueOf(1);
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            m.invoke(instance, one);
+        }
+    }
+
+    @Test
+    public void timeMethod_invokeStaticI() throws Exception {
+        Class<?> klass = C.class;
+        Method m = klass.getDeclaredMethod("setStaticField", int.class);
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            m.invoke(null, 1);
+        }
+    }
+
+    @Test
+    public void timeMethod_invokeStaticPreBoxedI() throws Exception {
+        Class<?> klass = C.class;
+        Method m = klass.getDeclaredMethod("setStaticField", int.class);
+        Integer one = Integer.valueOf(1);
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            m.invoke(null, one);
+        }
+    }
+
+    @Test
+    public void timeRegularMethodInvocation() throws Exception {
+        C instance = new C();
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            instance.setField(1);
+        }
+    }
+
+    @Test
+    public void timeRegularConstructor() throws Exception {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            new C();
+        }
+    }
+
+    @Test
+    public void timeClass_classNewInstance() throws Exception {
+        Class<?> klass = C.class;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            klass.newInstance();
+        }
+    }
+
+    @Test
+    public void timeClass_isInstance() throws Exception {
+        D d = new D();
+        Class<?> klass = IC.class;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            klass.isInstance(d);
+        }
+    }
+
+    @Test
+    public void timeGetInstanceField() throws Exception {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            // TODO: Write a test script that generates both the classes we're
+            // reflecting on and the test case for each of its fields.
+            R.class.getField("mTextAppearanceLargePopupMenu");
+        }
+    }
+
+    @Test
+    public void timeGetStaticField() throws Exception {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            R.class.getField("WEEK_NUMBER_COLOR");
+        }
+    }
+
+    @Test
+    public void timeGetInterfaceStaticField() throws Exception {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            F.class.getField("SF");
+        }
+    }
+
+    @Test
+    public void timeGetSuperClassField() throws Exception {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            G.class.getField("f");
+        }
+    }
+
+    public static class C {
+        public static int sf = 0;
+        public int f = 0;
+
+        public C() {
+            // A non-empty constructor so we don't get optimized away.
+            f = 1;
+        }
+
+        public void m() {}
+
+        public static void sm() {}
+
+        public void setField(int value) {
+            f = value;
+        }
+
+        public static void setStaticField(int value) {
+            sf = value;
+        }
+    }
+
+    interface IA {}
+
+    interface IB extends IA {}
+
+    interface IC extends IB {
+        int SF = 0;
+    }
+
+    class D implements IC {}
+
+    class E extends D {}
+
+    class F extends E implements IB {}
+
+    class G extends C {}
+}
diff --git a/api/Android.bp b/api/Android.bp
index 69d602a..3fc3991 100644
--- a/api/Android.bp
+++ b/api/Android.bp
@@ -188,6 +188,37 @@
         "$(location :frameworks-base-api-module-lib-current.txt)",
 }
 
+// This produces the same annotations.zip as framework-doc-stubs, but by using
+// outputs from individual modules instead of all the source code.
+genrule_defaults {
+    name: "sdk-annotations-defaults",
+    out: ["annotations.zip"],
+    tools: [
+        "merge_annotation_zips",
+        "soong_zip",
+    ],
+    cmd: "$(location merge_annotation_zips) $(genDir)/out $(in) && " +
+        "$(location soong_zip) -o $(out) -C $(genDir)/out -D $(genDir)/out",
+}
+
+genrule {
+    name: "sdk-annotations.zip",
+    defaults: ["sdk-annotations-defaults"],
+    srcs: [
+        ":android-non-updatable-doc-stubs{.annotations.zip}",
+        ":all-modules-public-annotations",
+    ],
+}
+
+genrule {
+    name: "sdk-annotations-system.zip",
+    defaults: ["sdk-annotations-defaults"],
+    srcs: [
+        ":android-non-updatable-doc-stubs-system{.annotations.zip}",
+        ":all-modules-system-annotations",
+    ],
+}
+
 genrule {
     name: "combined-removed-dex",
     visibility: [
diff --git a/api/api.go b/api/api.go
index 93f1354..bf6b085 100644
--- a/api/api.go
+++ b/api/api.go
@@ -148,17 +148,18 @@
 	ctx.CreateModule(genrule.GenRuleFactory, &props)
 }
 
-// This produces the same annotations.zip as framework-doc-stubs, but by using
-// outputs from individual modules instead of all the source code.
-func createMergedAnnotations(ctx android.LoadHookContext, modules []string) {
-	props := genruleProps{}
-	props.Name = proptools.StringPtr("sdk-annotations.zip")
-	props.Tools = []string{"merge_annotation_zips", "soong_zip"}
-	props.Out = []string{"annotations.zip"}
-	props.Cmd = proptools.StringPtr("$(location merge_annotation_zips) $(genDir)/out $(in) && " +
-		"$(location soong_zip) -o $(out) -C $(genDir)/out -D $(genDir)/out")
-	props.Srcs = append([]string{":android-non-updatable-doc-stubs{.annotations.zip}"}, createSrcs(modules, "{.public.annotations.zip}")...)
-	ctx.CreateModule(genrule.GenRuleFactory, &props)
+func createMergedPublicAnnotationsFilegroup(ctx android.LoadHookContext, modules []string) {
+	props := fgProps{}
+	props.Name = proptools.StringPtr("all-modules-public-annotations")
+	props.Srcs = createSrcs(modules, "{.public.annotations.zip}")
+	ctx.CreateModule(android.FileGroupFactory, &props)
+}
+
+func createMergedSystemAnnotationsFilegroup(ctx android.LoadHookContext, modules []string) {
+	props := fgProps{}
+	props.Name = proptools.StringPtr("all-modules-system-annotations")
+	props.Srcs = createSrcs(modules, "{.system.annotations.zip}")
+	ctx.CreateModule(android.FileGroupFactory, &props)
 }
 
 func createFilteredApiVersions(ctx android.LoadHookContext, modules []string) {
@@ -299,7 +300,8 @@
 	createMergedFrameworkModuleLibStubs(ctx, bootclasspath)
 	createMergedFrameworkImpl(ctx, bootclasspath)
 
-	createMergedAnnotations(ctx, bootclasspath)
+	createMergedPublicAnnotationsFilegroup(ctx, bootclasspath)
+	createMergedSystemAnnotationsFilegroup(ctx, bootclasspath)
 
 	createFilteredApiVersions(ctx, bootclasspath)
 
diff --git a/cmds/incidentd/src/Section.cpp b/cmds/incidentd/src/Section.cpp
index e56ed39..581367a 100644
--- a/cmds/incidentd/src/Section.cpp
+++ b/cmds/incidentd/src/Section.cpp
@@ -733,7 +733,7 @@
         return -errno;
     }
 
-    const std::set<int> hal_pids = get_interesting_hal_pids();
+    const std::set<int> hal_pids = get_interesting_pids();
 
     auto pooledBuffer = get_buffer_from_pool();
     ProtoOutputStream proto(pooledBuffer);
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index abc2b74..cf3f07f 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -230,6 +230,7 @@
     field public static final String READ_WALLPAPER_INTERNAL = "android.permission.READ_WALLPAPER_INTERNAL";
     field public static final String READ_WIFI_CREDENTIAL = "android.permission.READ_WIFI_CREDENTIAL";
     field public static final String REAL_GET_TASKS = "android.permission.REAL_GET_TASKS";
+    field public static final String RECEIVE_BLUETOOTH_MAP = "android.permission.RECEIVE_BLUETOOTH_MAP";
     field public static final String RECEIVE_DATA_ACTIVITY_CHANGE = "android.permission.RECEIVE_DATA_ACTIVITY_CHANGE";
     field public static final String RECEIVE_DEVICE_CUSTOMIZATION_READY = "android.permission.RECEIVE_DEVICE_CUSTOMIZATION_READY";
     field public static final String RECEIVE_EMERGENCY_BROADCAST = "android.permission.RECEIVE_EMERGENCY_BROADCAST";
@@ -311,6 +312,7 @@
     field public static final String WRITE_EMBEDDED_SUBSCRIPTIONS = "android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS";
     field @Deprecated public static final String WRITE_MEDIA_STORAGE = "android.permission.WRITE_MEDIA_STORAGE";
     field public static final String WRITE_OBB = "android.permission.WRITE_OBB";
+    field public static final String WRITE_SMS = "android.permission.WRITE_SMS";
   }
 
   public static final class Manifest.permission_group {
@@ -1978,6 +1980,7 @@
     method @Nullable @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL) public android.content.Intent registerReceiverForAllUsers(@Nullable android.content.BroadcastReceiver, @NonNull android.content.IntentFilter, @Nullable String, @Nullable android.os.Handler, int);
     method public abstract void sendBroadcast(android.content.Intent, @Nullable String, @Nullable android.os.Bundle);
     method @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public abstract void sendBroadcastAsUser(@RequiresPermission android.content.Intent, android.os.UserHandle, @Nullable String, @Nullable android.os.Bundle);
+    method public void sendBroadcastMultiplePermissions(@NonNull android.content.Intent, @NonNull String[], @Nullable android.app.BroadcastOptions);
     method public abstract void sendOrderedBroadcast(@NonNull android.content.Intent, @Nullable String, @Nullable android.os.Bundle, @Nullable android.content.BroadcastReceiver, @Nullable android.os.Handler, int, @Nullable String, @Nullable android.os.Bundle);
     method @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public void startActivityAsUser(@NonNull @RequiresPermission android.content.Intent, @NonNull android.os.UserHandle);
     field public static final String APP_HIBERNATION_SERVICE = "app_hibernation";
@@ -2077,6 +2080,7 @@
     field public static final String ACTION_UPGRADE_SETUP = "android.intent.action.UPGRADE_SETUP";
     field public static final String ACTION_USER_ADDED = "android.intent.action.USER_ADDED";
     field public static final String ACTION_USER_REMOVED = "android.intent.action.USER_REMOVED";
+    field public static final String ACTION_USER_SWITCHED = "android.intent.action.USER_SWITCHED";
     field public static final String ACTION_VOICE_ASSIST = "android.intent.action.VOICE_ASSIST";
     field public static final String CATEGORY_LEANBACK_SETTINGS = "android.intent.category.LEANBACK_SETTINGS";
     field public static final String EXTRA_CALLING_PACKAGE = "android.intent.extra.CALLING_PACKAGE";
@@ -2097,7 +2101,9 @@
     field public static final String EXTRA_RESULT_NEEDED = "android.intent.extra.RESULT_NEEDED";
     field public static final String EXTRA_ROLE_NAME = "android.intent.extra.ROLE_NAME";
     field public static final String EXTRA_UNKNOWN_INSTANT_APP = "android.intent.extra.UNKNOWN_INSTANT_APP";
+    field public static final String EXTRA_USER_HANDLE = "android.intent.extra.user_handle";
     field public static final String EXTRA_VERIFICATION_BUNDLE = "android.intent.extra.VERIFICATION_BUNDLE";
+    field public static final int FLAG_RECEIVER_INCLUDE_BACKGROUND = 16777216; // 0x1000000
     field public static final int FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT = 67108864; // 0x4000000
     field public static final String METADATA_SETUP_VERSION = "android.SETUP_VERSION";
   }
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index bfbb910..51ecd4c 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -149,6 +149,7 @@
     method @NonNull @RequiresPermission(android.Manifest.permission.START_TASKS_FROM_RECENTS) public static android.app.ActivityOptions makeCustomTaskAnimation(@NonNull android.content.Context, int, int, @Nullable android.os.Handler, @Nullable android.app.ActivityOptions.OnAnimationStartedListener, @Nullable android.app.ActivityOptions.OnAnimationFinishedListener);
     method public static void setExitTransitionTimeout(long);
     method public void setLaunchActivityType(int);
+    method public void setLaunchTaskDisplayAreaFeatureId(int);
     method public void setLaunchWindowingMode(int);
     method public void setLaunchedFromBubble(boolean);
     method public void setTaskAlwaysOnTop(boolean);
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 6a877f9..d7ff7e9 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -4366,8 +4366,8 @@
         try {
             getService().broadcastIntentWithFeature(
                     null, null, intent, null, null, Activity.RESULT_OK, null, null,
-                    null /*requiredPermissions*/, null /*excludedPermissions*/, appOp, null, false,
-                    true, userId);
+                    null /*requiredPermissions*/, null /*excludedPermissions*/,
+                    null /*excludedPackages*/, appOp, null, false, true, userId);
         } catch (RemoteException ex) {
         }
     }
diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java
index 0ff9f66..a92cbf3 100644
--- a/core/java/android/app/ActivityOptions.java
+++ b/core/java/android/app/ActivityOptions.java
@@ -21,6 +21,7 @@
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
 import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
 import static android.view.Display.INVALID_DISPLAY;
+import static android.window.DisplayAreaOrganizer.FEATURE_UNDEFINED;
 
 import android.annotation.IntDef;
 import android.annotation.NonNull;
@@ -208,6 +209,14 @@
             "android.activity.launchTaskDisplayAreaToken";
 
     /**
+     * The task display area feature id the activity should be launched into.
+     * @see #setLaunchTaskDisplayAreaFeatureId(int)
+     * @hide
+     */
+    private static final String KEY_LAUNCH_TASK_DISPLAY_AREA_FEATURE_ID =
+            "android.activity.launchTaskDisplayAreaFeatureId";
+
+    /**
      * The root task token the activity should be launched into.
      * @see #setLaunchRootTask(WindowContainerToken)
      * @hide
@@ -404,6 +413,7 @@
     private int mLaunchDisplayId = INVALID_DISPLAY;
     private int mCallerDisplayId = INVALID_DISPLAY;
     private WindowContainerToken mLaunchTaskDisplayArea;
+    private int mLaunchTaskDisplayAreaFeatureId = FEATURE_UNDEFINED;
     private WindowContainerToken mLaunchRootTask;
     private IBinder mLaunchTaskFragmentToken;
     @WindowConfiguration.WindowingMode
@@ -1147,6 +1157,8 @@
         mLaunchDisplayId = opts.getInt(KEY_LAUNCH_DISPLAY_ID, INVALID_DISPLAY);
         mCallerDisplayId = opts.getInt(KEY_CALLER_DISPLAY_ID, INVALID_DISPLAY);
         mLaunchTaskDisplayArea = opts.getParcelable(KEY_LAUNCH_TASK_DISPLAY_AREA_TOKEN);
+        mLaunchTaskDisplayAreaFeatureId = opts.getInt(KEY_LAUNCH_TASK_DISPLAY_AREA_FEATURE_ID,
+                FEATURE_UNDEFINED);
         mLaunchRootTask = opts.getParcelable(KEY_LAUNCH_ROOT_TASK_TOKEN);
         mLaunchTaskFragmentToken = opts.getBinder(KEY_LAUNCH_TASK_FRAGMENT_TOKEN);
         mLaunchWindowingMode = opts.getInt(KEY_LAUNCH_WINDOWING_MODE, WINDOWING_MODE_UNDEFINED);
@@ -1472,6 +1484,23 @@
     }
 
     /** @hide */
+    public int getLaunchTaskDisplayAreaFeatureId() {
+        return mLaunchTaskDisplayAreaFeatureId;
+    }
+
+    /**
+     * Sets the TaskDisplayArea feature Id the activity should launch into.
+     * Note: It is possible to have TaskDisplayAreas with the same featureId on multiple displays.
+     * If launch display id is not specified, the TaskDisplayArea on the default display will be
+     * used.
+     * @hide
+     */
+    @TestApi
+    public void setLaunchTaskDisplayAreaFeatureId(int launchTaskDisplayAreaFeatureId) {
+        mLaunchTaskDisplayAreaFeatureId = launchTaskDisplayAreaFeatureId;
+    }
+
+    /** @hide */
     public WindowContainerToken getLaunchRootTask() {
         return mLaunchRootTask;
     }
@@ -1902,6 +1931,9 @@
         if (mLaunchTaskDisplayArea != null) {
             b.putParcelable(KEY_LAUNCH_TASK_DISPLAY_AREA_TOKEN, mLaunchTaskDisplayArea);
         }
+        if (mLaunchTaskDisplayAreaFeatureId != FEATURE_UNDEFINED) {
+            b.putInt(KEY_LAUNCH_TASK_DISPLAY_AREA_FEATURE_ID, mLaunchTaskDisplayAreaFeatureId);
+        }
         if (mLaunchRootTask != null) {
             b.putParcelable(KEY_LAUNCH_ROOT_TASK_TOKEN, mLaunchRootTask);
         }
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 24046c0..52228e5 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -1185,7 +1185,7 @@
             ActivityManager.getService().broadcastIntentWithFeature(
                     mMainThread.getApplicationThread(), getAttributionTag(), intent, resolvedType,
                     null, Activity.RESULT_OK, null, null, null, null /*excludedPermissions=*/,
-                    AppOpsManager.OP_NONE, null, false, false, getUserId());
+                    null, AppOpsManager.OP_NONE, null, false, false, getUserId());
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -1202,7 +1202,7 @@
             ActivityManager.getService().broadcastIntentWithFeature(
                     mMainThread.getApplicationThread(), getAttributionTag(), intent, resolvedType,
                     null, Activity.RESULT_OK, null, null, receiverPermissions,
-                    null /*excludedPermissions=*/, AppOpsManager.OP_NONE, null, false, false,
+                    null /*excludedPermissions=*/, null, AppOpsManager.OP_NONE, null, false, false,
                     getUserId());
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
@@ -1218,7 +1218,7 @@
             ActivityManager.getService().broadcastIntentWithFeature(
                     mMainThread.getApplicationThread(), getAttributionTag(), intent, resolvedType,
                     null, Activity.RESULT_OK, null, null, receiverPermissions,
-                    null /*excludedPermissions=*/, AppOpsManager.OP_NONE, null, false, false,
+                    null /*excludedPermissions=*/, null, AppOpsManager.OP_NONE, null, false, false,
                     getUserId());
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
@@ -1235,8 +1235,8 @@
             ActivityManager.getService().broadcastIntentWithFeature(
                     mMainThread.getApplicationThread(), getAttributionTag(), intent, resolvedType,
                     null, Activity.RESULT_OK, null, null, receiverPermissions,
-                    null /*excludedPermissions=*/, AppOpsManager.OP_NONE, options, false, false,
-                    getUserId());
+                    null /*excludedPermissions=*/, null /*excludedPackages*/,
+                    AppOpsManager.OP_NONE, options, false, false, getUserId());
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -1251,7 +1251,7 @@
             ActivityManager.getService().broadcastIntentWithFeature(
                     mMainThread.getApplicationThread(), getAttributionTag(), intent, resolvedType,
                     null, Activity.RESULT_OK, null, null, receiverPermissions,
-                    null /*excludedPermissions=*/, AppOpsManager.OP_NONE, null, false, false,
+                    null /*excludedPermissions=*/, null, AppOpsManager.OP_NONE, null, false, false,
                     user.getIdentifier());
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
@@ -1260,7 +1260,7 @@
 
     @Override
     public void sendBroadcastMultiplePermissions(Intent intent, String[] receiverPermissions,
-            String[] excludedPermissions) {
+            String[] excludedPermissions, String[] excludedPackages) {
         warnIfCallingFromSystemProcess();
         String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
         try {
@@ -1268,7 +1268,7 @@
             ActivityManager.getService().broadcastIntentWithFeature(
                     mMainThread.getApplicationThread(), getAttributionTag(), intent, resolvedType,
                     null, Activity.RESULT_OK, null, null, receiverPermissions, excludedPermissions,
-                    AppOpsManager.OP_NONE, null, false, false, getUserId());
+                    excludedPackages, AppOpsManager.OP_NONE, null, false, false, getUserId());
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -1285,8 +1285,8 @@
             ActivityManager.getService().broadcastIntentWithFeature(
                     mMainThread.getApplicationThread(), getAttributionTag(), intent, resolvedType,
                     null, Activity.RESULT_OK, null, null, receiverPermissions,
-                    null /*excludedPermissions=*/, AppOpsManager.OP_NONE, options, false, false,
-                    getUserId());
+                    null /*excludedPermissions=*/, null, AppOpsManager.OP_NONE, options, false,
+                    false, getUserId());
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -1303,7 +1303,7 @@
             ActivityManager.getService().broadcastIntentWithFeature(
                     mMainThread.getApplicationThread(), getAttributionTag(), intent, resolvedType,
                     null, Activity.RESULT_OK, null, null, receiverPermissions,
-                    null /*excludedPermissions=*/, appOp, null, false, false, getUserId());
+                    null /*excludedPermissions=*/, null, appOp, null, false, false, getUserId());
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -1320,7 +1320,7 @@
             ActivityManager.getService().broadcastIntentWithFeature(
                     mMainThread.getApplicationThread(), getAttributionTag(), intent, resolvedType,
                     null, Activity.RESULT_OK, null, null, receiverPermissions,
-                    null /*excludedPermissions=*/, AppOpsManager.OP_NONE, null, true, false,
+                    null /*excludedPermissions=*/, null, AppOpsManager.OP_NONE, null, true, false,
                     getUserId());
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
@@ -1384,7 +1384,7 @@
             ActivityManager.getService().broadcastIntentWithFeature(
                     mMainThread.getApplicationThread(), getAttributionTag(), intent, resolvedType,
                     rd, initialCode, initialData, initialExtras, receiverPermissions,
-                    null /*excludedPermissions=*/, appOp, options, true, false, getUserId());
+                    null /*excludedPermissions=*/, null, appOp, options, true, false, getUserId());
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -1398,7 +1398,7 @@
             ActivityManager.getService().broadcastIntentWithFeature(
                     mMainThread.getApplicationThread(), getAttributionTag(), intent, resolvedType,
                     null, Activity.RESULT_OK, null, null, null, null /*excludedPermissions=*/,
-                    AppOpsManager.OP_NONE, null, false, false, user.getIdentifier());
+                    null, AppOpsManager.OP_NONE, null, false, false, user.getIdentifier());
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -1421,8 +1421,8 @@
             ActivityManager.getService().broadcastIntentWithFeature(
                     mMainThread.getApplicationThread(), getAttributionTag(), intent, resolvedType,
                     null, Activity.RESULT_OK, null, null, receiverPermissions,
-                    null /*excludedPermissions=*/, AppOpsManager.OP_NONE, options, false, false,
-                    user.getIdentifier());
+                    null /*excludedPermissions=*/, null, AppOpsManager.OP_NONE, options, false,
+                    false, user.getIdentifier());
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -1439,7 +1439,8 @@
             ActivityManager.getService().broadcastIntentWithFeature(
                     mMainThread.getApplicationThread(), getAttributionTag(), intent, resolvedType,
                     null, Activity.RESULT_OK, null, null, receiverPermissions,
-                    null /*excludedPermissions=*/, appOp, null, false, false, user.getIdentifier());
+                    null /*excludedPermissions=*/, null, appOp, null, false, false,
+                    user.getIdentifier());
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -1490,7 +1491,7 @@
             ActivityManager.getService().broadcastIntentWithFeature(
                     mMainThread.getApplicationThread(), getAttributionTag(), intent, resolvedType,
                     rd, initialCode, initialData, initialExtras, receiverPermissions,
-                    null /*excludedPermissions=*/, appOp, options, true, false,
+                    null /*excludedPermissions=*/, null, appOp, options, true, false,
                     user.getIdentifier());
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
@@ -1532,7 +1533,7 @@
             ActivityManager.getService().broadcastIntentWithFeature(
                     mMainThread.getApplicationThread(), getAttributionTag(), intent, resolvedType,
                     null, Activity.RESULT_OK, null, null, null, null /*excludedPermissions=*/,
-                    AppOpsManager.OP_NONE, null, false, true, getUserId());
+                    null, AppOpsManager.OP_NONE, null, false, true, getUserId());
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -1571,7 +1572,7 @@
             ActivityManager.getService().broadcastIntentWithFeature(
                     mMainThread.getApplicationThread(), getAttributionTag(), intent, resolvedType,
                     null, Activity.RESULT_OK, null, null, null, null /*excludedPermissions=*/,
-                    AppOpsManager.OP_NONE, options, false, true, getUserId());
+                    null, AppOpsManager.OP_NONE, options, false, true, getUserId());
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -1607,7 +1608,7 @@
             ActivityManager.getService().broadcastIntentWithFeature(
                     mMainThread.getApplicationThread(), getAttributionTag(), intent, resolvedType,
                     rd, initialCode, initialData, initialExtras, null,
-                    null /*excludedPermissions=*/, AppOpsManager.OP_NONE, null, true, true,
+                    null /*excludedPermissions=*/, null, AppOpsManager.OP_NONE, null, true, true,
                     getUserId());
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
@@ -1640,7 +1641,7 @@
             ActivityManager.getService().broadcastIntentWithFeature(
                     mMainThread.getApplicationThread(), getAttributionTag(), intent, resolvedType,
                     null, Activity.RESULT_OK, null, null, null, null /*excludedPermissions=*/,
-                    AppOpsManager.OP_NONE, null, false, true, user.getIdentifier());
+                    null, AppOpsManager.OP_NONE, null, false, true, user.getIdentifier());
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -1655,7 +1656,7 @@
             ActivityManager.getService().broadcastIntentWithFeature(
                     mMainThread.getApplicationThread(), getAttributionTag(), intent, resolvedType,
                     null, Activity.RESULT_OK, null, null, null, null /*excludedPermissions=*/,
-                    AppOpsManager.OP_NONE, options, false, true, user.getIdentifier());
+                    null, AppOpsManager.OP_NONE, options, false, true, user.getIdentifier());
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -1690,7 +1691,7 @@
             ActivityManager.getService().broadcastIntentWithFeature(
                     mMainThread.getApplicationThread(), getAttributionTag(), intent, resolvedType,
                     rd, initialCode, initialData, initialExtras, null,
-                    null /*excludedPermissions=*/, AppOpsManager.OP_NONE, null, true, true,
+                    null /*excludedPermissions=*/, null, AppOpsManager.OP_NONE, null, true, true,
                     user.getIdentifier());
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index df95f8f..f2c808b 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -138,7 +138,7 @@
     int broadcastIntentWithFeature(in IApplicationThread caller, in String callingFeatureId,
             in Intent intent, in String resolvedType, in IIntentReceiver resultTo, int resultCode,
             in String resultData, in Bundle map, in String[] requiredPermissions, in String[] excludePermissions,
-            int appOp, in Bundle options, boolean serialized, boolean sticky, int userId);
+            in String[] excludePackages, int appOp, in Bundle options, boolean serialized, boolean sticky, int userId);
     void unbroadcastIntent(in IApplicationThread caller, in Intent intent, int userId);
     @UnsupportedAppUsage
     oneway void finishReceiver(in IBinder who, int resultCode, in String resultData, in Bundle map,
diff --git a/core/java/android/app/smartspace/OWNERS b/core/java/android/app/smartspace/OWNERS
index 19ef9d7..4d9a633 100644
--- a/core/java/android/app/smartspace/OWNERS
+++ b/core/java/android/app/smartspace/OWNERS
@@ -1,2 +1 @@
-srazdan@google.com
-alexmang@google.com
\ No newline at end of file
+include /core/java/android/service/smartspace/OWNERS
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 402007d..de9d491 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -37,6 +37,7 @@
 import android.annotation.UiContext;
 import android.annotation.UserIdInt;
 import android.app.ActivityManager;
+import android.app.BroadcastOptions;
 import android.app.GameManager;
 import android.app.IApplicationThread;
 import android.app.IServiceConnection;
@@ -2224,6 +2225,19 @@
      */
     public void sendBroadcastMultiplePermissions(@NonNull Intent intent,
             @NonNull String[] receiverPermissions, @Nullable String[] excludedPermissions) {
+        sendBroadcastMultiplePermissions(intent, receiverPermissions, excludedPermissions, null);
+    }
+
+
+    /**
+     * Like {@link #sendBroadcastMultiplePermissions(Intent, String[], String[])}, but also allows
+     * specification of a list of excluded packages.
+     *
+     * @hide
+     */
+    public void sendBroadcastMultiplePermissions(@NonNull Intent intent,
+            @NonNull String[] receiverPermissions, @Nullable String[] excludedPermissions,
+            @Nullable String[] excludedPackages) {
         throw new RuntimeException("Not implemented. Must override in a subclass.");
     }
 
@@ -2248,6 +2262,27 @@
     }
 
     /**
+     * Version of {@link #sendBroadcastMultiplePermissions(Intent, String[])} that allows you to
+     * specify the {@link android.app.BroadcastOptions}.
+     *
+     * @param intent The Intent to broadcast; all receivers matching this
+     *               Intent will receive the broadcast.
+     * @param receiverPermissions Array of names of permissions that a receiver must hold
+     *                            in order to receive your broadcast.
+     *                            If empty, no permissions are required.
+     * @param options Additional sending options, generated from a
+     *                {@link android.app.BroadcastOptions}.
+     * @see #sendBroadcastMultiplePermissions(Intent, String[])
+     * @see android.app.BroadcastOptions
+     * @hide
+     */
+    @SystemApi
+    public void sendBroadcastMultiplePermissions(@NonNull Intent intent,
+            @NonNull String[] receiverPermissions, @Nullable BroadcastOptions options) {
+        sendBroadcastMultiplePermissions(intent, receiverPermissions, options.toBundle());
+    }
+
+    /**
      * Broadcast the given intent to all interested BroadcastReceivers, allowing
      * an array of required permissions to be enforced.  This call is asynchronous; it returns
      * immediately, and you will continue executing while the receivers are run.  No results are
diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java
index 3a02004..18a46cf 100644
--- a/core/java/android/content/ContextWrapper.java
+++ b/core/java/android/content/ContextWrapper.java
@@ -494,8 +494,10 @@
     /** @hide */
     @Override
     public void sendBroadcastMultiplePermissions(@NonNull Intent intent,
-            @NonNull String[] receiverPermissions, @Nullable String[] excludedPermissions) {
-        mBase.sendBroadcastMultiplePermissions(intent, receiverPermissions, excludedPermissions);
+            @NonNull String[] receiverPermissions, @Nullable String[] excludedPermissions,
+            @Nullable String[] excludedPackages) {
+        mBase.sendBroadcastMultiplePermissions(intent, receiverPermissions, excludedPermissions,
+                excludedPackages);
     }
 
     /** @hide */
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 22c838c..76591ca 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -3836,7 +3836,7 @@
      * {@link android.Manifest.permission#MANAGE_USERS} to receive this broadcast.
      * @hide
      */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
+    @SystemApi
     public static final String ACTION_USER_SWITCHED =
             "android.intent.action.USER_SWITCHED";
 
@@ -5970,6 +5970,8 @@
      *
      * @hide
      */
+    @SystemApi
+    @SuppressLint("ActionValue")
     public static final String EXTRA_USER_HANDLE =
             "android.intent.extra.user_handle";
 
@@ -6824,6 +6826,7 @@
      *
      * @hide
      */
+    @SystemApi
     public static final int FLAG_RECEIVER_INCLUDE_BACKGROUND = 0x01000000;
     /**
      * If set, the broadcast will never go to manifest receivers in background (cached
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index a411eee..61325bc 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -168,7 +168,7 @@
      * signature checks} or
      * <a href="https://developer.android.com/training/articles/security-tips#Permissions">permissions</a>.
      *
-     * <p><b>Warning:</b> Note that does flag not behave the same as
+     * <p><b>Warning:</b> Note that this flag does not behave the same as
      * {@link android.R.attr#protectionLevel android:protectionLevel} {@code system} or
      * {@code signatureOrSystem}.
      */
diff --git a/core/java/android/debug/AdbManagerInternal.java b/core/java/android/debug/AdbManagerInternal.java
index d730129..e448706 100644
--- a/core/java/android/debug/AdbManagerInternal.java
+++ b/core/java/android/debug/AdbManagerInternal.java
@@ -55,6 +55,12 @@
     public abstract File getAdbTempKeysFile();
 
     /**
+     * Notify the AdbManager that the key files have changed and any in-memory state should be
+     * reloaded.
+     */
+    public abstract void notifyKeyFilesUpdated();
+
+    /**
      * Starts adbd for a transport.
      */
     public abstract void startAdbdForTransport(byte transportType);
diff --git a/core/java/android/debug/OWNERS b/core/java/android/debug/OWNERS
new file mode 100644
index 0000000..b97f795
--- /dev/null
+++ b/core/java/android/debug/OWNERS
@@ -0,0 +1 @@
+include platform/packages/modules/adb:/OWNERS
diff --git a/core/java/android/hardware/hdmi/HdmiPlaybackClient.java b/core/java/android/hardware/hdmi/HdmiPlaybackClient.java
index d06bc1d..3e41d63 100644
--- a/core/java/android/hardware/hdmi/HdmiPlaybackClient.java
+++ b/core/java/android/hardware/hdmi/HdmiPlaybackClient.java
@@ -122,6 +122,9 @@
     }
 
     private IHdmiControlCallback getCallbackWrapper(final OneTouchPlayCallback callback) {
+        if (callback == null) {
+            throw new IllegalArgumentException("OneTouchPlayCallback cannot be null.");
+        }
         return new IHdmiControlCallback.Stub() {
             @Override
             public void onComplete(int result) {
@@ -131,6 +134,9 @@
     }
 
     private IHdmiControlCallback getCallbackWrapper(final DisplayStatusCallback callback) {
+        if (callback == null) {
+            throw new IllegalArgumentException("DisplayStatusCallback cannot be null.");
+        }
         return new IHdmiControlCallback.Stub() {
             @Override
             public void onComplete(int status) {
diff --git a/core/java/android/hardware/radio/OWNERS b/core/java/android/hardware/radio/OWNERS
index ea4421e..d2bdd64 100644
--- a/core/java/android/hardware/radio/OWNERS
+++ b/core/java/android/hardware/radio/OWNERS
@@ -1,2 +1,3 @@
-twasilczyk@google.com
-randolphs@google.com
+xuweilin@google.com
+oscarazu@google.com
+keunyoung@google.com
diff --git a/core/java/android/os/Binder.java b/core/java/android/os/Binder.java
index 59db8f4..a7c7ce2 100644
--- a/core/java/android/os/Binder.java
+++ b/core/java/android/os/Binder.java
@@ -350,7 +350,7 @@
     }
 
     /**
-     * Reset the identity of the incoming IPC on the current thread. This can
+     * Reset the kernel binder identity of the incoming IPC on the current thread. This can
      * be useful if, while handling an incoming call, you will be calling
      * on interfaces of other objects that may be local to your process and
      * need to do permission checks on the calls coming into them (so they
@@ -369,7 +369,7 @@
     public static final native long clearCallingIdentity();
 
     /**
-     * Restore the identity of the incoming IPC on the current thread
+     * Restore the kernel binder identity of the incoming IPC on the current thread
      * back to a previously identity that was returned by {@link
      * #clearCallingIdentity}.
      *
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
index 6411f42..9649d38 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -33,6 +33,7 @@
 import android.util.ExceptionUtils;
 import android.util.Log;
 import android.util.MathUtils;
+import android.util.Pair;
 import android.util.Size;
 import android.util.SizeF;
 import android.util.Slog;
@@ -247,6 +248,7 @@
     private ArrayMap<Class, Object> mClassCookies;
 
     private RuntimeException mStack;
+    private boolean mRecycled = false;
 
     /** @hide */
     @TestApi
@@ -528,6 +530,7 @@
         if (res == null) {
             res = new Parcel(0);
         } else {
+            res.mRecycled = false;
             if (DEBUG_RECYCLE) {
                 res.mStack = new RuntimeException();
             }
@@ -556,7 +559,15 @@
      * the object after this call.
      */
     public final void recycle() {
-        if (DEBUG_RECYCLE) mStack = null;
+        if (mRecycled) {
+            Log.w(TAG, "Recycle called on unowned Parcel. (recycle twice?)", mStack);
+        }
+        mRecycled = true;
+
+        // We try to reset the entire object here, but in order to be
+        // able to print a stack when a Parcel is recycled twice, that
+        // is cleared in obtain instead.
+
         mClassCookies = null;
         freeBuffer();
 
@@ -4848,28 +4859,36 @@
         if (name == null) {
             return null;
         }
-        Parcelable.Creator<?> creator;
-        HashMap<String, Parcelable.Creator<?>> map;
-        synchronized (mCreators) {
-            map = mCreators.get(loader);
+
+        Pair<Parcelable.Creator<?>, Class<?>> creatorAndParcelableClass;
+        synchronized (sPairedCreators) {
+            HashMap<String, Pair<Parcelable.Creator<?>, Class<?>>> map =
+                    sPairedCreators.get(loader);
             if (map == null) {
-                map = new HashMap<>();
-                mCreators.put(loader, map);
+                sPairedCreators.put(loader, new HashMap<>());
+                mCreators.put(loader, new HashMap<>());
+                creatorAndParcelableClass = null;
+            } else {
+                creatorAndParcelableClass = map.get(name);
             }
-            creator = map.get(name);
         }
-        if (creator != null) {
+
+        if (creatorAndParcelableClass != null) {
+            Parcelable.Creator<?> creator = creatorAndParcelableClass.first;
+            Class<?> parcelableClass = creatorAndParcelableClass.second;
             if (clazz != null) {
-                Class<?> parcelableClass = creator.getClass().getEnclosingClass();
                 if (!clazz.isAssignableFrom(parcelableClass)) {
                     throw new BadTypeParcelableException("Parcelable creator " + name + " is not "
                             + "a subclass of required class " + clazz.getName()
                             + " provided in the parameter");
                 }
             }
+
             return (Parcelable.Creator<T>) creator;
         }
 
+        Parcelable.Creator<?> creator;
+        Class<?> parcelableClass;
         try {
             // If loader == null, explicitly emulate Class.forName(String) "caller
             // classloader" behavior.
@@ -4877,7 +4896,7 @@
                     (loader == null ? getClass().getClassLoader() : loader);
             // Avoid initializing the Parcelable class until we know it implements
             // Parcelable and has the necessary CREATOR field. http://b/1171613.
-            Class<?> parcelableClass = Class.forName(name, false /* initialize */,
+            parcelableClass = Class.forName(name, false /* initialize */,
                     parcelableClassLoader);
             if (!Parcelable.class.isAssignableFrom(parcelableClass)) {
                 throw new BadParcelableException("Parcelable protocol requires subclassing "
@@ -4924,8 +4943,9 @@
                     + "CREATOR on class " + name);
         }
 
-        synchronized (mCreators) {
-            map.put(name, creator);
+        synchronized (sPairedCreators) {
+            sPairedCreators.get(loader).put(name, Pair.create(creator, parcelableClass));
+            mCreators.get(loader).put(name, creator);
         }
 
         return (Parcelable.Creator<T>) creator;
@@ -5076,12 +5096,17 @@
         }
     }
 
-    // Cache of previously looked up CREATOR.createFromParcel() methods for
-    // particular classes.  Keys are the names of the classes, values are
-    // Method objects.
+
+    // Left due to the UnsupportedAppUsage. Do not use anymore - use sPairedCreators instead
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
-    private static final HashMap<ClassLoader,HashMap<String,Parcelable.Creator<?>>>
-        mCreators = new HashMap<>();
+    private static final HashMap<ClassLoader, HashMap<String, Parcelable.Creator<?>>>
+            mCreators = new HashMap<>();
+
+    // Cache of previously looked up CREATOR.createFromParcel() methods for particular classes.
+    // Keys are the names of the classes, values are a pair consisting of a parcelable creator,
+    // and the class of the parcelable type for the object.
+    private static final HashMap<ClassLoader, HashMap<String,
+            Pair<Parcelable.Creator<?>, Class<?>>>> sPairedCreators = new HashMap<>();
 
     /** @hide for internal use only. */
     static protected final Parcel obtain(int obj) {
@@ -5105,6 +5130,7 @@
         if (res == null) {
             res = new Parcel(obj);
         } else {
+            res.mRecycled = false;
             if (DEBUG_RECYCLE) {
                 res.mStack = new RuntimeException();
             }
@@ -5153,7 +5179,8 @@
     @Override
     protected void finalize() throws Throwable {
         if (DEBUG_RECYCLE) {
-            if (mStack != null) {
+            // we could always have this log on, but it's spammy
+            if (!mRecycled) {
                 Log.w(TAG, "Client did not call Parcel.recycle()", mStack);
             }
         }
diff --git a/core/java/android/os/VibrationAttributes.java b/core/java/android/os/VibrationAttributes.java
index 43ea2e7..a52c989 100644
--- a/core/java/android/os/VibrationAttributes.java
+++ b/core/java/android/os/VibrationAttributes.java
@@ -133,6 +133,9 @@
 
     /**
      * Flag requesting vibration effect to be played even under limited interruptions.
+     *
+     * <p>Only privileged apps can ignore user settings that limit interruptions, and this
+     * flag will be ignored otherwise.
      */
     public static final int FLAG_BYPASS_INTERRUPTION_POLICY = 0x1;
 
diff --git a/core/java/android/os/ZygoteProcess.java b/core/java/android/os/ZygoteProcess.java
index bf28981..3cb5c60 100644
--- a/core/java/android/os/ZygoteProcess.java
+++ b/core/java/android/os/ZygoteProcess.java
@@ -82,13 +82,6 @@
     private static final String LOG_TAG = "ZygoteProcess";
 
     /**
-     * The default value for enabling the unspecialized app process (USAP) pool.  This value will
-     * not be used if the devices has a DeviceConfig profile pushed to it that contains a value for
-     * this key.
-     */
-    private static final String USAP_POOL_ENABLED_DEFAULT = "false";
-
-    /**
      * The name of the socket used to communicate with the primary zygote.
      */
     private final LocalSocketAddress mZygoteSocketAddress;
@@ -793,14 +786,8 @@
     private boolean fetchUsapPoolEnabledProp() {
         boolean origVal = mUsapPoolEnabled;
 
-        final String propertyString = Zygote.getConfigurationProperty(
-                ZygoteConfig.USAP_POOL_ENABLED, USAP_POOL_ENABLED_DEFAULT);
-
-        if (!propertyString.isEmpty()) {
-            mUsapPoolEnabled = Zygote.getConfigurationPropertyBoolean(
-                  ZygoteConfig.USAP_POOL_ENABLED,
-                  Boolean.parseBoolean(USAP_POOL_ENABLED_DEFAULT));
-        }
+        mUsapPoolEnabled = ZygoteConfig.getBool(
+            ZygoteConfig.USAP_POOL_ENABLED, ZygoteConfig.USAP_POOL_ENABLED_DEFAULT);
 
         boolean valueChanged = origVal != mUsapPoolEnabled;
 
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 134cca1..595fd4a 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -16400,7 +16400,7 @@
         public @interface SyncDisabledMode {}
 
         /**
-         * Sync is not not disabled.
+         * Sync is not disabled.
          *
          * @hide
          */
diff --git a/core/java/android/service/appprediction/OWNERS b/core/java/android/service/appprediction/OWNERS
index fe012da..6efb975 100644
--- a/core/java/android/service/appprediction/OWNERS
+++ b/core/java/android/service/appprediction/OWNERS
@@ -1,2 +1,4 @@
 adamcohen@google.com
+hyunyoungs@google.com
+pinyaoting@google.com
 sunnygoyal@google.com
diff --git a/core/java/android/service/smartspace/OWNERS b/core/java/android/service/smartspace/OWNERS
index 19ef9d7..d3acd3d3 100644
--- a/core/java/android/service/smartspace/OWNERS
+++ b/core/java/android/service/smartspace/OWNERS
@@ -1,2 +1,4 @@
+hyunyoungs@google.com
+awickham@google.com
 srazdan@google.com
-alexmang@google.com
\ No newline at end of file
+sunnygoyal@google.com
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index ce212e2..34330b2 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -160,7 +160,7 @@
     private static final int MAGIC = 0xBA757475; // 'BATSTATS'
 
     // Current on-disk Parcel version
-    static final int VERSION = 200;
+    static final int VERSION = 201;
 
     // The maximum number of names wakelocks we will keep track of
     // per uid; once the limit is reached, we batch the remaining wakelocks
@@ -929,6 +929,28 @@
                 screenBrightnessTimers[i].reset(false, elapsedRealtimeUs);
             }
         }
+
+        /**
+         * Write data to summary parcel
+         */
+        public void writeSummaryToParcel(Parcel out, long elapsedRealtimeUs) {
+            screenOnTimer.writeSummaryFromParcelLocked(out, elapsedRealtimeUs);
+            screenDozeTimer.writeSummaryFromParcelLocked(out, elapsedRealtimeUs);
+            for (int i = 0; i < NUM_SCREEN_BRIGHTNESS_BINS; i++) {
+                screenBrightnessTimers[i].writeSummaryFromParcelLocked(out, elapsedRealtimeUs);
+            }
+        }
+
+        /**
+         * Read data from summary parcel
+         */
+        public void readSummaryFromParcel(Parcel in) {
+            screenOnTimer.readSummaryFromParcelLocked(in);
+            screenDozeTimer.readSummaryFromParcelLocked(in);
+            for (int i = 0; i < NUM_SCREEN_BRIGHTNESS_BINS; i++) {
+                screenBrightnessTimers[i].readSummaryFromParcelLocked(in);
+            }
+        }
     }
 
     DisplayBatteryStats[] mPerDisplayBatteryStats;
@@ -15636,6 +15658,10 @@
         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
             mScreenBrightnessTimer[i].readSummaryFromParcelLocked(in);
         }
+        final int numDisplays = in.readInt();
+        for (int i = 0; i < numDisplays; i++) {
+            mPerDisplayBatteryStats[i].readSummaryFromParcel(in);
+        }
         mInteractive = false;
         mInteractiveTimer.readSummaryFromParcelLocked(in);
         mPhoneOn = false;
@@ -16135,6 +16161,11 @@
         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
             mScreenBrightnessTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
         }
+        final int numDisplays = mPerDisplayBatteryStats.length;
+        out.writeInt(numDisplays);
+        for (int i = 0; i < numDisplays; i++) {
+            mPerDisplayBatteryStats[i].writeSummaryToParcel(out, NOWREAL_SYS);
+        }
         mInteractiveTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
         mPowerSaveModeEnabledTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
         out.writeLong(mLongestLightIdleTimeMs);
diff --git a/core/java/com/android/internal/os/ZygoteConfig.java b/core/java/com/android/internal/os/ZygoteConfig.java
index 6ebcae1..e5dc874 100644
--- a/core/java/com/android/internal/os/ZygoteConfig.java
+++ b/core/java/com/android/internal/os/ZygoteConfig.java
@@ -16,6 +16,9 @@
 
 package com.android.internal.os;
 
+import android.os.SystemProperties;
+import android.provider.DeviceConfig;
+
 /**
  * Flag names for configuring the zygote.
  *
@@ -26,15 +29,87 @@
     /** If {@code true}, enables the unspecialized app process (USAP) pool feature */
     public static final String USAP_POOL_ENABLED = "usap_pool_enabled";
 
+    /**
+     * The default value for enabling the unspecialized app process (USAP) pool.  This value will
+     * not be used if the devices has a DeviceConfig profile pushed to it that contains a value for
+     * this key or if the System Property dalvik.vm.usap_pool_enabled is set.
+     */
+    public static final boolean USAP_POOL_ENABLED_DEFAULT = false;
+
+
+
     /** The threshold used to determine if the pool should be refilled */
     public static final String USAP_POOL_REFILL_THRESHOLD = "usap_refill_threshold";
 
+    public static final int USAP_POOL_REFILL_THRESHOLD_DEFAULT = 1;
+
+
+
     /** The maximum number of processes to keep in the USAP pool */
     public static final String USAP_POOL_SIZE_MAX = "usap_pool_size_max";
 
+    public static final int USAP_POOL_SIZE_MAX_DEFAULT = 3;
+
+    /**
+     * The maximim value that will be accepted from the USAP_POOL_SIZE_MAX device property.
+     * is a mirror of USAP_POOL_MAX_LIMIT found in com_android_internal_os_Zygote.cpp.
+     */
+    public static final int USAP_POOL_SIZE_MAX_LIMIT = 100;
+
+
+
     /** The minimum number of processes to keep in the USAP pool */
     public static final String USAP_POOL_SIZE_MIN = "usap_pool_size_min";
 
+    public static final int USAP_POOL_SIZE_MIN_DEFAULT = 1;
+
+    /**
+     * The minimum value that will be accepted from the USAP_POOL_SIZE_MIN device property.
+     */
+    public static final int USAP_POOL_SIZE_MIN_LIMIT = 1;
+
+
+
     /** The number of milliseconds to delay before refilling the USAP pool */
     public static final String USAP_POOL_REFILL_DELAY_MS = "usap_pool_refill_delay_ms";
+
+    public static final int USAP_POOL_REFILL_DELAY_MS_DEFAULT = 3000;
+
+    public static final String PROPERTY_PREFIX_DEVICE_CONFIG = "persist.device_config";
+    public static final String PROPERTY_PREFIX_SYSTEM = "dalvik.vm.";
+
+    private static String getDeviceConfig(String name) {
+        return SystemProperties.get(
+            String.join(
+                ".",
+                PROPERTY_PREFIX_DEVICE_CONFIG,
+                DeviceConfig.NAMESPACE_RUNTIME_NATIVE,
+                name));
+    }
+
+    /**
+     * Get a property value from SystemProperties and convert it to an integer value.
+     */
+    public static int getInt(String name, int defaultValue) {
+        final String propString = getDeviceConfig(name);
+
+        if (!propString.isEmpty()) {
+            return Integer.parseInt(propString);
+        } else {
+            return SystemProperties.getInt(PROPERTY_PREFIX_SYSTEM + name, defaultValue);
+        }
+    }
+
+    /**
+     * Get a property value from SystemProperties and convert it to a Boolean value.
+     */
+    public static boolean getBool(String name, boolean defaultValue) {
+        final String propString = getDeviceConfig(name);
+
+        if (!propString.isEmpty()) {
+            return Boolean.parseBoolean(propString);
+        } else {
+            return SystemProperties.getBoolean(PROPERTY_PREFIX_SYSTEM + name, defaultValue);
+        }
+    }
 }
diff --git a/core/java/com/android/internal/os/ZygoteServer.java b/core/java/com/android/internal/os/ZygoteServer.java
index 4d2266b..f8598f2 100644
--- a/core/java/com/android/internal/os/ZygoteServer.java
+++ b/core/java/com/android/internal/os/ZygoteServer.java
@@ -49,26 +49,6 @@
     // TODO (chriswailes): Change this so it is set with Zygote or ZygoteSecondary as appropriate
     public static final String TAG = "ZygoteServer";
 
-    /**
-     * The maximim value that will be accepted from the USAP_POOL_SIZE_MAX device property.
-     * is a mirror of USAP_POOL_MAX_LIMIT found in com_android_internal_os_Zygote.cpp.
-     */
-    private static final int USAP_POOL_SIZE_MAX_LIMIT = 100;
-
-    /**
-     * The minimum value that will be accepted from the USAP_POOL_SIZE_MIN device property.
-     */
-    private static final int USAP_POOL_SIZE_MIN_LIMIT = 1;
-
-    /** The default value used for the USAP_POOL_SIZE_MAX device property */
-    private static final String USAP_POOL_SIZE_MAX_DEFAULT = "10";
-
-    /** The default value used for the USAP_POOL_SIZE_MIN device property */
-    private static final String USAP_POOL_SIZE_MIN_DEFAULT = "1";
-
-    /** The default value used for the USAP_REFILL_DELAY_MS device property */
-    private static final String USAP_POOL_REFILL_DELAY_MS_DEFAULT = "3000";
-
     /** The "not a timestamp" value for the refill delay timestamp mechanism. */
     private static final int INVALID_TIMESTAMP = -1;
 
@@ -264,46 +244,35 @@
 
     private void fetchUsapPoolPolicyProps() {
         if (mUsapPoolSupported) {
-            final String usapPoolSizeMaxPropString = Zygote.getConfigurationProperty(
-                    ZygoteConfig.USAP_POOL_SIZE_MAX, USAP_POOL_SIZE_MAX_DEFAULT);
+            mUsapPoolSizeMax = Integer.min(
+                ZygoteConfig.getInt(
+                    ZygoteConfig.USAP_POOL_SIZE_MAX,
+                    ZygoteConfig.USAP_POOL_SIZE_MAX_DEFAULT),
+                ZygoteConfig.USAP_POOL_SIZE_MAX_LIMIT);
 
-            if (!usapPoolSizeMaxPropString.isEmpty()) {
-                mUsapPoolSizeMax = Integer.min(Integer.parseInt(
-                        usapPoolSizeMaxPropString), USAP_POOL_SIZE_MAX_LIMIT);
-            }
+            mUsapPoolSizeMin = Integer.max(
+                ZygoteConfig.getInt(
+                    ZygoteConfig.USAP_POOL_SIZE_MIN,
+                    ZygoteConfig.USAP_POOL_SIZE_MIN_DEFAULT),
+                ZygoteConfig.USAP_POOL_SIZE_MIN_LIMIT);
 
-            final String usapPoolSizeMinPropString = Zygote.getConfigurationProperty(
-                    ZygoteConfig.USAP_POOL_SIZE_MIN, USAP_POOL_SIZE_MIN_DEFAULT);
-
-            if (!usapPoolSizeMinPropString.isEmpty()) {
-                mUsapPoolSizeMin = Integer.max(
-                        Integer.parseInt(usapPoolSizeMinPropString), USAP_POOL_SIZE_MIN_LIMIT);
-            }
-
-            final String usapPoolRefillThresholdPropString = Zygote.getConfigurationProperty(
+            mUsapPoolRefillThreshold = Integer.min(
+                ZygoteConfig.getInt(
                     ZygoteConfig.USAP_POOL_REFILL_THRESHOLD,
-                    Integer.toString(mUsapPoolSizeMax / 2));
+                    ZygoteConfig.USAP_POOL_REFILL_THRESHOLD_DEFAULT),
+                mUsapPoolSizeMax);
 
-            if (!usapPoolRefillThresholdPropString.isEmpty()) {
-                mUsapPoolRefillThreshold = Integer.min(
-                        Integer.parseInt(usapPoolRefillThresholdPropString),
-                        mUsapPoolSizeMax);
-            }
-
-            final String usapPoolRefillDelayMsPropString = Zygote.getConfigurationProperty(
-                    ZygoteConfig.USAP_POOL_REFILL_DELAY_MS, USAP_POOL_REFILL_DELAY_MS_DEFAULT);
-
-            if (!usapPoolRefillDelayMsPropString.isEmpty()) {
-                mUsapPoolRefillDelayMs = Integer.parseInt(usapPoolRefillDelayMsPropString);
-            }
+            mUsapPoolRefillDelayMs = ZygoteConfig.getInt(
+                ZygoteConfig.USAP_POOL_REFILL_DELAY_MS,
+                ZygoteConfig.USAP_POOL_REFILL_DELAY_MS_DEFAULT);
 
             // Validity check
             if (mUsapPoolSizeMin >= mUsapPoolSizeMax) {
                 Log.w(TAG, "The max size of the USAP pool must be greater than the minimum size."
                         + "  Restoring default values.");
 
-                mUsapPoolSizeMax = Integer.parseInt(USAP_POOL_SIZE_MAX_DEFAULT);
-                mUsapPoolSizeMin = Integer.parseInt(USAP_POOL_SIZE_MIN_DEFAULT);
+                mUsapPoolSizeMax = ZygoteConfig.USAP_POOL_SIZE_MAX_DEFAULT;
+                mUsapPoolSizeMin = ZygoteConfig.USAP_POOL_SIZE_MIN_DEFAULT;
                 mUsapPoolRefillThreshold = mUsapPoolSizeMax / 2;
             }
         }
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index 51939b2..682dbc31 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -381,6 +381,7 @@
                 // (e.g. gDefaultServiceManager)
                 "libbinder",
                 "libhidlbase", // libhwbinder is in here
+                "libvintf",
             ],
         },
     },
diff --git a/core/jni/android_os_Parcel.cpp b/core/jni/android_os_Parcel.cpp
index 0d530f6..bb4ab39 100644
--- a/core/jni/android_os_Parcel.cpp
+++ b/core/jni/android_os_Parcel.cpp
@@ -549,10 +549,15 @@
        return NULL;
     }
 
-    // do not marshall if there are binder objects in the parcel
+    if (parcel->isForRpc()) {
+        jniThrowException(env, "java/lang/RuntimeException", "Tried to marshall an RPC Parcel.");
+        return NULL;
+    }
+
     if (parcel->objectsCount())
     {
-        jniThrowException(env, "java/lang/RuntimeException", "Tried to marshall a Parcel that contained Binder objects.");
+        jniThrowException(env, "java/lang/RuntimeException",
+                          "Tried to marshall a Parcel that contains objects (binders or FDs).");
         return NULL;
     }
 
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index 1122c20..3622029 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -94,6 +94,10 @@
 
 #include "nativebridge/native_bridge.h"
 
+#if defined(__BIONIC__)
+extern "C" void android_reset_stack_guards();
+#endif
+
 namespace {
 
 // TODO (chriswailes): Add a function to initialize native Zygote data.
@@ -412,6 +416,7 @@
 }
 
 // This signal handler is for zygote mode, since the zygote must reap its children
+NO_STACK_PROTECTOR
 static void SigChldHandler(int /*signal_number*/, siginfo_t* info, void* /*ucontext*/) {
     pid_t pid;
     int status;
@@ -2042,6 +2047,7 @@
 static bool gPreloadFdsExtracted = false;
 
 // Utility routine to fork a process from the zygote.
+NO_STACK_PROTECTOR
 pid_t zygote::ForkCommon(JNIEnv* env, bool is_system_server,
                          const std::vector<int>& fds_to_close,
                          const std::vector<int>& fds_to_ignore,
@@ -2098,6 +2104,11 @@
       setpriority(PRIO_PROCESS, 0, PROCESS_PRIORITY_MIN);
     }
 
+#if defined(__BIONIC__)
+    // Reset the stack guard for the new process.
+    android_reset_stack_guards();
+#endif
+
     // The child process.
     PreApplicationInit();
 
@@ -2130,6 +2141,7 @@
   PreApplicationInit();
 }
 
+NO_STACK_PROTECTOR
 static jint com_android_internal_os_Zygote_nativeForkAndSpecialize(
         JNIEnv* env, jclass, jint uid, jint gid, jintArray gids, jint runtime_flags,
         jobjectArray rlimits, jint mount_external, jstring se_info, jstring nice_name,
@@ -2184,6 +2196,7 @@
     return pid;
 }
 
+NO_STACK_PROTECTOR
 static jint com_android_internal_os_Zygote_nativeForkSystemServer(
         JNIEnv* env, jclass, uid_t uid, gid_t gid, jintArray gids,
         jint runtime_flags, jobjectArray rlimits, jlong permitted_capabilities,
@@ -2255,6 +2268,7 @@
  * @param is_priority_fork  Controls the nice level assigned to the newly created process
  * @return child pid in the parent, 0 in the child
  */
+NO_STACK_PROTECTOR
 static jint com_android_internal_os_Zygote_nativeForkApp(JNIEnv* env,
                                                          jclass,
                                                          jint read_pipe_fd,
@@ -2269,6 +2283,7 @@
                             args_known == JNI_TRUE, is_priority_fork == JNI_TRUE, true);
 }
 
+NO_STACK_PROTECTOR
 int zygote::forkApp(JNIEnv* env,
                     int read_pipe_fd,
                     int write_pipe_fd,
diff --git a/core/jni/com_android_internal_os_Zygote.h b/core/jni/com_android_internal_os_Zygote.h
index b87396c..15f53e0 100644
--- a/core/jni/com_android_internal_os_Zygote.h
+++ b/core/jni/com_android_internal_os_Zygote.h
@@ -20,6 +20,14 @@
 #define LOG_TAG "Zygote"
 #define ATRACE_TAG ATRACE_TAG_DALVIK
 
+/*
+ * All functions that lead to ForkCommon must be marked with the
+ * no_stack_protector attributed.  Because ForkCommon changes the stack
+ * protector cookie, all of the guard checks on the frames above ForkCommon
+ * would fail when they are popped.
+ */
+#define NO_STACK_PROTECTOR __attribute__((no_stack_protector))
+
 #include <jni.h>
 #include <vector>
 #include <android-base/stringprintf.h>
diff --git a/core/jni/com_android_internal_os_ZygoteCommandBuffer.cpp b/core/jni/com_android_internal_os_ZygoteCommandBuffer.cpp
index add645de..2b5b8f7 100644
--- a/core/jni/com_android_internal_os_ZygoteCommandBuffer.cpp
+++ b/core/jni/com_android_internal_os_ZygoteCommandBuffer.cpp
@@ -377,6 +377,7 @@
 // We only process fork commands if the peer uid matches expected_uid.
 // For every fork command after the first, we check that the requested uid is at
 // least minUid.
+NO_STACK_PROTECTOR
 jboolean com_android_internal_os_ZygoteCommandBuffer_nativeForkRepeatedly(
             JNIEnv* env,
             jclass,
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index d2c4b64..02453a4 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1536,7 +1536,7 @@
         android:protectionLevel="normal"
         android:permissionFlags="removed"/>
 
-    <!-- @hide We need to keep this around for backwards compatibility -->
+    <!-- @SystemApi @hide We need to keep this around for backwards compatibility -->
     <permission android:name="android.permission.WRITE_SMS"
         android:protectionLevel="normal"
         android:permissionFlags="removed"/>
@@ -1614,7 +1614,7 @@
     <permission android:name="android.permission.RECEIVE_EMERGENCY_BROADCAST"
         android:protectionLevel="signature|privileged" />
 
-    <!-- Allows an application to monitor incoming Bluetooth MAP messages, to record
+    <!-- @SystemApi Allows an application to monitor incoming Bluetooth MAP messages, to record
          or perform processing on them. -->
     <!-- @hide -->
     <permission android:name="android.permission.RECEIVE_BLUETOOTH_MAP"
@@ -6325,10 +6325,6 @@
                  android:permission="android.permission.BIND_JOB_SERVICE" >
         </service>
 
-        <service android:name="com.android.server.timezone.TimeZoneUpdateIdler"
-                 android:permission="android.permission.BIND_JOB_SERVICE" >
-        </service>
-
         <service android:name="com.android.server.usage.UsageStatsIdleService"
                  android:permission="android.permission.BIND_JOB_SERVICE" >
         </service>
diff --git a/core/res/res/values-mcc440-mnc20/config.xml b/core/res/res/values-mcc440-mnc20/config.xml
index 62001d9..7a48342 100644
--- a/core/res/res/values-mcc440-mnc20/config.xml
+++ b/core/res/res/values-mcc440-mnc20/config.xml
@@ -23,6 +23,6 @@
 
     <!-- Configure mobile network MTU. Carrier specific value is set here.
     -->
-    <integer name="config_mobile_mtu">1422</integer>
+    <integer name="config_mobile_mtu">1358</integer>
 
 </resources>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 160376c..4ece840 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1644,49 +1644,6 @@
          suggestions to TimeDetector service. See also config_autoTimeSourcesPriority. -->
     <bool name="config_enableGnssTimeUpdateService">false</bool>
 
-    <!-- Enables the TimeZoneRuleManager service. This is the global switch for the updateable time
-         zone update mechanism. -->
-    <bool name="config_enableUpdateableTimeZoneRules">false</bool>
-
-    <!-- Enables APK-based time zone update triggering. Set this to false when updates are triggered
-         via external events and not by APK updates. For example, if an updater checks with a server
-         on a regular schedule.
-         [This is only used if config_enableUpdateableTimeZoneRules is true.] -->
-    <bool name="config_timeZoneRulesUpdateTrackingEnabled">false</bool>
-
-    <!-- The package of the time zone rules updater application. Expected to be the same
-         for all Android devices that support APK-based time zone rule updates.
-         A package-targeted com.android.intent.action.timezone.TRIGGER_RULES_UPDATE_CHECK intent
-         will be sent to the updater app if the system server detects an update to the updater or
-         data app packages.
-         The package referenced here must have the android.permission.UPDATE_TIME_ZONE_RULES
-         permission.
-         [This is only used if config_enableUpdateableTimeZoneRules and
-         config_timeZoneRulesUpdateTrackingEnabled are true.] -->
-    <string name="config_timeZoneRulesUpdaterPackage" translatable="false">com.android.timezone.updater</string>
-
-    <!-- The package of the time zone rules data application. Expected to be configured
-         by OEMs to reference their own priv-app APK package.
-         A package-targeted com.android.intent.action.timezone.TRIGGER_RULES_UPDATE_CHECK intent
-         will be sent to the updater app if the system server detects an update to the updater or
-         data app packages.
-         [This is only used if config_enableUpdateableTimeZoneRules and
-         config_timeZoneRulesUpdateTrackingEnabled are true.] -->
-    <string name="config_timeZoneRulesDataPackage" translatable="false"></string>
-
-    <!-- The allowed time in milliseconds between an update check intent being broadcast and the
-         response being considered overdue. Reliability triggers will not fire in this time.
-         [This is only used if config_enableUpdateableTimeZoneRules and
-         config_timeZoneRulesUpdateTrackingEnabled are true.] -->
-    <!-- 5 minutes -->
-    <integer name="config_timeZoneRulesCheckTimeMillisAllowed">300000</integer>
-
-    <!-- The number of times a time zone update check is allowed to fail before the system will stop
-         reacting to reliability triggers.
-         [This is only used if config_enableUpdateableTimeZoneRules and
-         config_timeZoneRulesUpdateTrackingEnabled are true.] -->
-    <integer name="config_timeZoneRulesCheckRetryCount">5</integer>
-
     <!-- Whether the geolocation time zone detection feature is enabled. Setting this to false means
          the feature cannot be used. Setting this to true means system server components can be
          tested and location time zone detection may be used if other configuration allows (see
@@ -5242,4 +5199,12 @@
 
     <!-- Whether this device should support taking app snapshots on closure -->
     <bool name="config_disableTaskSnapshots">false</bool>
+
+    <!-- List of system components which are allowed to receive ServiceState entries in an
+         un-sanitized form, even if the location toggle is off. This is intended ONLY for system
+         components, such as the telephony stack, which require access to the full ServiceState for
+         tasks such as network registration. -->
+    <string-array name="config_serviceStateLocationAllowedPackages">
+        <item>"com.android.phone"</item>
+    </string-array>
 </resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 5894bdc..89797e8 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -323,12 +323,6 @@
   <java-symbol type="bool" name="config_checkWallpaperAtBoot" />
   <java-symbol type="string" name="config_wallpaperManagerServiceName" />
   <java-symbol type="string" name="config_inputEventCompatProcessorOverrideClassName" />
-  <java-symbol type="bool" name="config_enableUpdateableTimeZoneRules" />
-  <java-symbol type="bool" name="config_timeZoneRulesUpdateTrackingEnabled" />
-  <java-symbol type="string" name="config_timeZoneRulesUpdaterPackage" />
-  <java-symbol type="string" name="config_timeZoneRulesDataPackage" />
-  <java-symbol type="integer" name="config_timeZoneRulesCheckTimeMillisAllowed" />
-  <java-symbol type="integer" name="config_timeZoneRulesCheckRetryCount" />
   <java-symbol type="bool" name="config_sendAudioBecomingNoisy" />
   <java-symbol type="bool" name="config_enableScreenshotChord" />
   <java-symbol type="bool" name="config_enableWifiDisplay" />
@@ -4469,5 +4463,6 @@
 
   <java-symbol type="bool" name="config_disableTaskSnapshots" />
 
+  <java-symbol type="array" name="config_serviceStateLocationAllowedPackages" />
   <java-symbol type="dimen" name="status_bar_height_default" />
 </resources>
diff --git a/core/res/res/xml/sms_short_codes.xml b/core/res/res/xml/sms_short_codes.xml
index dab4f1b..8519ddf 100644
--- a/core/res/res/xml/sms_short_codes.xml
+++ b/core/res/res/xml/sms_short_codes.xml
@@ -61,7 +61,7 @@
     <shortcode country="bg" pattern="\\d{4,5}" premium="18(?:16|423)|19(?:1[56]|35)" free="116\\d{3}|1988|1490" />
 
     <!-- Bahrain: 1-5 digits (standard system default, not country specific) -->
-    <shortcode country="bh" pattern="\\d{1,5}" free="81181" />
+    <shortcode country="bh" pattern="\\d{1,5}" free="81181|85999" />
 
     <!-- Brazil: 1-5 digits (standard system default, not country specific) -->
     <shortcode country="br" pattern="\\d{1,5}" free="6000[012]\\d|876|5500|9963|4141|8000" />
@@ -83,7 +83,7 @@
     <shortcode country="cn" premium="1066.*" free="1065.*" />
 
     <!-- Colombia: 1-6 digits (not confirmed) -->
-    <shortcode country="co" pattern="\\d{1,6}" free="890350|908160|892255|898002|898880|899960|899948|87739" />
+    <shortcode country="co" pattern="\\d{1,6}" free="890350|908160|892255|898002|898880|899960|899948|87739|85517" />
 
     <!-- Cyprus: 4-6 digits (not confirmed), known premium codes listed, plus EU -->
     <shortcode country="cy" pattern="\\d{4,6}" premium="7510" free="116\\d{3}" />
@@ -190,7 +190,7 @@
     <shortcode country="mk" pattern="\\d{1,6}" free="129005|122" />
 
     <!-- Mexico: 4-5 digits (not confirmed), known premium codes listed -->
-    <shortcode country="mx" pattern="\\d{4,5}" premium="53035|7766" free="26259|46645|50025|50052|5050|76551|88778|9963" />
+    <shortcode country="mx" pattern="\\d{4,5}" premium="53035|7766" free="26259|46645|50025|50052|5050|76551|88778|9963|91101" />
 
     <!-- Malaysia: 5 digits: http://www.skmm.gov.my/attachment/Consumer_Regulation/Mobile_Content_Services_FAQs.pdf -->
     <shortcode country="my" pattern="\\d{5}" premium="32298|33776" free="22099|28288|66668" />
diff --git a/core/tests/BroadcastRadioTests/OWNERS b/core/tests/BroadcastRadioTests/OWNERS
index 3e360e7..d2bdd64 100644
--- a/core/tests/BroadcastRadioTests/OWNERS
+++ b/core/tests/BroadcastRadioTests/OWNERS
@@ -1,3 +1,3 @@
-keunyoung@google.com
+xuweilin@google.com
 oscarazu@google.com
-twasilczyk@google.com
+keunyoung@google.com
diff --git a/data/keyboards/Vendor_054c_Product_0ce6.kl b/data/keyboards/Vendor_054c_Product_0ce6.kl
index 4d51a9e..411dd95 100644
--- a/data/keyboards/Vendor_054c_Product_0ce6.kl
+++ b/data/keyboards/Vendor_054c_Product_0ce6.kl
@@ -16,6 +16,8 @@
 # Sony Playstation(R) DualSense Controller
 #
 
+# Only use this key layout if we have HID_PLAYSTATION!
+requires_kernel_config CONFIG_HID_PLAYSTATION
 
 # Mapping according to https://developer.android.com/training/game-controllers/controller-input.html
 
diff --git a/data/keyboards/Vendor_054c_Product_0ce6_fallback.kl b/data/keyboards/Vendor_054c_Product_0ce6_fallback.kl
new file mode 100644
index 0000000..d1a364c
--- /dev/null
+++ b/data/keyboards/Vendor_054c_Product_0ce6_fallback.kl
@@ -0,0 +1,75 @@
+# Copyright (C) 2022 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+#
+# Sony Playstation(R) DualSense Controller
+#
+
+# Use this if HID_PLAYSTATION is not available
+
+# Mapping according to https://developer.android.com/training/game-controllers/controller-input.html
+
+# Square
+key 304   BUTTON_X
+# Cross
+key 305   BUTTON_A
+# Circle
+key 306   BUTTON_B
+# Triangle
+key 307   BUTTON_Y
+
+key 308   BUTTON_L1
+key 309   BUTTON_R1
+key 310   BUTTON_L2
+key 311   BUTTON_R2
+
+# L2 axis
+axis 0x03   LTRIGGER
+# R2 axis
+axis 0x04   RTRIGGER
+
+# Left Analog Stick
+axis 0x00   X
+axis 0x01   Y
+# Right Analog Stick
+axis 0x02   Z
+axis 0x05   RZ
+
+# Left stick click
+key 314   BUTTON_THUMBL
+# Right stick click
+key 315   BUTTON_THUMBR
+
+# Hat
+axis 0x10   HAT_X
+axis 0x11   HAT_Y
+
+# Mapping according to https://www.kernel.org/doc/Documentation/input/gamepad.txt
+# Share / "half-sun"
+key 312   BUTTON_SELECT
+# Options / three horizontal lines
+key 313   BUTTON_START
+# PS key
+key 316   BUTTON_MODE
+
+# Touchpad press
+key 317 BUTTON_1
+
+# SENSORs
+sensor 0x00 ACCELEROMETER X
+sensor 0x01 ACCELEROMETER Y
+sensor 0x02 ACCELEROMETER Z
+sensor 0x03 GYROSCOPE X
+sensor 0x04 GYROSCOPE Y
+sensor 0x05 GYROSCOPE Z
diff --git a/libs/hwui/Readback.cpp b/libs/hwui/Readback.cpp
index a743d30..ed87990 100644
--- a/libs/hwui/Readback.cpp
+++ b/libs/hwui/Readback.cpp
@@ -90,11 +90,36 @@
 
     SkRect srcRect = inSrcRect.toSkRect();
 
-    SkRect imageSrcRect =
-            SkRect::MakeLTRB(cropRect.left, cropRect.top, cropRect.right, cropRect.bottom);
-    if (imageSrcRect.isEmpty()) {
-        imageSrcRect = SkRect::MakeIWH(description.width, description.height);
+    SkRect imageSrcRect = SkRect::MakeIWH(description.width, description.height);
+    SkISize imageWH = SkISize::Make(description.width, description.height);
+    if (cropRect.left < cropRect.right && cropRect.top < cropRect.bottom) {
+        imageSrcRect =
+                SkRect::MakeLTRB(cropRect.left, cropRect.top, cropRect.right, cropRect.bottom);
+        imageWH = SkISize::Make(cropRect.right - cropRect.left, cropRect.bottom - cropRect.top);
+
+        // Chroma channels of YUV420 images are subsampled we may need to shrink the crop region by
+        // a whole texel on each side. Since skia still adds its own 0.5 inset, we apply an
+        // additional 0.5 inset. See GLConsumer::computeTransformMatrix for details.
+        float shrinkAmount = 0.0f;
+        switch (description.format) {
+            // Use HAL formats since some AHB formats are only available in vndk
+            case HAL_PIXEL_FORMAT_YCBCR_420_888:
+            case HAL_PIXEL_FORMAT_YV12:
+            case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
+                shrinkAmount = 0.5f;
+                break;
+            default:
+                break;
+        }
+
+        // Shrink the crop if it has more than 1-px and differs from the buffer size.
+        if (imageWH.width() > 1 && imageWH.width() < (int32_t)description.width)
+            imageSrcRect = imageSrcRect.makeInset(shrinkAmount, 0);
+
+        if (imageWH.height() > 1 && imageWH.height() < (int32_t)description.height)
+            imageSrcRect = imageSrcRect.makeInset(0, shrinkAmount);
     }
+
     ALOGV("imageSrcRect = " RECT_STRING, SK_RECT_ARGS(imageSrcRect));
 
     // Represents the "logical" width/height of the texture. That is, the dimensions of the buffer
@@ -153,7 +178,7 @@
      */
 
     SkMatrix m;
-    const SkRect imageDstRect = SkRect::MakeIWH(imageSrcRect.width(), imageSrcRect.height());
+    const SkRect imageDstRect = SkRect::Make(imageWH);
     const float px = imageDstRect.centerX();
     const float py = imageDstRect.centerY();
     if (windowTransform & NATIVE_WINDOW_TRANSFORM_FLIP_H) {
diff --git a/libs/protoutil/Android.bp b/libs/protoutil/Android.bp
index 132d71e..128be3c 100644
--- a/libs/protoutil/Android.bp
+++ b/libs/protoutil/Android.bp
@@ -55,6 +55,7 @@
 
     export_include_dirs: ["include"],
 
+    min_sdk_version: "30",
     apex_available: [
         "//apex_available:platform",
         "com.android.os.statsd",
@@ -81,5 +82,5 @@
 
     proto: {
         type: "full",
-    }
+    },
 }
diff --git a/media/java/android/media/AudioAttributes.java b/media/java/android/media/AudioAttributes.java
index b27a00c..c495535 100644
--- a/media/java/android/media/AudioAttributes.java
+++ b/media/java/android/media/AudioAttributes.java
@@ -1200,6 +1200,8 @@
         /**
          * Specifying if haptic should be muted or not when playing audio-haptic coupled data.
          * By default, haptic channels are disabled.
+         * <p>This will be ignored if the caller doesn't have the
+         * {@link android.Manifest.permission#VIBRATE} permission.
          * @param muted true to force muting haptic channels.
          * @return the same Builder instance.
          */
diff --git a/media/java/android/media/audiofx/HapticGenerator.java b/media/java/android/media/audiofx/HapticGenerator.java
index fe7f29e..d2523ef 100644
--- a/media/java/android/media/audiofx/HapticGenerator.java
+++ b/media/java/android/media/audiofx/HapticGenerator.java
@@ -91,7 +91,8 @@
     }
 
     /**
-     * Enable or disable the effect.
+     * Enable or disable the effect. The effect can only be enabled if the caller has the
+     * {@link android.Manifest.permission#VIBRATE} permission.
      *
      * @param enabled the requested enable state
      * @return {@link #SUCCESS} in case of success, {@link #ERROR_INVALID_OPERATION}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CsipDeviceManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CsipDeviceManager.java
index 89e10c4..fc70ba4 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CsipDeviceManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CsipDeviceManager.java
@@ -20,15 +20,19 @@
 import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothProfile;
 import android.bluetooth.BluetoothUuid;
+import android.os.Build;
 import android.os.ParcelUuid;
 import android.util.Log;
 
+import androidx.annotation.ChecksSdkIntAtLeast;
+
 import com.android.internal.annotations.VisibleForTesting;
 
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.stream.Collectors;
 
 /**
  * CsipDeviceManager manages the set of remote CSIP Bluetooth devices.
@@ -126,32 +130,84 @@
         }
     }
 
+    @ChecksSdkIntAtLeast(api = Build.VERSION_CODES.TIRAMISU)
+    private static boolean isAtLeastT() {
+        return Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU;
+    }
+
     // Group devices by groupId
     @VisibleForTesting
     void onGroupIdChanged(int groupId) {
-        int firstMatchedIndex = -1;
-        CachedBluetoothDevice mainDevice = null;
+        if (!isValidGroupId(groupId)) {
+            log("onGroupIdChanged: groupId is invalid");
+            return;
+        }
+        log("onGroupIdChanged: mCachedDevices list =" + mCachedDevices.toString());
+        final LocalBluetoothProfileManager profileManager = mBtManager.getProfileManager();
+        final CachedBluetoothDeviceManager deviceManager = mBtManager.getCachedDeviceManager();
+        final LeAudioProfile leAudioProfile = profileManager.getLeAudioProfile();
+        final BluetoothDevice mainBluetoothDevice = (leAudioProfile != null && isAtLeastT()) ?
+                leAudioProfile.getConnectedGroupLeadDevice(groupId) : null;
+        CachedBluetoothDevice newMainDevice =
+                mainBluetoothDevice != null ? deviceManager.findDevice(mainBluetoothDevice) : null;
+        if (newMainDevice != null) {
+            final CachedBluetoothDevice finalNewMainDevice = newMainDevice;
+            final List<CachedBluetoothDevice> memberDevices = mCachedDevices.stream()
+                    .filter(cachedDevice -> !cachedDevice.equals(finalNewMainDevice)
+                            && cachedDevice.getGroupId() == groupId)
+                    .collect(Collectors.toList());
+            if (memberDevices == null || memberDevices.isEmpty()) {
+                log("onGroupIdChanged: There is no member device in list.");
+                return;
+            }
+            log("onGroupIdChanged: removed from UI device =" + memberDevices
+                    + ", with groupId=" + groupId + " mainDevice= " + newMainDevice);
+            for (CachedBluetoothDevice memberDeviceItem : memberDevices) {
+                Set<CachedBluetoothDevice> memberSet = memberDeviceItem.getMemberDevice();
+                if (!memberSet.isEmpty()) {
+                    log("onGroupIdChanged: Transfer the member list into new main device.");
+                    for (CachedBluetoothDevice memberListItem : memberSet) {
+                        if (!memberListItem.equals(newMainDevice)) {
+                            newMainDevice.addMemberDevice(memberListItem);
+                        }
+                    }
+                    memberSet.clear();
+                }
 
-        for (int i = mCachedDevices.size() - 1; i >= 0; i--) {
-            final CachedBluetoothDevice cachedDevice = mCachedDevices.get(i);
-            if (cachedDevice.getGroupId() != groupId) {
-                continue;
+                newMainDevice.addMemberDevice(memberDeviceItem);
+                mCachedDevices.remove(memberDeviceItem);
+                mBtManager.getEventManager().dispatchDeviceRemoved(memberDeviceItem);
             }
 
-            if (firstMatchedIndex == -1) {
-                // Found the first one
-                firstMatchedIndex = i;
-                mainDevice = cachedDevice;
-                continue;
+            if (!mCachedDevices.contains(newMainDevice)) {
+                mCachedDevices.add(newMainDevice);
+                mBtManager.getEventManager().dispatchDeviceAdded(newMainDevice);
             }
+        } else {
+            log("onGroupIdChanged: There is no main device from the LE profile.");
+            int firstMatchedIndex = -1;
 
-            log("onGroupIdChanged: removed from UI device =" + cachedDevice
-                    + ", with groupId=" + groupId + " firstMatchedIndex=" + firstMatchedIndex);
+            for (int i = mCachedDevices.size() - 1; i >= 0; i--) {
+                final CachedBluetoothDevice cachedDevice = mCachedDevices.get(i);
+                if (cachedDevice.getGroupId() != groupId) {
+                    continue;
+                }
 
-            mainDevice.addMemberDevice(cachedDevice);
-            mCachedDevices.remove(i);
-            mBtManager.getEventManager().dispatchDeviceRemoved(cachedDevice);
-            break;
+                if (firstMatchedIndex == -1) {
+                    // Found the first one
+                    firstMatchedIndex = i;
+                    newMainDevice = cachedDevice;
+                    continue;
+                }
+
+                log("onGroupIdChanged: removed from UI device =" + cachedDevice
+                        + ", with groupId=" + groupId + " firstMatchedIndex=" + firstMatchedIndex);
+
+                newMainDevice.addMemberDevice(cachedDevice);
+                mCachedDevices.remove(i);
+                mBtManager.getEventManager().dispatchDeviceRemoved(cachedDevice);
+                break;
+            }
         }
     }
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LeAudioProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LeAudioProfile.java
index c323c4e..b6dcdc3 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LeAudioProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LeAudioProfile.java
@@ -21,6 +21,7 @@
 import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_ALLOWED;
 import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
 
+import android.annotation.Nullable;
 import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothClass;
 import android.bluetooth.BluetoothCodecConfig;
@@ -183,6 +184,37 @@
         return mBluetoothAdapter.getActiveDevices(BluetoothProfile.LE_AUDIO);
     }
 
+    /**
+     * Get Lead device for the group.
+     *
+     * Lead device is the device that can be used as an active device in the system.
+     * Active devices points to the Audio Device for the Le Audio group.
+     * This method returns the Lead devices for the connected LE Audio
+     * group and this device should be used in the setActiveDevice() method by other parts
+     * of the system, which wants to set to active a particular Le Audio group.
+     *
+     * Note: getActiveDevice() returns the Lead device for the currently active LE Audio group.
+     * Note: When Lead device gets disconnected while Le Audio group is active and has more devices
+     * in the group, then Lead device will not change. If Lead device gets disconnected, for the
+     * Le Audio group which is not active, a new Lead device will be chosen
+     *
+     * @param groupId The group id.
+     * @return group lead device.
+     *
+     * @hide
+     */
+    @RequiresApi(Build.VERSION_CODES.TIRAMISU)
+    public @Nullable BluetoothDevice getConnectedGroupLeadDevice(int groupId) {
+        if (DEBUG) {
+            Log.d(TAG,"getConnectedGroupLeadDevice");
+        }
+        if (mService == null) {
+            Log.e(TAG,"No service.");
+            return null;
+        }
+        return mService.getConnectedGroupLeadDevice(groupId);
+    }
+
     @Override
     public boolean isEnabled(BluetoothDevice device) {
         if (mService == null || device == null) {
diff --git a/packages/StatementService/OWNERS b/packages/StatementService/OWNERS
new file mode 100644
index 0000000..f0b4ce7
--- /dev/null
+++ b/packages/StatementService/OWNERS
@@ -0,0 +1,2 @@
+include /PACKAGE_MANAGER_OWNERS
+
diff --git a/packages/StatementService/src/com/android/statementservice/domain/DomainVerificationReceiverV1.kt b/packages/StatementService/src/com/android/statementservice/domain/DomainVerificationReceiverV1.kt
index 0ec8ed3..acb54f6 100644
--- a/packages/StatementService/src/com/android/statementservice/domain/DomainVerificationReceiverV1.kt
+++ b/packages/StatementService/src/com/android/statementservice/domain/DomainVerificationReceiverV1.kt
@@ -67,6 +67,10 @@
             }
         }
 
+        //clear sp before enqueue unique work since policy is REPLACE
+        val deContext = context.createDeviceProtectedStorageContext()
+        val editor = deContext?.getSharedPreferences(packageName, Context.MODE_PRIVATE)?.edit()
+        editor?.clear()?.apply()
         WorkManager.getInstance(context)
             .beginUniqueWork(
                 "$PACKAGE_WORK_PREFIX_V1$packageName",
diff --git a/packages/StatementService/src/com/android/statementservice/domain/worker/CollectV1Worker.kt b/packages/StatementService/src/com/android/statementservice/domain/worker/CollectV1Worker.kt
index 3a3aea9..36c81722 100644
--- a/packages/StatementService/src/com/android/statementservice/domain/worker/CollectV1Worker.kt
+++ b/packages/StatementService/src/com/android/statementservice/domain/worker/CollectV1Worker.kt
@@ -41,9 +41,7 @@
                     Data.Builder()
                         .putInt(VERIFICATION_ID_KEY, verificationId)
                         .apply {
-                            if (DEBUG) {
-                                putString(PACKAGE_NAME_KEY, packageName)
-                            }
+                            putString(PACKAGE_NAME_KEY, packageName)
                         }
                         .build()
                 )
@@ -52,6 +50,18 @@
 
     override suspend fun doWork() = coroutineScope {
         if (!AndroidUtils.isReceiverV1Enabled(appContext)) {
+            //clear sp and commit here
+            val inputData = params.inputData
+            val packageName = inputData.getString(PACKAGE_NAME_KEY)
+            val deContext = appContext.createDeviceProtectedStorageContext()
+            val sp = deContext?.getSharedPreferences(packageName, Context.MODE_PRIVATE)
+            val editor = sp?.edit()
+            editor?.clear()?.commit()
+            //delete sp file
+            val retOfDel = deContext?.deleteSharedPreferences(packageName)
+            if (DEBUG) {
+                Log.d(TAG, "delete sp for $packageName return $retOfDel")
+            }
             return@coroutineScope Result.success()
         }
 
@@ -59,7 +69,10 @@
         val verificationId = inputData.getInt(VERIFICATION_ID_KEY, -1)
         val successfulHosts = mutableListOf<String>()
         val failedHosts = mutableListOf<String>()
-        inputData.keyValueMap.entries.forEach { (key, _) ->
+        val packageName = inputData.getString(PACKAGE_NAME_KEY)
+        val deContext = appContext.createDeviceProtectedStorageContext()
+        val sp = deContext?.getSharedPreferences(packageName, Context.MODE_PRIVATE)
+        sp?.all?.entries?.forEach { (key, _) ->
             when {
                 key.startsWith(SingleV1RequestWorker.HOST_SUCCESS_PREFIX) ->
                     successfulHosts += key.removePrefix(SingleV1RequestWorker.HOST_SUCCESS_PREFIX)
@@ -69,7 +82,6 @@
         }
 
         if (DEBUG) {
-            val packageName = inputData.getString(PACKAGE_NAME_KEY)
             Log.d(
                 TAG, "Domain verification v1 request for $packageName: " +
                         "success = $successfulHosts, failed = $failedHosts"
@@ -84,6 +96,15 @@
 
         appContext.packageManager.verifyIntentFilter(verificationId, resultCode, failedHosts)
 
+        //clear sp and commit here
+        val editor = sp?.edit()
+        editor?.clear()?.commit()
+        //delete sp file
+        val retOfDel = deContext?.deleteSharedPreferences(packageName)
+        if (DEBUG) {
+            Log.d(TAG, "delete sp for $packageName return $retOfDel")
+        }
+
         Result.success()
     }
 }
diff --git a/packages/StatementService/src/com/android/statementservice/domain/worker/SingleV1RequestWorker.kt b/packages/StatementService/src/com/android/statementservice/domain/worker/SingleV1RequestWorker.kt
index cd8a182..7a198cb 100644
--- a/packages/StatementService/src/com/android/statementservice/domain/worker/SingleV1RequestWorker.kt
+++ b/packages/StatementService/src/com/android/statementservice/domain/worker/SingleV1RequestWorker.kt
@@ -71,16 +71,18 @@
 
         // Coerce failure results into success so that final collection task gets a chance to run
         when (result) {
-            is Result.Success -> Result.success(
-                Data.Builder()
-                    .putInt("$HOST_SUCCESS_PREFIX$host", status.value)
-                    .build()
-            )
-            is Result.Failure -> Result.success(
-                Data.Builder()
-                    .putInt("$HOST_FAILURE_PREFIX$host", status.value)
-                    .build()
-            )
+            is Result.Success -> {
+                val deContext = appContext.createDeviceProtectedStorageContext()
+                val sp = deContext?.getSharedPreferences(packageName, Context.MODE_PRIVATE)
+                sp?.edit()?.putInt("$HOST_SUCCESS_PREFIX$host", status.value)?.apply()
+                Result.success()
+            }
+            is Result.Failure -> {
+                val deContext = appContext.createDeviceProtectedStorageContext()
+                val sp = deContext?.getSharedPreferences(packageName, Context.MODE_PRIVATE)
+                sp?.edit()?.putInt("$HOST_FAILURE_PREFIX$host", status.value)?.apply()
+                Result.success()
+            }
             else -> result
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/MobileSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/MobileSignalController.java
index 9ae7ea2..4578a61 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/MobileSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/MobileSignalController.java
@@ -110,7 +110,7 @@
                 @Override
                 public void onMobileStatusChanged(boolean updateTelephony,
                         MobileStatus mobileStatus) {
-                    if (Log.isLoggable(mTag, Log.DEBUG)) {
+                    if (DEBUG) {
                         Log.d(mTag, "onMobileStatusChanged="
                                 + " updateTelephony=" + updateTelephony
                                 + " mobileStatus=" + mobileStatus.toString());
@@ -719,7 +719,7 @@
      * This will call listeners if necessary.
      */
     private void updateTelephony() {
-        if (Log.isLoggable(mTag, Log.DEBUG)) {
+        if (DEBUG) {
             Log.d(mTag, "updateTelephonySignalStrength: hasService="
                     + mCurrentState.isInService()
                     + " ss=" + mCurrentState.signalStrength
diff --git a/services/accessibility/OWNERS b/services/accessibility/OWNERS
index a31cfae..2b9f179 100644
--- a/services/accessibility/OWNERS
+++ b/services/accessibility/OWNERS
@@ -1,4 +1,4 @@
-svetoslavganov@google.com
 pweaver@google.com
-rhedjao@google.com
+sallyyuen@google.com
 ryanlwlin@google.com
+fuego@google.com
diff --git a/services/core/Android.bp b/services/core/Android.bp
index e4a0097..797df5a4 100644
--- a/services/core/Android.bp
+++ b/services/core/Android.bp
@@ -132,8 +132,6 @@
     ],
 
     static_libs: [
-        "time_zone_distro",
-        "time_zone_distro_installer",
         "android.hardware.authsecret-V1.0-java",
         "android.hardware.boot-V1.0-java",
         "android.hardware.boot-V1.1-java",
diff --git a/services/core/java/com/android/server/RuntimeService.java b/services/core/java/com/android/server/RuntimeService.java
index f4249f8..a04d5e7 100644
--- a/services/core/java/com/android/server/RuntimeService.java
+++ b/services/core/java/com/android/server/RuntimeService.java
@@ -20,21 +20,13 @@
 import android.os.Binder;
 import android.service.runtime.DebugEntryProto;
 import android.service.runtime.RuntimeServiceInfoProto;
-import android.util.Slog;
 import android.util.proto.ProtoOutputStream;
 
 import com.android.i18n.timezone.DebugInfo;
 import com.android.i18n.timezone.I18nModuleDebug;
-import com.android.i18n.timezone.TimeZoneDataFiles;
 import com.android.internal.util.DumpUtils;
-import com.android.timezone.distro.DistroException;
-import com.android.timezone.distro.DistroVersion;
-import com.android.timezone.distro.FileUtils;
-import com.android.timezone.distro.TimeZoneDistro;
 
-import java.io.File;
 import java.io.FileDescriptor;
-import java.io.IOException;
 import java.io.PrintWriter;
 
 /**
@@ -61,7 +53,6 @@
         ProtoOutputStream proto = null;
 
         DebugInfo i18nLibraryDebugInfo = I18nModuleDebug.getDebugInfo();
-        addTimeZoneApkDebugInfo(i18nLibraryDebugInfo);
 
         if (protoFormat) {
             proto = new ProtoOutputStream(fd);
@@ -86,20 +77,6 @@
     }
 
     /**
-     * Add information to {@link DebugInfo} about the time zone data supplied by the
-     * "Time zone updates via APK" feature.
-     */
-    private static void addTimeZoneApkDebugInfo(DebugInfo coreLibraryDebugInfo) {
-        // Add /data tz data set using the DistroVersion class (which libcore cannot use).
-        // This update mechanism will be removed after the time zone APEX is launched so this
-        // untidiness will disappear with it.
-        String debugKeyPrefix = "core_library.timezone.source.data_";
-        String versionFileName = TimeZoneDataFiles.getDataTimeZoneFile(
-                TimeZoneDistro.DISTRO_VERSION_FILE_NAME);
-        addDistroVersionDebugInfo(versionFileName, debugKeyPrefix, coreLibraryDebugInfo);
-    }
-
-    /**
      * Prints {@code coreLibraryDebugInfo} to {@code pw}.
      *
      * <p>If you change this method, make sure to modify
@@ -131,42 +108,4 @@
             protoStream.end(entryToken);
         }
     }
-
-    /**
-     * Adds version information to {@code debugInfo} from the distro_version file that may exist
-     * at {@code distroVersionFileName}. If the file does not exist or cannot be read this is
-     * reported as debug information too.
-     */
-    private static void addDistroVersionDebugInfo(String distroVersionFileName,
-            String debugKeyPrefix, DebugInfo debugInfo) {
-        File file = new File(distroVersionFileName);
-        String statusKey = debugKeyPrefix + "status";
-        if (file.exists()) {
-            try {
-                byte[] versionBytes =
-                        FileUtils.readBytes(file, DistroVersion.DISTRO_VERSION_FILE_LENGTH);
-                DistroVersion distroVersion = DistroVersion.fromBytes(versionBytes);
-                String formatVersionString = distroVersion.formatMajorVersion + "."
-                        + distroVersion.formatMinorVersion;
-                debugInfo.addStringEntry(statusKey, "OK")
-                        .addStringEntry(debugKeyPrefix + "formatVersion", formatVersionString)
-                        .addStringEntry(debugKeyPrefix + "rulesVersion",
-                                distroVersion.rulesVersion)
-                        .addStringEntry(debugKeyPrefix + "revision",
-                                distroVersion.revision);
-            } catch (IOException | DistroException e) {
-                debugInfo.addStringEntry(statusKey, "ERROR");
-                debugInfo.addStringEntry(debugKeyPrefix + "exception_class",
-                        e.getClass().getName());
-                debugInfo.addStringEntry(debugKeyPrefix + "exception_msg", e.getMessage());
-                logMessage("Error reading " + file, e);
-            }
-        } else {
-            debugInfo.addStringEntry(statusKey, "NOT_FOUND");
-        }
-    }
-
-    private static void logMessage(String msg, Throwable t) {
-        Slog.v(TAG, msg, t);
-    }
 }
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index 7cbe218..16c4880 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -125,6 +125,7 @@
 import android.util.ArraySet;
 import android.util.AtomicFile;
 import android.util.DataUnit;
+import android.util.EventLog;
 import android.util.Log;
 import android.util.Pair;
 import android.util.Slog;
@@ -354,6 +355,8 @@
     private static final float DEFAULT_LOW_BATTERY_LEVEL = 20F;
     // Decide whether charging is required to turn on the feature
     private static final boolean DEFAULT_CHARGING_REQUIRED = true;
+    // Minimum GC interval sleep time in ms
+    private static final int DEFAULT_MIN_GC_SLEEPTIME = 10000;
 
     private volatile int mLifetimePercentThreshold;
     private volatile int mMinSegmentsThreshold;
@@ -361,6 +364,7 @@
     private volatile float mSegmentReclaimWeight;
     private volatile float mLowBatteryLevel;
     private volatile boolean mChargingRequired;
+    private volatile int mMinGCSleepTime;
     private volatile boolean mNeedGC;
 
     private volatile boolean mPassedLifetimeThresh;
@@ -2611,6 +2615,8 @@
                 "low_battery_level", DEFAULT_LOW_BATTERY_LEVEL);
             mChargingRequired = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_STORAGE_NATIVE_BOOT,
                 "charging_required", DEFAULT_CHARGING_REQUIRED);
+            mMinGCSleepTime = DeviceConfig.getInt(DeviceConfig.NAMESPACE_STORAGE_NATIVE_BOOT,
+                "min_gc_sleeptime", DEFAULT_MIN_GC_SLEEPTIME);
 
             // If we use the smart idle maintenance, we need to turn off GC in the traditional idle
             // maintenance to avoid the conflict
@@ -2728,6 +2734,14 @@
         enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
 
         try {
+            int latestWrite = mVold.getWriteAmount();
+            if (latestWrite == -1) {
+                Slog.w(TAG, "Failed to get storage write record");
+                return;
+            }
+
+            updateStorageWriteRecords(latestWrite);
+
             // Block based checkpoint process runs fstrim. So, if checkpoint is in progress
             // (first boot after OTA), We skip the smart idle maintenance
             if (!needsCheckpoint() || !supportsBlockCheckpoint()) {
@@ -2735,13 +2749,6 @@
                     return;
                 }
 
-                int latestWrite = mVold.getWriteAmount();
-                if (latestWrite == -1) {
-                    Slog.w(TAG, "Failed to get storage write record");
-                    return;
-                }
-
-                updateStorageWriteRecords(latestWrite);
                 int avgWriteAmount = getAverageWriteAmount();
 
                 Slog.i(TAG, "Set smart idle maintenance: " + "latest write amount: " +
@@ -2749,9 +2756,11 @@
                             ", min segment threshold: " + mMinSegmentsThreshold +
                             ", dirty reclaim rate: " + mDirtyReclaimRate +
                             ", segment reclaim weight: " + mSegmentReclaimWeight +
-                            ", period: " + sSmartIdleMaintPeriod);
+                            ", period(min): " + sSmartIdleMaintPeriod +
+                            ", min gc sleep time(ms): " + mMinGCSleepTime);
                 mVold.setGCUrgentPace(avgWriteAmount, mMinSegmentsThreshold, mDirtyReclaimRate,
-                                      mSegmentReclaimWeight, sSmartIdleMaintPeriod);
+                                      mSegmentReclaimWeight, sSmartIdleMaintPeriod,
+                                      mMinGCSleepTime);
             } else {
                 Slog.i(TAG, "Skipping smart idle maintenance - block based checkpoint in progress");
             }
@@ -3274,11 +3283,21 @@
                     mInstaller.tryMountDataMirror(volumeUuid);
                 }
             }
-        } catch (RemoteException | Installer.InstallerException e) {
+        } catch (Exception e) {
+            EventLog.writeEvent(0x534e4554, "224585613", -1, "");
             Slog.wtf(TAG, e);
             // Make sure to re-throw this exception; we must not ignore failure
             // to prepare the user storage as it could indicate that encryption
             // wasn't successfully set up.
+            //
+            // Very unfortunately, these errors need to be ignored for broken
+            // users that already existed on-disk from older Android versions.
+            UserManagerInternal umInternal = LocalServices.getService(UserManagerInternal.class);
+            if (umInternal.shouldIgnorePrepareStorageErrors(userId)) {
+                Slog.wtf(TAG, "ignoring error preparing storage for existing user " + userId
+                        + "; device may be insecure!");
+                return;
+            }
             throw new RuntimeException(e);
         }
     }
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index 724d17b..481b53c 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -3065,42 +3065,88 @@
             Binder.restoreCallingIdentity(ident);
         }
 
+        // Send the broadcast exactly once to all possible disjoint sets of apps.
+        // If the location master switch is on, broadcast the ServiceState 4 times:
+        // - Full ServiceState sent to apps with ACCESS_FINE_LOCATION and READ_PHONE_STATE
+        // - Full ServiceState sent to apps with ACCESS_FINE_LOCATION and
+        //   READ_PRIVILEGED_PHONE_STATE but not READ_PHONE_STATE
+        // - Sanitized ServiceState sent to apps with READ_PHONE_STATE but not ACCESS_FINE_LOCATION
+        // - Sanitized ServiceState sent to apps with READ_PRIVILEGED_PHONE_STATE but neither
+        //   READ_PHONE_STATE nor ACCESS_FINE_LOCATION
+        // If the location master switch is off, broadcast the ServiceState multiple times:
+        // - Full ServiceState sent to all apps permitted to bypass the location master switch if
+        //   they have either READ_PHONE_STATE or READ_PRIVILEGED_PHONE_STATE
+        // - Sanitized ServiceState sent to all other apps with READ_PHONE_STATE
+        // - Sanitized ServiceState sent to all other apps with READ_PRIVILEGED_PHONE_STATE but not
+        //   READ_PHONE_STATE
+        if (Binder.withCleanCallingIdentity(() ->
+                LocationAccessPolicy.isLocationModeEnabled(mContext, mContext.getUserId()))) {
+            Intent fullIntent = createServiceStateIntent(state, subId, phoneId, false);
+            mContext.createContextAsUser(UserHandle.ALL, 0).sendBroadcastMultiplePermissions(
+                    fullIntent,
+                    new String[]{Manifest.permission.READ_PHONE_STATE,
+                            Manifest.permission.ACCESS_FINE_LOCATION});
+            mContext.createContextAsUser(UserHandle.ALL, 0).sendBroadcastMultiplePermissions(
+                    fullIntent,
+                    new String[]{Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
+                            Manifest.permission.ACCESS_FINE_LOCATION},
+                    new String[]{Manifest.permission.READ_PHONE_STATE});
+
+            Intent sanitizedIntent = createServiceStateIntent(state, subId, phoneId, true);
+            mContext.createContextAsUser(UserHandle.ALL, 0).sendBroadcastMultiplePermissions(
+                    sanitizedIntent,
+                    new String[]{Manifest.permission.READ_PHONE_STATE},
+                    new String[]{Manifest.permission.ACCESS_FINE_LOCATION});
+            mContext.createContextAsUser(UserHandle.ALL, 0).sendBroadcastMultiplePermissions(
+                    sanitizedIntent,
+                    new String[]{Manifest.permission.READ_PRIVILEGED_PHONE_STATE},
+                    new String[]{Manifest.permission.READ_PHONE_STATE,
+                            Manifest.permission.ACCESS_FINE_LOCATION});
+        } else {
+            String[] locationBypassPackages = Binder.withCleanCallingIdentity(() ->
+                    LocationAccessPolicy.getLocationBypassPackages(mContext));
+            for (String locationBypassPackage : locationBypassPackages) {
+                Intent fullIntent = createServiceStateIntent(state, subId, phoneId, false);
+                fullIntent.setPackage(locationBypassPackage);
+                mContext.createContextAsUser(UserHandle.ALL, 0).sendBroadcastMultiplePermissions(
+                        fullIntent,
+                        new String[]{Manifest.permission.READ_PHONE_STATE});
+                mContext.createContextAsUser(UserHandle.ALL, 0).sendBroadcastMultiplePermissions(
+                        fullIntent,
+                        new String[]{Manifest.permission.READ_PRIVILEGED_PHONE_STATE},
+                        new String[]{Manifest.permission.READ_PHONE_STATE});
+            }
+
+            Intent sanitizedIntent = createServiceStateIntent(state, subId, phoneId, true);
+            mContext.createContextAsUser(UserHandle.ALL, 0).sendBroadcastMultiplePermissions(
+                    sanitizedIntent,
+                    new String[]{Manifest.permission.READ_PHONE_STATE},
+                    new String[]{/* no excluded permissions */},
+                    locationBypassPackages);
+            mContext.createContextAsUser(UserHandle.ALL, 0).sendBroadcastMultiplePermissions(
+                    sanitizedIntent,
+                    new String[]{Manifest.permission.READ_PRIVILEGED_PHONE_STATE},
+                    new String[]{Manifest.permission.READ_PHONE_STATE},
+                    locationBypassPackages);
+        }
+    }
+
+    private Intent createServiceStateIntent(ServiceState state, int subId, int phoneId,
+            boolean sanitizeLocation) {
         Intent intent = new Intent(Intent.ACTION_SERVICE_STATE);
         intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
         Bundle data = new Bundle();
-        state.fillInNotifierBundle(data);
+        if (sanitizeLocation) {
+            state.createLocationInfoSanitizedCopy(true).fillInNotifierBundle(data);
+        } else {
+            state.fillInNotifierBundle(data);
+        }
         intent.putExtras(data);
-        // Pass the subscription along with the intent.
         intent.putExtra(PHONE_CONSTANTS_SUBSCRIPTION_KEY, subId);
         intent.putExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX, subId);
         intent.putExtra(PHONE_CONSTANTS_SLOT_KEY, phoneId);
         intent.putExtra(SubscriptionManager.EXTRA_SLOT_INDEX, phoneId);
-
-        // Send the broadcast twice -- once for all apps with READ_PHONE_STATE, then again
-        // for all apps with READ_PRIVILEGED_PHONE_STATE but not READ_PHONE_STATE.
-        // Do this again twice, the first time for apps with ACCESS_FINE_LOCATION, then again with
-        // the location-sanitized service state for all apps without ACCESS_FINE_LOCATION.
-        // This ensures that any app holding either READ_PRIVILEGED_PHONE_STATE or READ_PHONE_STATE
-        // get this broadcast exactly once, and we are not exposing location without permission.
-        mContext.createContextAsUser(UserHandle.ALL, 0).sendBroadcastMultiplePermissions(intent,
-                new String[] {Manifest.permission.READ_PHONE_STATE,
-                        Manifest.permission.ACCESS_FINE_LOCATION});
-        mContext.createContextAsUser(UserHandle.ALL, 0).sendBroadcastMultiplePermissions(intent,
-                new String[] {Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
-                        Manifest.permission.ACCESS_FINE_LOCATION},
-                new String[] {Manifest.permission.READ_PHONE_STATE});
-
-        // Replace bundle with location-sanitized ServiceState
-        data = new Bundle();
-        state.createLocationInfoSanitizedCopy(true).fillInNotifierBundle(data);
-        intent.putExtras(data);
-        mContext.createContextAsUser(UserHandle.ALL, 0).sendBroadcastMultiplePermissions(intent,
-                new String[] {Manifest.permission.READ_PHONE_STATE},
-                new String[] {Manifest.permission.ACCESS_FINE_LOCATION});
-        mContext.createContextAsUser(UserHandle.ALL, 0).sendBroadcastMultiplePermissions(intent,
-                new String[] {Manifest.permission.READ_PRIVILEGED_PHONE_STATE},
-                new String[] {Manifest.permission.READ_PHONE_STATE,
-                        Manifest.permission.ACCESS_FINE_LOCATION});
+        return intent;
     }
 
     private void broadcastSignalStrengthChanged(SignalStrength signalStrength, int phoneId,
diff --git a/services/core/java/com/android/server/VpnManagerService.java b/services/core/java/com/android/server/VpnManagerService.java
index d3ef6be..c9a420e 100644
--- a/services/core/java/com/android/server/VpnManagerService.java
+++ b/services/core/java/com/android/server/VpnManagerService.java
@@ -45,6 +45,7 @@
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.INetworkManagementService;
+import android.os.Looper;
 import android.os.ParcelFileDescriptor;
 import android.os.Process;
 import android.os.ServiceManager;
@@ -131,6 +132,12 @@
             return INetworkManagementService.Stub.asInterface(
                     ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE));
         }
+
+        /** Create a VPN. */
+        public Vpn createVpn(Looper looper, Context context, INetworkManagementService nms,
+                INetd netd, int userId) {
+            return new Vpn(looper, context, nms, netd, userId, new VpnProfileStore());
+        }
     }
 
     public VpnManagerService(Context context, Dependencies deps) {
@@ -688,6 +695,7 @@
 
         // Listen to package add and removal events for all users.
         intentFilter = new IntentFilter();
+        intentFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
         intentFilter.addAction(Intent.ACTION_PACKAGE_REPLACED);
         intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
         intentFilter.addDataScheme("package");
@@ -738,6 +746,10 @@
                 final boolean isReplacing = intent.getBooleanExtra(
                         Intent.EXTRA_REPLACING, false);
                 onPackageRemoved(packageName, uid, isReplacing);
+            } else if (Intent.ACTION_PACKAGE_ADDED.equals(action)) {
+                final boolean isReplacing = intent.getBooleanExtra(
+                        Intent.EXTRA_REPLACING, false);
+                onPackageAdded(packageName, uid, isReplacing);
             } else {
                 Log.wtf(TAG, "received unexpected intent: " + action);
             }
@@ -764,8 +776,7 @@
                 loge("Starting user already has a VPN");
                 return;
             }
-            userVpn = new Vpn(mHandler.getLooper(), mContext, mNMS, mNetd, userId,
-                    new VpnProfileStore());
+            userVpn = mDeps.createVpn(mHandler.getLooper(), mContext, mNMS, mNetd, userId);
             mVpns.put(userId, userVpn);
             if (mUserManager.getUserInfo(userId).isPrimary() && isLockdownVpnEnabled()) {
                 updateLockdownVpn();
@@ -851,15 +862,33 @@
         final int userId = UserHandle.getUserId(uid);
         synchronized (mVpns) {
             final Vpn vpn = mVpns.get(userId);
-            if (vpn == null) {
+            if (vpn == null || isReplacing) {
                 return;
             }
             // Legacy always-on VPN won't be affected since the package name is not set.
-            if (TextUtils.equals(vpn.getAlwaysOnPackage(), packageName) && !isReplacing) {
+            if (TextUtils.equals(vpn.getAlwaysOnPackage(), packageName)) {
                 log("Removing always-on VPN package " + packageName + " for user "
                         + userId);
                 vpn.setAlwaysOnPackage(null, false, null);
             }
+
+            vpn.refreshPlatformVpnAppExclusionList();
+        }
+    }
+
+    private void onPackageAdded(String packageName, int uid, boolean isReplacing) {
+        if (TextUtils.isEmpty(packageName) || uid < 0) {
+            Log.wtf(TAG, "Invalid package in onPackageAdded: " + packageName + " | " + uid);
+            return;
+        }
+
+        final int userId = UserHandle.getUserId(uid);
+        synchronized (mVpns) {
+            final Vpn vpn = mVpns.get(userId);
+
+            if (vpn != null && !isReplacing) {
+                vpn.refreshPlatformVpnAppExclusionList();
+            }
         }
     }
 
diff --git a/services/core/java/com/android/server/adb/AdbDebuggingManager.java b/services/core/java/com/android/server/adb/AdbDebuggingManager.java
index 297d28d..56990ed 100644
--- a/services/core/java/com/android/server/adb/AdbDebuggingManager.java
+++ b/services/core/java/com/android/server/adb/AdbDebuggingManager.java
@@ -19,7 +19,7 @@
 import static com.android.internal.util.dump.DumpUtils.writeStringIfNotNull;
 
 import android.annotation.NonNull;
-import android.annotation.TestApi;
+import android.annotation.Nullable;
 import android.app.ActivityManager;
 import android.app.Notification;
 import android.app.NotificationChannel;
@@ -102,11 +102,26 @@
 import java.util.concurrent.atomic.AtomicBoolean;
 
 /**
- * Provides communication to the Android Debug Bridge daemon to allow, deny, or clear public keysi
+ * Provides communication to the Android Debug Bridge daemon to allow, deny, or clear public keys
  * that are authorized to connect to the ADB service itself.
+ *
+ * <p>The AdbDebuggingManager controls two files:
+ * <ol>
+ *     <li>adb_keys
+ *     <li>adb_temp_keys.xml
+ * </ol>
+ *
+ * <p>The ADB Daemon (adbd) reads <em>only</em> the adb_keys file for authorization. Public keys
+ * from registered hosts are stored in adb_keys, one entry per line.
+ *
+ * <p>AdbDebuggingManager also keeps adb_temp_keys.xml, which is used for two things
+ * <ol>
+ *     <li>Removing unused keys from the adb_keys file
+ *     <li>Managing authorized WiFi access points for ADB over WiFi
+ * </ol>
  */
 public class AdbDebuggingManager {
-    private static final String TAG = "AdbDebuggingManager";
+    private static final String TAG = AdbDebuggingManager.class.getSimpleName();
     private static final boolean DEBUG = false;
     private static final boolean MDNS_DEBUG = false;
 
@@ -118,18 +133,20 @@
     // as a subsequent connection occurs within the allowed duration.
     private static final String ADB_TEMP_KEYS_FILE = "adb_temp_keys.xml";
     private static final int BUFFER_SIZE = 65536;
+    private static final Ticker SYSTEM_TICKER = () -> System.currentTimeMillis();
 
     private final Context mContext;
     private final ContentResolver mContentResolver;
-    private final Handler mHandler;
-    private AdbDebuggingThread mThread;
+    @VisibleForTesting final AdbDebuggingHandler mHandler;
+    @Nullable private AdbDebuggingThread mThread;
     private boolean mAdbUsbEnabled = false;
     private boolean mAdbWifiEnabled = false;
     private String mFingerprints;
     // A key can be used more than once (e.g. USB, wifi), so need to keep a refcount
-    private final Map<String, Integer> mConnectedKeys;
-    private String mConfirmComponent;
-    private final File mTestUserKeyFile;
+    private final Map<String, Integer> mConnectedKeys = new HashMap<>();
+    private final String mConfirmComponent;
+    @Nullable private final File mUserKeyFile;
+    @Nullable private final File mTempKeysFile;
 
     private static final String WIFI_PERSISTENT_CONFIG_PROPERTY =
             "persist.adb.tls_server.enable";
@@ -138,37 +155,44 @@
     private static final int PAIRING_CODE_LENGTH = 6;
     private PairingThread mPairingThread = null;
     // A list of keys connected via wifi
-    private final Set<String> mWifiConnectedKeys;
+    private final Set<String> mWifiConnectedKeys = new HashSet<>();
     // The current info of the adbwifi connection.
-    private AdbConnectionInfo mAdbConnectionInfo;
+    private AdbConnectionInfo mAdbConnectionInfo = new AdbConnectionInfo();
     // Polls for a tls port property when adb wifi is enabled
     private AdbConnectionPortPoller mConnectionPortPoller;
     private final PortListenerImpl mPortListener = new PortListenerImpl();
+    private final Ticker mTicker;
 
     public AdbDebuggingManager(Context context) {
-        mHandler = new AdbDebuggingHandler(FgThread.get().getLooper());
-        mContext = context;
-        mContentResolver = mContext.getContentResolver();
-        mTestUserKeyFile = null;
-        mConnectedKeys = new HashMap<String, Integer>();
-        mWifiConnectedKeys = new HashSet<String>();
-        mAdbConnectionInfo = new AdbConnectionInfo();
+        this(
+                context,
+                /* confirmComponent= */ null,
+                getAdbFile(ADB_KEYS_FILE),
+                getAdbFile(ADB_TEMP_KEYS_FILE),
+                /* adbDebuggingThread= */ null,
+                SYSTEM_TICKER);
     }
 
     /**
      * Constructor that accepts the component to be invoked to confirm if the user wants to allow
      * an adb connection from the key.
      */
-    @TestApi
-    protected AdbDebuggingManager(Context context, String confirmComponent, File testUserKeyFile) {
-        mHandler = new AdbDebuggingHandler(FgThread.get().getLooper());
+    @VisibleForTesting
+    AdbDebuggingManager(
+            Context context,
+            String confirmComponent,
+            File testUserKeyFile,
+            File tempKeysFile,
+            AdbDebuggingThread adbDebuggingThread,
+            Ticker ticker) {
         mContext = context;
         mContentResolver = mContext.getContentResolver();
         mConfirmComponent = confirmComponent;
-        mTestUserKeyFile = testUserKeyFile;
-        mConnectedKeys = new HashMap<String, Integer>();
-        mWifiConnectedKeys = new HashSet<String>();
-        mAdbConnectionInfo = new AdbConnectionInfo();
+        mUserKeyFile = testUserKeyFile;
+        mTempKeysFile = tempKeysFile;
+        mThread = adbDebuggingThread;
+        mTicker = ticker;
+        mHandler = new AdbDebuggingHandler(FgThread.get().getLooper(), mThread);
     }
 
     static void sendBroadcastWithDebugPermission(@NonNull Context context, @NonNull Intent intent,
@@ -189,8 +213,7 @@
         // consisting of only letters, digits, and hyphens, must begin and end
         // with a letter or digit, must not contain consecutive hyphens, and
         // must contain at least one letter.
-        @VisibleForTesting
-        static final String SERVICE_PROTOCOL = "adb-tls-pairing";
+        @VisibleForTesting static final String SERVICE_PROTOCOL = "adb-tls-pairing";
         private final String mServiceType = String.format("_%s._tcp.", SERVICE_PROTOCOL);
         private int mPort;
 
@@ -352,16 +375,24 @@
         }
     }
 
-    class AdbDebuggingThread extends Thread {
+    @VisibleForTesting
+    static class AdbDebuggingThread extends Thread {
         private boolean mStopped;
         private LocalSocket mSocket;
         private OutputStream mOutputStream;
         private InputStream mInputStream;
+        private Handler mHandler;
 
+        @VisibleForTesting
         AdbDebuggingThread() {
             super(TAG);
         }
 
+        @VisibleForTesting
+        void setHandler(Handler handler) {
+            mHandler = handler;
+        }
+
         @Override
         public void run() {
             if (DEBUG) Slog.d(TAG, "Entering thread");
@@ -536,7 +567,7 @@
         }
     }
 
-    class AdbConnectionInfo {
+    private static class AdbConnectionInfo {
         private String mBssid;
         private String mSsid;
         private int mPort;
@@ -743,11 +774,14 @@
         // Notification when adbd socket is disconnected.
         static final int MSG_ADBD_SOCKET_DISCONNECTED = 27;
 
+        // === Messages from other parts of the system
+        private static final int MESSAGE_KEY_FILES_UPDATED = 28;
+
         // === Messages we can send to adbd ===========
         static final String MSG_DISCONNECT_DEVICE = "DD";
         static final String MSG_DISABLE_ADBDWIFI = "DA";
 
-        private AdbKeyStore mAdbKeyStore;
+        @Nullable @VisibleForTesting AdbKeyStore mAdbKeyStore;
 
         // Usb, Wi-Fi transports can be enabled together or separately, so don't break the framework
         // connection unless all transport types are disconnected.
@@ -762,19 +796,19 @@
             }
         };
 
-        AdbDebuggingHandler(Looper looper) {
-            super(looper);
-        }
-
-        /**
-         * Constructor that accepts the AdbDebuggingThread to which responses should be sent
-         * and the AdbKeyStore to be used to store the temporary grants.
-         */
-        @TestApi
-        AdbDebuggingHandler(Looper looper, AdbDebuggingThread thread, AdbKeyStore adbKeyStore) {
+        /** Constructor that accepts the AdbDebuggingThread to which responses should be sent. */
+        @VisibleForTesting
+        AdbDebuggingHandler(Looper looper, AdbDebuggingThread thread) {
             super(looper);
             mThread = thread;
-            mAdbKeyStore = adbKeyStore;
+        }
+
+        /** Initialize the AdbKeyStore so tests can grab mAdbKeyStore immediately. */
+        @VisibleForTesting
+        void initKeyStore() {
+            if (mAdbKeyStore == null) {
+                mAdbKeyStore = new AdbKeyStore();
+            }
         }
 
         // Show when at least one device is connected.
@@ -805,6 +839,7 @@
 
             registerForAuthTimeChanges();
             mThread = new AdbDebuggingThread();
+            mThread.setHandler(mHandler);
             mThread.start();
 
             mAdbKeyStore.updateKeyStore();
@@ -825,8 +860,7 @@
 
             if (!mConnectedKeys.isEmpty()) {
                 for (Map.Entry<String, Integer> entry : mConnectedKeys.entrySet()) {
-                    mAdbKeyStore.setLastConnectionTime(entry.getKey(),
-                            System.currentTimeMillis());
+                    mAdbKeyStore.setLastConnectionTime(entry.getKey(), mTicker.currentTimeMillis());
                 }
                 sendPersistKeyStoreMessage();
                 mConnectedKeys.clear();
@@ -836,9 +870,7 @@
         }
 
         public void handleMessage(Message msg) {
-            if (mAdbKeyStore == null) {
-                mAdbKeyStore = new AdbKeyStore();
-            }
+            initKeyStore();
 
             switch (msg.what) {
                 case MESSAGE_ADB_ENABLED:
@@ -873,7 +905,7 @@
                             if (!mConnectedKeys.containsKey(key)) {
                                 mConnectedKeys.put(key, 1);
                             }
-                            mAdbKeyStore.setLastConnectionTime(key, System.currentTimeMillis());
+                            mAdbKeyStore.setLastConnectionTime(key, mTicker.currentTimeMillis());
                             sendPersistKeyStoreMessage();
                             scheduleJobToUpdateAdbKeyStore();
                         }
@@ -920,9 +952,7 @@
                     mConnectedKeys.clear();
                     // If the key store has not yet been instantiated then do so now; this avoids
                     // the unnecessary creation of the key store when adb is not enabled.
-                    if (mAdbKeyStore == null) {
-                        mAdbKeyStore = new AdbKeyStore();
-                    }
+                    initKeyStore();
                     mWifiConnectedKeys.clear();
                     mAdbKeyStore.deleteKeyStore();
                     cancelJobToUpdateAdbKeyStore();
@@ -937,7 +967,8 @@
                             alwaysAllow = true;
                             int refcount = mConnectedKeys.get(key) - 1;
                             if (refcount == 0) {
-                                mAdbKeyStore.setLastConnectionTime(key, System.currentTimeMillis());
+                                mAdbKeyStore.setLastConnectionTime(
+                                        key, mTicker.currentTimeMillis());
                                 sendPersistKeyStoreMessage();
                                 scheduleJobToUpdateAdbKeyStore();
                                 mConnectedKeys.remove(key);
@@ -963,7 +994,7 @@
                     if (!mConnectedKeys.isEmpty()) {
                         for (Map.Entry<String, Integer> entry : mConnectedKeys.entrySet()) {
                             mAdbKeyStore.setLastConnectionTime(entry.getKey(),
-                                    System.currentTimeMillis());
+                                    mTicker.currentTimeMillis());
                         }
                         sendPersistKeyStoreMessage();
                         scheduleJobToUpdateAdbKeyStore();
@@ -984,7 +1015,7 @@
                         } else {
                             mConnectedKeys.put(key, mConnectedKeys.get(key) + 1);
                         }
-                        mAdbKeyStore.setLastConnectionTime(key, System.currentTimeMillis());
+                        mAdbKeyStore.setLastConnectionTime(key, mTicker.currentTimeMillis());
                         sendPersistKeyStoreMessage();
                         scheduleJobToUpdateAdbKeyStore();
                         logAdbConnectionChanged(key, AdbProtoEnums.AUTOMATICALLY_ALLOWED, true);
@@ -1206,6 +1237,10 @@
                     }
                     break;
                 }
+                case MESSAGE_KEY_FILES_UPDATED: {
+                    mAdbKeyStore.reloadKeyMap();
+                    break;
+                }
             }
         }
 
@@ -1377,8 +1412,7 @@
                 AdbDebuggingManager.sendBroadcastWithDebugPermission(mContext, intent,
                         UserHandle.ALL);
                 // Add the key into the keystore
-                mAdbKeyStore.setLastConnectionTime(publicKey,
-                        System.currentTimeMillis());
+                mAdbKeyStore.setLastConnectionTime(publicKey, mTicker.currentTimeMillis());
                 sendPersistKeyStoreMessage();
                 scheduleJobToUpdateAdbKeyStore();
             }
@@ -1449,19 +1483,13 @@
         extras.add(new AbstractMap.SimpleEntry<String, String>("ssid", ssid));
         extras.add(new AbstractMap.SimpleEntry<String, String>("bssid", bssid));
         int currentUserId = ActivityManager.getCurrentUser();
-        UserInfo userInfo = UserManager.get(mContext).getUserInfo(currentUserId);
-        String componentString;
-        if (userInfo.isAdmin()) {
-            componentString = Resources.getSystem().getString(
-                    com.android.internal.R.string.config_customAdbWifiNetworkConfirmationComponent);
-        } else {
-            componentString = Resources.getSystem().getString(
-                    com.android.internal.R.string.config_customAdbWifiNetworkConfirmationComponent);
-        }
+        String componentString =
+                Resources.getSystem().getString(
+                        R.string.config_customAdbWifiNetworkConfirmationComponent);
         ComponentName componentName = ComponentName.unflattenFromString(componentString);
+        UserInfo userInfo = UserManager.get(mContext).getUserInfo(currentUserId);
         if (startConfirmationActivity(componentName, userInfo.getUserHandle(), extras)
-                || startConfirmationService(componentName, userInfo.getUserHandle(),
-                        extras)) {
+                || startConfirmationService(componentName, userInfo.getUserHandle(), extras)) {
             return;
         }
         Slog.e(TAG, "Unable to start customAdbWifiNetworkConfirmation[SecondaryUser]Component "
@@ -1543,7 +1571,7 @@
     /**
      * Returns a new File with the specified name in the adb directory.
      */
-    private File getAdbFile(String fileName) {
+    private static File getAdbFile(String fileName) {
         File dataDir = Environment.getDataDirectory();
         File adbDir = new File(dataDir, ADB_DIRECTORY);
 
@@ -1556,66 +1584,38 @@
     }
 
     File getAdbTempKeysFile() {
-        return getAdbFile(ADB_TEMP_KEYS_FILE);
+        return mTempKeysFile;
     }
 
     File getUserKeyFile() {
-        return mTestUserKeyFile == null ? getAdbFile(ADB_KEYS_FILE) : mTestUserKeyFile;
-    }
-
-    private void writeKey(String key) {
-        try {
-            File keyFile = getUserKeyFile();
-
-            if (keyFile == null) {
-                return;
-            }
-
-            FileOutputStream fo = new FileOutputStream(keyFile, true);
-            fo.write(key.getBytes());
-            fo.write('\n');
-            fo.close();
-
-            FileUtils.setPermissions(keyFile.toString(),
-                    FileUtils.S_IRUSR | FileUtils.S_IWUSR | FileUtils.S_IRGRP, -1, -1);
-        } catch (IOException ex) {
-            Slog.e(TAG, "Error writing key:" + ex);
-        }
+        return mUserKeyFile;
     }
 
     private void writeKeys(Iterable<String> keys) {
-        AtomicFile atomicKeyFile = null;
+        if (mUserKeyFile == null) {
+            return;
+        }
+
+        AtomicFile atomicKeyFile = new AtomicFile(mUserKeyFile);
+        // Note: Do not use a try-with-resources with the FileOutputStream, because AtomicFile
+        // requires that it's cleaned up with AtomicFile.failWrite();
         FileOutputStream fo = null;
         try {
-            File keyFile = getUserKeyFile();
-
-            if (keyFile == null) {
-                return;
-            }
-
-            atomicKeyFile = new AtomicFile(keyFile);
             fo = atomicKeyFile.startWrite();
             for (String key : keys) {
                 fo.write(key.getBytes());
                 fo.write('\n');
             }
             atomicKeyFile.finishWrite(fo);
-
-            FileUtils.setPermissions(keyFile.toString(),
-                    FileUtils.S_IRUSR | FileUtils.S_IWUSR | FileUtils.S_IRGRP, -1, -1);
         } catch (IOException ex) {
             Slog.e(TAG, "Error writing keys: " + ex);
-            if (atomicKeyFile != null) {
-                atomicKeyFile.failWrite(fo);
-            }
+            atomicKeyFile.failWrite(fo);
+            return;
         }
-    }
 
-    private void deleteKeyFile() {
-        File keyFile = getUserKeyFile();
-        if (keyFile != null) {
-            keyFile.delete();
-        }
+        FileUtils.setPermissions(
+                mUserKeyFile.toString(),
+                FileUtils.S_IRUSR | FileUtils.S_IWUSR | FileUtils.S_IRGRP, -1, -1);
     }
 
     /**
@@ -1745,6 +1745,13 @@
     }
 
     /**
+     * Notify that they key files were updated so the AdbKeyManager reloads the keys.
+     */
+    public void notifyKeyFilesUpdated() {
+        mHandler.sendEmptyMessage(AdbDebuggingHandler.MESSAGE_KEY_FILES_UPDATED);
+    }
+
+    /**
      * Sends a message to the handler to persist the keystore.
      */
     private void sendPersistKeyStoreMessage() {
@@ -1778,7 +1785,7 @@
 
         try {
             dump.write("keystore", AdbDebuggingManagerProto.KEYSTORE,
-                    FileUtils.readTextFile(getAdbTempKeysFile(), 0, null));
+                    FileUtils.readTextFile(mTempKeysFile, 0, null));
         } catch (IOException e) {
             Slog.i(TAG, "Cannot read keystore: ", e);
         }
@@ -1792,12 +1799,12 @@
      * ADB_ALLOWED_CONNECTION_TIME setting.
      */
     class AdbKeyStore {
-        private Map<String, Long> mKeyMap;
-        private Set<String> mSystemKeys;
-        private File mKeyFile;
         private AtomicFile mAtomicKeyFile;
 
-        private List<String> mTrustedNetworks;
+        private final Set<String> mSystemKeys;
+        private final Map<String, Long> mKeyMap = new HashMap<>();
+        private final List<String> mTrustedNetworks = new ArrayList<>();
+
         private static final int KEYSTORE_VERSION = 1;
         private static final int MAX_SUPPORTED_KEYSTORE_VERSION = 1;
         private static final String XML_KEYSTORE_START_TAG = "keyStore";
@@ -1819,26 +1826,22 @@
         public static final long NO_PREVIOUS_CONNECTION = 0;
 
         /**
-         * Constructor that uses the default location for the persistent adb keystore.
+         * Create an AdbKeyStore instance.
+         *
+         * <p>Upon creation, we parse {@link #mTempKeysFile} to determine authorized WiFi APs and
+         * retrieve the map of stored ADB keys and their last connected times. After that, we read
+         * the {@link #mUserKeyFile}, and any keys that exist in that file that do not exist in the
+         * map are added to the map (for backwards compatibility).
          */
         AdbKeyStore() {
-            init();
-        }
-
-        /**
-         * Constructor that uses the specified file as the location for the persistent adb keystore.
-         */
-        AdbKeyStore(File keyFile) {
-            mKeyFile = keyFile;
-            init();
-        }
-
-        private void init() {
             initKeyFile();
-            mKeyMap = getKeyMap();
-            mTrustedNetworks = getTrustedNetworks();
+            readTempKeysFile();
             mSystemKeys = getSystemKeysFromFile(SYSTEM_KEY_FILE);
-            addUserKeysToKeyStore();
+            addExistingUserKeysToKeyStore();
+        }
+
+        public void reloadKeyMap() {
+            readTempKeysFile();
         }
 
         public void addTrustedNetwork(String bssid) {
@@ -1877,7 +1880,6 @@
         public void removeKey(String key) {
             if (mKeyMap.containsKey(key)) {
                 mKeyMap.remove(key);
-                writeKeys(mKeyMap.keySet());
                 sendPersistKeyStoreMessage();
             }
         }
@@ -1886,12 +1888,9 @@
          * Initializes the key file that will be used to persist the adb grants.
          */
         private void initKeyFile() {
-            if (mKeyFile == null) {
-                mKeyFile = getAdbTempKeysFile();
-            }
-            // getAdbTempKeysFile can return null if the adb file cannot be obtained
-            if (mKeyFile != null) {
-                mAtomicKeyFile = new AtomicFile(mKeyFile);
+            // mTempKeysFile can be null if the adb file cannot be obtained
+            if (mTempKeysFile != null) {
+                mAtomicKeyFile = new AtomicFile(mTempKeysFile);
             }
         }
 
@@ -1932,201 +1931,108 @@
         }
 
         /**
-         * Returns the key map with the keys and last connection times from the key file.
+         * Update the key map and the trusted networks list with values parsed from the temp keys
+         * file.
          */
-        private Map<String, Long> getKeyMap() {
-            Map<String, Long> keyMap = new HashMap<String, Long>();
-            // if the AtomicFile could not be instantiated before attempt again; if it still fails
-            // return an empty key map.
+        private void readTempKeysFile() {
+            mKeyMap.clear();
+            mTrustedNetworks.clear();
             if (mAtomicKeyFile == null) {
                 initKeyFile();
                 if (mAtomicKeyFile == null) {
-                    Slog.e(TAG, "Unable to obtain the key file, " + mKeyFile + ", for reading");
-                    return keyMap;
+                    Slog.e(
+                            TAG,
+                            "Unable to obtain the key file, " + mTempKeysFile + ", for reading");
+                    return;
                 }
             }
             if (!mAtomicKeyFile.exists()) {
-                return keyMap;
+                return;
             }
             try (FileInputStream keyStream = mAtomicKeyFile.openRead()) {
-                TypedXmlPullParser parser = Xml.resolvePullParser(keyStream);
-                // Check for supported keystore version.
-                XmlUtils.beginDocument(parser, XML_KEYSTORE_START_TAG);
-                if (parser.next() != XmlPullParser.END_DOCUMENT) {
-                    String tagName = parser.getName();
-                    if (tagName == null || !XML_KEYSTORE_START_TAG.equals(tagName)) {
-                        Slog.e(TAG, "Expected " + XML_KEYSTORE_START_TAG + ", but got tag="
-                                + tagName);
-                        return keyMap;
-                    }
+                TypedXmlPullParser parser;
+                try {
+                    parser = Xml.resolvePullParser(keyStream);
+                    XmlUtils.beginDocument(parser, XML_KEYSTORE_START_TAG);
+
                     int keystoreVersion = parser.getAttributeInt(null, XML_ATTRIBUTE_VERSION);
                     if (keystoreVersion > MAX_SUPPORTED_KEYSTORE_VERSION) {
                         Slog.e(TAG, "Keystore version=" + keystoreVersion
                                 + " not supported (max_supported="
                                 + MAX_SUPPORTED_KEYSTORE_VERSION + ")");
-                        return keyMap;
+                        return;
                     }
+                } catch (XmlPullParserException e) {
+                    // This could be because the XML document doesn't start with
+                    // XML_KEYSTORE_START_TAG. Try again, instead just starting the document with
+                    // the adbKey tag (the old format).
+                    parser = Xml.resolvePullParser(keyStream);
                 }
-                while (parser.next() != XmlPullParser.END_DOCUMENT) {
-                    String tagName = parser.getName();
-                    if (tagName == null) {
-                        break;
-                    } else if (!tagName.equals(XML_TAG_ADB_KEY)) {
-                        XmlUtils.skipCurrentTag(parser);
-                        continue;
-                    }
-                    String key = parser.getAttributeValue(null, XML_ATTRIBUTE_KEY);
-                    long connectionTime;
-                    try {
-                        connectionTime = parser.getAttributeLong(null,
-                                XML_ATTRIBUTE_LAST_CONNECTION);
-                    } catch (XmlPullParserException e) {
-                        Slog.e(TAG,
-                                "Caught a NumberFormatException parsing the last connection time: "
-                                        + e);
-                        XmlUtils.skipCurrentTag(parser);
-                        continue;
-                    }
-                    keyMap.put(key, connectionTime);
-                }
+                readKeyStoreContents(parser);
             } catch (IOException e) {
                 Slog.e(TAG, "Caught an IOException parsing the XML key file: ", e);
             } catch (XmlPullParserException e) {
-                Slog.w(TAG, "Caught XmlPullParserException parsing the XML key file: ", e);
-                // The file could be written in a format prior to introducing keystore tag.
-                return getKeyMapBeforeKeystoreVersion();
+                Slog.e(TAG, "Caught XmlPullParserException parsing the XML key file: ", e);
             }
-            return keyMap;
         }
 
-
-        /**
-         * Returns the key map with the keys and last connection times from the key file.
-         * This implementation was prior to adding the XML_KEYSTORE_START_TAG.
-         */
-        private Map<String, Long> getKeyMapBeforeKeystoreVersion() {
-            Map<String, Long> keyMap = new HashMap<String, Long>();
-            // if the AtomicFile could not be instantiated before attempt again; if it still fails
-            // return an empty key map.
-            if (mAtomicKeyFile == null) {
-                initKeyFile();
-                if (mAtomicKeyFile == null) {
-                    Slog.e(TAG, "Unable to obtain the key file, " + mKeyFile + ", for reading");
-                    return keyMap;
+        private void readKeyStoreContents(TypedXmlPullParser parser)
+                throws XmlPullParserException, IOException {
+            // This parser is very forgiving. For backwards-compatibility, we simply iterate through
+            // all the tags in the file, skipping over anything that's not an <adbKey> tag or a
+            // <wifiAP> tag. Invalid tags (such as ones that don't have a valid "lastConnection"
+            // attribute) are simply ignored.
+            while ((parser.next()) != XmlPullParser.END_DOCUMENT) {
+                String tagName = parser.getName();
+                if (XML_TAG_ADB_KEY.equals(tagName)) {
+                    addAdbKeyToKeyMap(parser);
+                } else if (XML_TAG_WIFI_ACCESS_POINT.equals(tagName)) {
+                    addTrustedNetworkToTrustedNetworks(parser);
+                } else {
+                    Slog.w(TAG, "Ignoring tag '" + tagName + "'. Not recognized.");
                 }
+                XmlUtils.skipCurrentTag(parser);
             }
-            if (!mAtomicKeyFile.exists()) {
-                return keyMap;
-            }
-            try (FileInputStream keyStream = mAtomicKeyFile.openRead()) {
-                TypedXmlPullParser parser = Xml.resolvePullParser(keyStream);
-                XmlUtils.beginDocument(parser, XML_TAG_ADB_KEY);
-                while (parser.next() != XmlPullParser.END_DOCUMENT) {
-                    String tagName = parser.getName();
-                    if (tagName == null) {
-                        break;
-                    } else if (!tagName.equals(XML_TAG_ADB_KEY)) {
-                        XmlUtils.skipCurrentTag(parser);
-                        continue;
-                    }
-                    String key = parser.getAttributeValue(null, XML_ATTRIBUTE_KEY);
-                    long connectionTime;
-                    try {
-                        connectionTime = parser.getAttributeLong(null,
-                                XML_ATTRIBUTE_LAST_CONNECTION);
-                    } catch (XmlPullParserException e) {
-                        Slog.e(TAG,
-                                "Caught a NumberFormatException parsing the last connection time: "
-                                        + e);
-                        XmlUtils.skipCurrentTag(parser);
-                        continue;
-                    }
-                    keyMap.put(key, connectionTime);
-                }
-            } catch (IOException | XmlPullParserException e) {
-                Slog.e(TAG, "Caught an exception parsing the XML key file: ", e);
-            }
-            return keyMap;
         }
 
-        /**
-         * Returns the map of trusted networks from the keystore file.
-         *
-         * This was implemented in keystore version 1.
-         */
-        private List<String> getTrustedNetworks() {
-            List<String> trustedNetworks = new ArrayList<String>();
-            // if the AtomicFile could not be instantiated before attempt again; if it still fails
-            // return an empty key map.
-            if (mAtomicKeyFile == null) {
-                initKeyFile();
-                if (mAtomicKeyFile == null) {
-                    Slog.e(TAG, "Unable to obtain the key file, " + mKeyFile + ", for reading");
-                    return trustedNetworks;
-                }
+        private void addAdbKeyToKeyMap(TypedXmlPullParser parser) {
+            String key = parser.getAttributeValue(null, XML_ATTRIBUTE_KEY);
+            try {
+                long connectionTime =
+                        parser.getAttributeLong(null, XML_ATTRIBUTE_LAST_CONNECTION);
+                mKeyMap.put(key, connectionTime);
+            } catch (XmlPullParserException e) {
+                Slog.e(TAG, "Error reading adbKey attributes", e);
             }
-            if (!mAtomicKeyFile.exists()) {
-                return trustedNetworks;
-            }
-            try (FileInputStream keyStream = mAtomicKeyFile.openRead()) {
-                TypedXmlPullParser parser = Xml.resolvePullParser(keyStream);
-                // Check for supported keystore version.
-                XmlUtils.beginDocument(parser, XML_KEYSTORE_START_TAG);
-                if (parser.next() != XmlPullParser.END_DOCUMENT) {
-                    String tagName = parser.getName();
-                    if (tagName == null || !XML_KEYSTORE_START_TAG.equals(tagName)) {
-                        Slog.e(TAG, "Expected " + XML_KEYSTORE_START_TAG + ", but got tag="
-                                + tagName);
-                        return trustedNetworks;
-                    }
-                    int keystoreVersion = parser.getAttributeInt(null, XML_ATTRIBUTE_VERSION);
-                    if (keystoreVersion > MAX_SUPPORTED_KEYSTORE_VERSION) {
-                        Slog.e(TAG, "Keystore version=" + keystoreVersion
-                                + " not supported (max_supported="
-                                + MAX_SUPPORTED_KEYSTORE_VERSION);
-                        return trustedNetworks;
-                    }
-                }
-                while (parser.next() != XmlPullParser.END_DOCUMENT) {
-                    String tagName = parser.getName();
-                    if (tagName == null) {
-                        break;
-                    } else if (!tagName.equals(XML_TAG_WIFI_ACCESS_POINT)) {
-                        XmlUtils.skipCurrentTag(parser);
-                        continue;
-                    }
-                    String bssid = parser.getAttributeValue(null, XML_ATTRIBUTE_WIFI_BSSID);
-                    trustedNetworks.add(bssid);
-                }
-            } catch (IOException | XmlPullParserException | NumberFormatException e) {
-                Slog.e(TAG, "Caught an exception parsing the XML key file: ", e);
-            }
-            return trustedNetworks;
+        }
+
+        private void addTrustedNetworkToTrustedNetworks(TypedXmlPullParser parser) {
+            String bssid = parser.getAttributeValue(null, XML_ATTRIBUTE_WIFI_BSSID);
+            mTrustedNetworks.add(bssid);
         }
 
         /**
          * Updates the keystore with keys that were previously set to be always allowed before the
          * connection time of keys was tracked.
          */
-        private void addUserKeysToKeyStore() {
-            File userKeyFile = getUserKeyFile();
+        private void addExistingUserKeysToKeyStore() {
+            if (mUserKeyFile == null || !mUserKeyFile.exists()) {
+                return;
+            }
             boolean mapUpdated = false;
-            if (userKeyFile != null && userKeyFile.exists()) {
-                try (BufferedReader in = new BufferedReader(new FileReader(userKeyFile))) {
-                    long time = System.currentTimeMillis();
-                    String key;
-                    while ((key = in.readLine()) != null) {
-                        // if the keystore does not contain the key from the user key file then add
-                        // it to the Map with the current system time to prevent it from expiring
-                        // immediately if the user is actively using this key.
-                        if (!mKeyMap.containsKey(key)) {
-                            mKeyMap.put(key, time);
-                            mapUpdated = true;
-                        }
+            try (BufferedReader in = new BufferedReader(new FileReader(mUserKeyFile))) {
+                String key;
+                while ((key = in.readLine()) != null) {
+                    // if the keystore does not contain the key from the user key file then add
+                    // it to the Map with the current system time to prevent it from expiring
+                    // immediately if the user is actively using this key.
+                    if (!mKeyMap.containsKey(key)) {
+                        mKeyMap.put(key, mTicker.currentTimeMillis());
+                        mapUpdated = true;
                     }
-                } catch (IOException e) {
-                    Slog.e(TAG, "Caught an exception reading " + userKeyFile + ": " + e);
                 }
+            } catch (IOException e) {
+                Slog.e(TAG, "Caught an exception reading " + mUserKeyFile + ": " + e);
             }
             if (mapUpdated) {
                 sendPersistKeyStoreMessage();
@@ -2147,7 +2053,9 @@
             if (mAtomicKeyFile == null) {
                 initKeyFile();
                 if (mAtomicKeyFile == null) {
-                    Slog.e(TAG, "Unable to obtain the key file, " + mKeyFile + ", for writing");
+                    Slog.e(
+                            TAG,
+                            "Unable to obtain the key file, " + mTempKeysFile + ", for writing");
                     return;
                 }
             }
@@ -2178,17 +2086,21 @@
                 Slog.e(TAG, "Caught an exception writing the key map: ", e);
                 mAtomicKeyFile.failWrite(keyStream);
             }
+            writeKeys(mKeyMap.keySet());
         }
 
         private boolean filterOutOldKeys() {
-            boolean keysDeleted = false;
             long allowedTime = getAllowedConnectionTime();
-            long systemTime = System.currentTimeMillis();
+            if (allowedTime == 0) {
+                return false;
+            }
+            boolean keysDeleted = false;
+            long systemTime = mTicker.currentTimeMillis();
             Iterator<Map.Entry<String, Long>> keyMapIterator = mKeyMap.entrySet().iterator();
             while (keyMapIterator.hasNext()) {
                 Map.Entry<String, Long> keyEntry = keyMapIterator.next();
                 long connectionTime = keyEntry.getValue();
-                if (allowedTime != 0 && systemTime > (connectionTime + allowedTime)) {
+                if (systemTime > (connectionTime + allowedTime)) {
                     keyMapIterator.remove();
                     keysDeleted = true;
                 }
@@ -2212,7 +2124,7 @@
             if (allowedTime == 0) {
                 return minExpiration;
             }
-            long systemTime = System.currentTimeMillis();
+            long systemTime = mTicker.currentTimeMillis();
             Iterator<Map.Entry<String, Long>> keyMapIterator = mKeyMap.entrySet().iterator();
             while (keyMapIterator.hasNext()) {
                 Map.Entry<String, Long> keyEntry = keyMapIterator.next();
@@ -2233,7 +2145,9 @@
         public void deleteKeyStore() {
             mKeyMap.clear();
             mTrustedNetworks.clear();
-            deleteKeyFile();
+            if (mUserKeyFile != null) {
+                mUserKeyFile.delete();
+            }
             if (mAtomicKeyFile == null) {
                 return;
             }
@@ -2260,7 +2174,8 @@
          * is set to true the time will be set even if it is older than the previously written
          * connection time.
          */
-        public void setLastConnectionTime(String key, long connectionTime, boolean force) {
+        @VisibleForTesting
+        void setLastConnectionTime(String key, long connectionTime, boolean force) {
             // Do not set the connection time to a value that is earlier than what was previously
             // stored as the last connection time unless force is set.
             if (mKeyMap.containsKey(key) && mKeyMap.get(key) >= connectionTime && !force) {
@@ -2271,11 +2186,6 @@
             if (mSystemKeys.contains(key)) {
                 return;
             }
-            // if this is the first time the key is being added then write it to the key file as
-            // well.
-            if (!mKeyMap.containsKey(key)) {
-                writeKey(key);
-            }
             mKeyMap.put(key, connectionTime);
         }
 
@@ -2307,12 +2217,8 @@
             long allowedConnectionTime = getAllowedConnectionTime();
             // if the allowed connection time is 0 then revert to the previous behavior of always
             // allowing previously granted adb grants.
-            if (allowedConnectionTime == 0 || (System.currentTimeMillis() < (lastConnectionTime
-                    + allowedConnectionTime))) {
-                return true;
-            } else {
-                return false;
-            }
+            return allowedConnectionTime == 0
+                    || (mTicker.currentTimeMillis() < (lastConnectionTime + allowedConnectionTime));
         }
 
         /**
@@ -2324,4 +2230,15 @@
             return mTrustedNetworks.contains(bssid);
         }
     }
+
+    /**
+     * A Guava-like interface for getting the current system time.
+     *
+     * This allows us to swap a fake ticker in for testing to reduce "Thread.sleep()" calls and test
+     * for exact expected times instead of random ones.
+     */
+    @VisibleForTesting
+    interface Ticker {
+        long currentTimeMillis();
+    }
 }
diff --git a/services/core/java/com/android/server/adb/AdbService.java b/services/core/java/com/android/server/adb/AdbService.java
index 69f6d3a..991edf5 100644
--- a/services/core/java/com/android/server/adb/AdbService.java
+++ b/services/core/java/com/android/server/adb/AdbService.java
@@ -152,6 +152,14 @@
         }
 
         @Override
+        public void notifyKeyFilesUpdated() {
+            if (mDebuggingManager == null) {
+                return;
+            }
+            mDebuggingManager.notifyKeyFilesUpdated();
+        }
+
+        @Override
         public void startAdbdForTransport(byte transportType) {
             FgThread.getHandler().sendMessage(obtainMessage(
                     AdbService::setAdbdEnabledForTransport, AdbService.this, true, transportType));
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index e28170f..09b601c 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -2574,7 +2574,7 @@
     public void batterySendBroadcast(Intent intent) {
         synchronized (this) {
             broadcastIntentLocked(null, null, null, intent, null, null, 0, null, null, null, null,
-                    OP_NONE, null, false, false, -1, SYSTEM_UID, Binder.getCallingUid(),
+                    null, OP_NONE, null, false, false, -1, SYSTEM_UID, Binder.getCallingUid(),
                     Binder.getCallingPid(), UserHandle.USER_ALL);
         }
     }
@@ -4051,7 +4051,7 @@
         intent.putExtra(Intent.EXTRA_UID, uid);
         intent.putExtra(Intent.EXTRA_USER_HANDLE, UserHandle.getUserId(uid));
         broadcastIntentLocked(null, null, null, intent,
-                null, null, 0, null, null, null, null, OP_NONE,
+                null, null, 0, null, null, null, null, null, OP_NONE,
                 null, false, false, MY_PID, SYSTEM_UID, Binder.getCallingUid(),
                 Binder.getCallingPid(), UserHandle.getUserId(uid));
     }
@@ -7746,7 +7746,7 @@
                             | Intent.FLAG_RECEIVER_FOREGROUND);
                     intent.putExtra(Intent.EXTRA_USER_HANDLE, currentUserId);
                     broadcastIntentLocked(null, null, null, intent,
-                            null, null, 0, null, null, null, null, OP_NONE,
+                            null, null, 0, null, null, null, null, null, OP_NONE,
                             null, false, false, MY_PID, SYSTEM_UID, callingUid, callingPid,
                             currentUserId);
                     intent = new Intent(Intent.ACTION_USER_STARTING);
@@ -7758,8 +7758,8 @@
                                 public void performReceive(Intent intent, int resultCode,
                                         String data, Bundle extras, boolean ordered, boolean sticky,
                                         int sendingUser) {}
-                            }, 0, null, null, new String[] {INTERACT_ACROSS_USERS}, null, OP_NONE,
-                            null, true, false, MY_PID, SYSTEM_UID, callingUid, callingPid,
+                            }, 0, null, null, new String[] {INTERACT_ACROSS_USERS}, null, null,
+                            OP_NONE, null, true, false, MY_PID, SYSTEM_UID, callingUid, callingPid,
                             UserHandle.USER_ALL);
                 } catch (Throwable e) {
                     Slog.wtf(TAG, "Failed sending first user broadcasts", e);
@@ -12577,8 +12577,8 @@
                     Intent intent = allSticky.get(i);
                     BroadcastQueue queue = broadcastQueueForIntent(intent);
                     BroadcastRecord r = new BroadcastRecord(queue, intent, null,
-                            null, null, -1, -1, false, null, null, null, OP_NONE, null, receivers,
-                            null, 0, null, null, false, true, true, -1, false, null,
+                            null, null, -1, -1, false, null, null, null, null, OP_NONE, null,
+                            receivers, null, 0, null, null, false, true, true, -1, false, null,
                             false /* only PRE_BOOT_COMPLETED should be exempt, no stickies */);
                     queue.enqueueParallelBroadcastLocked(r);
                     queue.scheduleBroadcastsLocked();
@@ -12820,12 +12820,14 @@
             String callerPackage, String callerFeatureId, Intent intent, String resolvedType,
             IIntentReceiver resultTo, int resultCode, String resultData,
             Bundle resultExtras, String[] requiredPermissions, String[] excludedPermissions,
-            int appOp, Bundle bOptions, boolean ordered, boolean sticky, int callingPid,
+            String[] excludedPackages, int appOp, Bundle bOptions, boolean ordered,
+            boolean sticky, int callingPid,
             int callingUid, int realCallingUid, int realCallingPid, int userId) {
         return broadcastIntentLocked(callerApp, callerPackage, callerFeatureId, intent,
                 resolvedType, resultTo, resultCode, resultData, resultExtras, requiredPermissions,
-                excludedPermissions, appOp, bOptions, ordered, sticky, callingPid, callingUid,
-                realCallingUid, realCallingPid, userId, false /* allowBackgroundActivityStarts */,
+                excludedPermissions, excludedPackages, appOp, bOptions, ordered, sticky, callingPid,
+                callingUid, realCallingUid, realCallingPid, userId,
+                false /* allowBackgroundActivityStarts */,
                 null /* tokenNeededForBackgroundActivityStarts */, null /* broadcastAllowList */);
     }
 
@@ -12834,7 +12836,7 @@
             @Nullable String callerFeatureId, Intent intent, String resolvedType,
             IIntentReceiver resultTo, int resultCode, String resultData,
             Bundle resultExtras, String[] requiredPermissions,
-            String[] excludedPermissions, int appOp, Bundle bOptions,
+            String[] excludedPermissions, String[] excludedPackages, int appOp, Bundle bOptions,
             boolean ordered, boolean sticky, int callingPid, int callingUid,
             int realCallingUid, int realCallingPid, int userId,
             boolean allowBackgroundActivityStarts,
@@ -13411,10 +13413,10 @@
             final BroadcastQueue queue = broadcastQueueForIntent(intent);
             BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp, callerPackage,
                     callerFeatureId, callingPid, callingUid, callerInstantApp, resolvedType,
-                    requiredPermissions, excludedPermissions, appOp, brOptions, registeredReceivers,
-                    resultTo, resultCode, resultData, resultExtras, ordered, sticky, false, userId,
-                    allowBackgroundActivityStarts, backgroundActivityStartsToken,
-                    timeoutExempt);
+                    requiredPermissions, excludedPermissions, excludedPackages, appOp, brOptions,
+                    registeredReceivers, resultTo, resultCode, resultData, resultExtras, ordered,
+                    sticky, false, userId, allowBackgroundActivityStarts,
+                    backgroundActivityStartsToken, timeoutExempt);
             if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Enqueueing parallel broadcast " + r);
             final boolean replaced = replacePending
                     && (queue.replaceParallelBroadcastLocked(r) != null);
@@ -13509,7 +13511,7 @@
             BroadcastQueue queue = broadcastQueueForIntent(intent);
             BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp, callerPackage,
                     callerFeatureId, callingPid, callingUid, callerInstantApp, resolvedType,
-                    requiredPermissions, excludedPermissions, appOp, brOptions,
+                    requiredPermissions, excludedPermissions, excludedPackages, appOp, brOptions,
                     receivers, resultTo, resultCode, resultData, resultExtras,
                     ordered, sticky, false, userId, allowBackgroundActivityStarts,
                     backgroundActivityStartsToken, timeoutExempt);
@@ -13638,14 +13640,16 @@
             String[] requiredPermissions, int appOp, Bundle bOptions,
             boolean serialized, boolean sticky, int userId) {
         return broadcastIntentWithFeature(caller, null, intent, resolvedType, resultTo, resultCode,
-                resultData, resultExtras, requiredPermissions, null, appOp, bOptions, serialized,
-                sticky, userId);
+                resultData, resultExtras, requiredPermissions, null, null, appOp, bOptions,
+                serialized, sticky, userId);
     }
 
+    @Override
     public final int broadcastIntentWithFeature(IApplicationThread caller, String callingFeatureId,
             Intent intent, String resolvedType, IIntentReceiver resultTo,
             int resultCode, String resultData, Bundle resultExtras,
-            String[] requiredPermissions, String[] excludedPermissions, int appOp, Bundle bOptions,
+            String[] requiredPermissions, String[] excludedPermissions,
+            String[] excludedPackages, int appOp, Bundle bOptions,
             boolean serialized, boolean sticky, int userId) {
         enforceNotIsolatedCaller("broadcastIntent");
         synchronized(this) {
@@ -13660,8 +13664,8 @@
                 return broadcastIntentLocked(callerApp,
                         callerApp != null ? callerApp.info.packageName : null, callingFeatureId,
                         intent, resolvedType, resultTo, resultCode, resultData, resultExtras,
-                        requiredPermissions, excludedPermissions, appOp, bOptions, serialized,
-                        sticky, callingPid, callingUid, callingUid, callingPid, userId);
+                        requiredPermissions, excludedPermissions, excludedPackages, appOp, bOptions,
+                        serialized, sticky, callingPid, callingUid, callingUid, callingPid, userId);
             } finally {
                 Binder.restoreCallingIdentity(origId);
             }
@@ -13683,7 +13687,7 @@
             try {
                 return broadcastIntentLocked(null, packageName, featureId, intent, resolvedType,
                         resultTo, resultCode, resultData, resultExtras, requiredPermissions, null,
-                        OP_NONE, bOptions, serialized, sticky, -1, uid, realCallingUid,
+                        null, OP_NONE, bOptions, serialized, sticky, -1, uid, realCallingUid,
                         realCallingPid, userId, allowBackgroundActivityStarts,
                         backgroundActivityStartsToken,
                         null /* broadcastAllowList */);
@@ -14372,6 +14376,10 @@
                             app.processName, app.toShortString(), cpuLimit, app)) {
                     mHandler.post(() -> {
                         synchronized (ActivityManagerService.this) {
+                            if (app.getThread() == null
+                               || app.mState.getSetProcState() < ActivityManager.PROCESS_STATE_HOME) {
+                                   return;
+                            }
                             app.killLocked("excessive cpu " + cpuTimeUsed + " during "
                                     + uptimeSince + " dur=" + checkDur + " limit=" + cpuLimit,
                                     ApplicationExitInfo.REASON_EXCESSIVE_RESOURCE_USAGE,
@@ -14397,6 +14405,10 @@
                             app.processName, r.toString(), cpuLimit, app)) {
                     mHandler.post(() -> {
                         synchronized (ActivityManagerService.this) {
+                            if (app.getThread() == null
+                               || app.mState.getSetProcState() < ActivityManager.PROCESS_STATE_HOME) {
+                                   return;
+                            }
                             mPhantomProcessList.killPhantomProcessGroupLocked(app, r,
                                     ApplicationExitInfo.REASON_EXCESSIVE_RESOURCE_USAGE,
                                     ApplicationExitInfo.SUBREASON_EXCESSIVE_CPU,
@@ -15943,10 +15955,11 @@
                     return ActivityManagerService.this.broadcastIntentLocked(null /*callerApp*/,
                             null /*callerPackage*/, null /*callingFeatureId*/, intent,
                             null /*resolvedType*/, resultTo, 0 /*resultCode*/, null /*resultData*/,
-                            null /*resultExtras*/, requiredPermissions, null, AppOpsManager.OP_NONE,
-                            bOptions /*options*/, serialized, false /*sticky*/, callingPid,
-                            callingUid, callingUid, callingPid, userId,
-                            false /*allowBackgroundStarts*/,
+                            null /*resultExtras*/, requiredPermissions,
+                            null /*excludedPermissions*/, null /*excludedPackages*/,
+                            AppOpsManager.OP_NONE, bOptions /*options*/, serialized,
+                            false /*sticky*/, callingPid, callingUid, callingUid, callingPid,
+                            userId, false /*allowBackgroundStarts*/,
                             null /*tokenNeededForBackgroundActivityStarts*/, appIdAllowList);
                 } finally {
                     Binder.restoreCallingIdentity(origId);
@@ -16068,7 +16081,7 @@
                         | Intent.FLAG_RECEIVER_FOREGROUND
                         | Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS);
                 broadcastIntentLocked(null, null, null, intent, null, null, 0, null, null, null,
-                        null, OP_NONE, null, false, false, MY_PID, SYSTEM_UID,
+                        null, null, OP_NONE, null, false, false, MY_PID, SYSTEM_UID,
                         Binder.getCallingUid(), Binder.getCallingPid(), UserHandle.USER_ALL);
                 if ((changes & ActivityInfo.CONFIG_LOCALE) != 0) {
                     intent = new Intent(Intent.ACTION_LOCALE_CHANGED);
@@ -16083,8 +16096,8 @@
                             TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED,
                             PowerExemptionManager.REASON_LOCALE_CHANGED, "");
                     broadcastIntentLocked(null, null, null, intent, null, null, 0, null, null, null,
-                            null, OP_NONE, bOptions.toBundle(), false, false, MY_PID, SYSTEM_UID,
-                            Binder.getCallingUid(), Binder.getCallingPid(),
+                            null, null, OP_NONE, bOptions.toBundle(), false, false, MY_PID,
+                            SYSTEM_UID, Binder.getCallingUid(), Binder.getCallingPid(),
                             UserHandle.USER_ALL);
                 }
 
@@ -16099,8 +16112,9 @@
                     String[] permissions =
                             new String[] { android.Manifest.permission.INSTALL_PACKAGES };
                     broadcastIntentLocked(null, null, null, intent, null, null, 0, null, null,
-                            permissions, null, OP_NONE, null, false, false, MY_PID, SYSTEM_UID,
-                            Binder.getCallingUid(), Binder.getCallingPid(), UserHandle.USER_ALL);
+                            permissions, null, null, OP_NONE, null, false, false, MY_PID,
+                            SYSTEM_UID, Binder.getCallingUid(), Binder.getCallingPid(),
+                            UserHandle.USER_ALL);
                 }
             }
         }
@@ -16124,8 +16138,8 @@
                 }
 
                 broadcastIntentLocked(null, null, null, intent, null, null, 0, null, null, null,
-                        null, OP_NONE, null, false, false, -1, SYSTEM_UID, Binder.getCallingUid(),
-                        Binder.getCallingPid(), UserHandle.USER_ALL);
+                        null, null, OP_NONE, null, false, false, -1, SYSTEM_UID,
+                        Binder.getCallingUid(), Binder.getCallingPid(), UserHandle.USER_ALL);
             }
         }
 
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index ea28117..827c5c4 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -24,6 +24,7 @@
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
 import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
 import static android.view.Display.INVALID_DISPLAY;
+import static android.window.DisplayAreaOrganizer.FEATURE_UNDEFINED;
 
 import static com.android.internal.app.procstats.ProcessStats.ADJ_MEM_FACTOR_CRITICAL;
 import static com.android.internal.app.procstats.ProcessStats.ADJ_MEM_FACTOR_LOW;
@@ -170,6 +171,7 @@
     private String mAgent;  // Agent to attach on startup.
     private boolean mAttachAgentDuringBind;  // Whether agent should be attached late.
     private int mDisplayId;
+    private int mTaskDisplayAreaFeatureId;
     private int mWindowingMode;
     private int mActivityType;
     private int mTaskId;
@@ -353,6 +355,7 @@
         mStreaming = false;
         mUserId = defUser;
         mDisplayId = INVALID_DISPLAY;
+        mTaskDisplayAreaFeatureId = FEATURE_UNDEFINED;
         mWindowingMode = WINDOWING_MODE_UNDEFINED;
         mActivityType = ACTIVITY_TYPE_UNDEFINED;
         mTaskId = INVALID_TASK_ID;
@@ -408,6 +411,8 @@
                     mReceiverPermission = getNextArgRequired();
                 } else if (opt.equals("--display")) {
                     mDisplayId = Integer.parseInt(getNextArgRequired());
+                } else if (opt.equals("--task-display-area-feature-id")) {
+                    mTaskDisplayAreaFeatureId = Integer.parseInt(getNextArgRequired());
                 } else if (opt.equals("--windowingMode")) {
                     mWindowingMode = Integer.parseInt(getNextArgRequired());
                 } else if (opt.equals("--activityType")) {
@@ -535,6 +540,12 @@
                 options = ActivityOptions.makeBasic();
                 options.setLaunchDisplayId(mDisplayId);
             }
+            if (mTaskDisplayAreaFeatureId != FEATURE_UNDEFINED) {
+                if (options == null) {
+                    options = ActivityOptions.makeBasic();
+                }
+                options.setLaunchTaskDisplayAreaFeatureId(mTaskDisplayAreaFeatureId);
+            }
             if (mWindowingMode != WINDOWING_MODE_UNDEFINED) {
                 if (options == null) {
                     options = ActivityOptions.makeBasic();
@@ -773,8 +784,8 @@
         pw.flush();
         Bundle bundle = mBroadcastOptions == null ? null : mBroadcastOptions.toBundle();
         mInterface.broadcastIntentWithFeature(null, null, intent, null, receiver, 0, null, null,
-                requiredPermissions, null, android.app.AppOpsManager.OP_NONE, bundle, true, false,
-                mUserId);
+                requiredPermissions, null, null, android.app.AppOpsManager.OP_NONE, bundle, true,
+                false, mUserId);
         if (!mAsync) {
             receiver.waitForFinish();
         }
diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java
index 2da4107..6daf709 100644
--- a/services/core/java/com/android/server/am/BroadcastQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastQueue.java
@@ -67,6 +67,7 @@
 import android.util.TimeUtils;
 import android.util.proto.ProtoOutputStream;
 
+import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.FrameworkStatsLog;
 
 import java.io.FileDescriptor;
@@ -766,6 +767,22 @@
                 skip = true;
             }
         }
+
+        // Check that the receiver does *not* belong to any of the excluded packages
+        if (!skip && r.excludedPackages != null && r.excludedPackages.length > 0) {
+            if (ArrayUtils.contains(r.excludedPackages, filter.packageName)) {
+                Slog.w(TAG, "Skipping delivery of excluded package "
+                        + r.intent.toString()
+                        + " to " + filter.receiverList.app
+                        + " (pid=" + filter.receiverList.pid
+                        + ", uid=" + filter.receiverList.uid + ")"
+                        + " excludes package " + filter.packageName
+                        + " due to sender " + r.callerPackage
+                        + " (uid " + r.callingUid + ")");
+                skip = true;
+            }
+        }
+
         // If the broadcast also requires an app op check that as well.
         if (!skip && r.appOp != AppOpsManager.OP_NONE
                 && mService.getAppOpsManager().noteOpNoThrow(r.appOp,
@@ -1600,6 +1617,19 @@
             }
         }
 
+        // Check that the receiver does *not* belong to any of the excluded packages
+        if (!skip && r.excludedPackages != null && r.excludedPackages.length > 0) {
+            if (ArrayUtils.contains(r.excludedPackages, component.getPackageName())) {
+                Slog.w(TAG, "Skipping delivery of excluded package "
+                        + r.intent + " to "
+                        + component.flattenToShortString()
+                        + " excludes package " + component.getPackageName()
+                        + " due to sender " + r.callerPackage
+                        + " (uid " + r.callingUid + ")");
+                skip = true;
+            }
+        }
+
         if (!skip && info.activityInfo.applicationInfo.uid != Process.SYSTEM_UID &&
                 r.requiredPermissions != null && r.requiredPermissions.length > 0) {
             for (int i = 0; i < r.requiredPermissions.length; i++) {
diff --git a/services/core/java/com/android/server/am/BroadcastRecord.java b/services/core/java/com/android/server/am/BroadcastRecord.java
index 8015596..84a9482 100644
--- a/services/core/java/com/android/server/am/BroadcastRecord.java
+++ b/services/core/java/com/android/server/am/BroadcastRecord.java
@@ -63,6 +63,7 @@
     final String resolvedType; // the resolved data type
     final String[] requiredPermissions; // permissions the caller has required
     final String[] excludedPermissions; // permissions to exclude
+    final String[] excludedPackages; // packages to exclude
     final int appOp;        // an app op that is associated with this broadcast
     final BroadcastOptions options; // BroadcastOptions supplied by caller
     final List receivers;   // contains BroadcastFilter and ResolveInfo
@@ -147,6 +148,10 @@
             pw.print(prefix); pw.print("excludedPermissions=");
             pw.print(Arrays.toString(excludedPermissions));
         }
+        if (excludedPackages != null && excludedPackages.length > 0) {
+            pw.print(prefix); pw.print("excludedPackages=");
+            pw.print(Arrays.toString(excludedPackages));
+        }
         if (options != null) {
             pw.print(prefix); pw.print("options="); pw.println(options.toBundle());
         }
@@ -245,7 +250,8 @@
             Intent _intent, ProcessRecord _callerApp, String _callerPackage,
             @Nullable String _callerFeatureId, int _callingPid, int _callingUid,
             boolean _callerInstantApp, String _resolvedType,
-            String[] _requiredPermissions, String[] _excludedPermissions, int _appOp,
+            String[] _requiredPermissions, String[] _excludedPermissions,
+            String[] _excludedPackages, int _appOp,
             BroadcastOptions _options, List _receivers, IIntentReceiver _resultTo, int _resultCode,
             String _resultData, Bundle _resultExtras, boolean _serialized, boolean _sticky,
             boolean _initialSticky, int _userId, boolean allowBackgroundActivityStarts,
@@ -265,6 +271,7 @@
         resolvedType = _resolvedType;
         requiredPermissions = _requiredPermissions;
         excludedPermissions = _excludedPermissions;
+        excludedPackages = _excludedPackages;
         appOp = _appOp;
         options = _options;
         receivers = _receivers;
@@ -306,6 +313,7 @@
         resolvedType = from.resolvedType;
         requiredPermissions = from.requiredPermissions;
         excludedPermissions = from.excludedPermissions;
+        excludedPackages = from.excludedPackages;
         appOp = from.appOp;
         options = from.options;
         receivers = from.receivers;
@@ -363,9 +371,10 @@
         // build a new BroadcastRecord around that single-target list
         BroadcastRecord split = new BroadcastRecord(queue, intent, callerApp, callerPackage,
                 callerFeatureId, callingPid, callingUid, callerInstantApp, resolvedType,
-                requiredPermissions, excludedPermissions, appOp, options, splitReceivers, resultTo,
-                resultCode, resultData, resultExtras, ordered, sticky, initialSticky, userId,
-                allowBackgroundActivityStarts, mBackgroundActivityStartsToken, timeoutExempt);
+                requiredPermissions, excludedPermissions, excludedPackages, appOp, options,
+                splitReceivers, resultTo, resultCode, resultData, resultExtras, ordered, sticky,
+                initialSticky, userId, allowBackgroundActivityStarts,
+                mBackgroundActivityStartsToken, timeoutExempt);
 
         split.splitToken = this.splitToken;
         return split;
diff --git a/services/core/java/com/android/server/am/OWNERS b/services/core/java/com/android/server/am/OWNERS
index c4efbd7..15887f0 100644
--- a/services/core/java/com/android/server/am/OWNERS
+++ b/services/core/java/com/android/server/am/OWNERS
@@ -1,4 +1,3 @@
-
 # Applications & Processes
 yamasani@google.com
 jsharkey@google.com
@@ -18,8 +17,6 @@
 ogunwale@google.com
 
 # Permissions & Packages
-svetoslavganov@google.com
-toddke@google.com
 patb@google.com
 
 # Battery Stats
@@ -35,8 +32,8 @@
 per-file *Assist* = file:/core/java/android/service/voice/OWNERS
 per-file *Voice* = file:/core/java/android/service/voice/OWNERS
 
-per-file SettingsToPropertiesMapper.java = omakoto@google.com, svetoslavganov@google.com, yamasani@google.com
+per-file SettingsToPropertiesMapper.java = omakoto@google.com, yamasani@google.com
 
-per-file CarUserSwitchingDialog.java = keunyoung@google.com, felipeal@google.com, gurunagarajan@google.com
+per-file CarUserSwitchingDialog.java = file:platform/packages/services/Car:/OWNERS
 
 per-file ContentProviderHelper.java = varunshah@google.com, omakoto@google.com, jsharkey@google.com, yamasani@google.com
diff --git a/services/core/java/com/android/server/am/PreBootBroadcaster.java b/services/core/java/com/android/server/am/PreBootBroadcaster.java
index 7562098..35f91ba 100644
--- a/services/core/java/com/android/server/am/PreBootBroadcaster.java
+++ b/services/core/java/com/android/server/am/PreBootBroadcaster.java
@@ -124,7 +124,7 @@
                 REASON_PRE_BOOT_COMPLETED, "");
         synchronized (mService) {
             mService.broadcastIntentLocked(null, null, null, mIntent, null, this, 0, null, null,
-                    null, null, AppOpsManager.OP_NONE, bOptions.toBundle(), true,
+                    null, null, null, AppOpsManager.OP_NONE, bOptions.toBundle(), true,
                     false, ActivityManagerService.MY_PID,
                     Process.SYSTEM_UID, Binder.getCallingUid(), Binder.getCallingPid(), mUserId);
         }
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index 1257f1f..ca16f57 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -2897,15 +2897,6 @@
         }
 
         int N = procs.size();
-        for (int i = 0; i < N; ++i) {
-            final ProcessRecord proc = procs.get(i).first;
-            try {
-                Process.setProcessFrozen(proc.getPid(), proc.uid, true);
-            } catch (Exception e) {
-                Slog.w(TAG, "Unable to freeze " + proc.getPid() + " " + proc.processName);
-            }
-        }
-
         for (int i=0; i<N; i++) {
             final Pair<ProcessRecord, Boolean> proc = procs.get(i);
             removeProcessLocked(proc.first, callerWillRestart, allowRestart || proc.second,
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index c465be1..6f7dab9 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -2994,8 +2994,8 @@
             synchronized (mService) {
                 return mService.broadcastIntentLocked(null, null, null, intent, resolvedType,
                         resultTo, resultCode, resultData, resultExtras, requiredPermissions, null,
-                        appOp, bOptions, ordered, sticky, callingPid, callingUid, realCallingUid,
-                        realCallingPid, userId);
+                        null, appOp, bOptions, ordered, sticky, callingPid, callingUid,
+                        realCallingUid, realCallingPid, userId);
             }
         }
 
diff --git a/services/core/java/com/android/server/apphibernation/AppHibernationService.java b/services/core/java/com/android/server/apphibernation/AppHibernationService.java
index 4d025c9..28a9191 100644
--- a/services/core/java/com/android/server/apphibernation/AppHibernationService.java
+++ b/services/core/java/com/android/server/apphibernation/AppHibernationService.java
@@ -423,6 +423,7 @@
                     null /* resultExtras */,
                     requiredPermissions,
                     null /* excludedPermissions */,
+                    null /* excludedPackages */,
                     OP_NONE,
                     null /* bOptions */,
                     false /* serialized */,
@@ -441,6 +442,7 @@
                     null /* resultExtras */,
                     requiredPermissions,
                     null /* excludedPermissions */,
+                    null /* excludedPackages */,
                     OP_NONE,
                     null /* bOptions */,
                     false /* serialized */,
diff --git a/services/core/java/com/android/server/broadcastradio/OWNERS b/services/core/java/com/android/server/broadcastradio/OWNERS
index 3e360e7..d2bdd64 100644
--- a/services/core/java/com/android/server/broadcastradio/OWNERS
+++ b/services/core/java/com/android/server/broadcastradio/OWNERS
@@ -1,3 +1,3 @@
-keunyoung@google.com
+xuweilin@google.com
 oscarazu@google.com
-twasilczyk@google.com
+keunyoung@google.com
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index a545ed6..c3fc8e0 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -186,7 +186,7 @@
     private static final boolean LOGD = true;
     private static final String ANDROID_KEYSTORE_PROVIDER = "AndroidKeyStore";
     /** Key containing prefix of vpn app excluded list */
-    @VisibleForTesting static final String VPN_APP_EXCLUDED = "VPN_APP_EXCLUDED_";
+    @VisibleForTesting static final String VPN_APP_EXCLUDED = "VPNAPPEXCLUDED_";
 
     // Length of time (in milliseconds) that an app hosting an always-on VPN is placed on
     // the device idle allowlist during service launch and VPN bootstrap.
@@ -1182,20 +1182,9 @@
                 cleanupVpnStateLocked();
             } else if (mVpnRunner != null) {
                 if (!VpnConfig.LEGACY_VPN.equals(mPackage)) {
-                    mAppOpsManager.finishOp(
-                            AppOpsManager.OPSTR_ESTABLISH_VPN_MANAGER, mOwnerUID, mPackage, null);
-                    // The underlying network, NetworkCapabilities and LinkProperties are not
-                    // necessary to send to VPN app since the purpose of this event is to notify
-                    // VPN app that VPN is deactivated by the user.
-                    // TODO(b/230548427): Remove SDK check once VPN related stuff are decoupled from
-                    //  ConnectivityServiceTest.
-                    if (SdkLevel.isAtLeastT()) {
-                        sendEventToVpnManagerApp(VpnManager.CATEGORY_EVENT_DEACTIVATED_BY_USER,
-                                -1 /* errorClass */, -1 /* errorCode*/, mPackage,
-                                getSessionKeyLocked(), makeVpnProfileStateLocked(),
-                                null /* underlyingNetwork */, null /* nc */, null /* lp */);
-                    }
+                    notifyVpnManagerVpnStopped(mPackage, mOwnerUID);
                 }
+
                 // cleanupVpnStateLocked() is called from mVpnRunner.exit()
                 mVpnRunner.exit();
             }
@@ -2712,8 +2701,8 @@
          */
         @NonNull private final ScheduledThreadPoolExecutor mExecutor;
 
-        @Nullable private ScheduledFuture<?> mScheduledHandleNetworkLostTimeout;
-        @Nullable private ScheduledFuture<?> mScheduledHandleRetryIkeSessionTimeout;
+        @Nullable private ScheduledFuture<?> mScheduledHandleNetworkLostFuture;
+        @Nullable private ScheduledFuture<?> mScheduledHandleRetryIkeSessionFuture;
 
         /** Signal to ensure shutdown is honored even if a new Network is connected. */
         private boolean mIsRunning = true;
@@ -2955,6 +2944,8 @@
             }
 
             try {
+                mTunnelIface.setUnderlyingNetwork(mIkeConnectionInfo.getNetwork());
+
                 // Transforms do not need to be persisted; the IkeSession will keep
                 // them alive for us
                 mIpSecManager.applyTunnelModeTransform(mTunnelIface, direction, transform);
@@ -3136,13 +3127,13 @@
             // If the default network is lost during the retry delay, the mActiveNetwork will be
             // null, and the new IKE session won't be established until there is a new default
             // network bringing up.
-            mScheduledHandleRetryIkeSessionTimeout =
+            mScheduledHandleRetryIkeSessionFuture =
                     mExecutor.schedule(() -> {
                         startOrMigrateIkeSession(mActiveNetwork);
 
-                        // Reset mScheduledHandleRetryIkeSessionTimeout since it's already run on
+                        // Reset mScheduledHandleRetryIkeSessionFuture since it's already run on
                         // executor thread.
-                        mScheduledHandleRetryIkeSessionTimeout = null;
+                        mScheduledHandleRetryIkeSessionFuture = null;
                     }, retryDelay, TimeUnit.SECONDS);
         }
 
@@ -3185,12 +3176,10 @@
                 mActiveNetwork = null;
             }
 
-            if (mScheduledHandleNetworkLostTimeout != null
-                    && !mScheduledHandleNetworkLostTimeout.isCancelled()
-                    && !mScheduledHandleNetworkLostTimeout.isDone()) {
+            if (mScheduledHandleNetworkLostFuture != null) {
                 final IllegalStateException exception =
                         new IllegalStateException(
-                                "Found a pending mScheduledHandleNetworkLostTimeout");
+                                "Found a pending mScheduledHandleNetworkLostFuture");
                 Log.i(
                         TAG,
                         "Unexpected error in onDefaultNetworkLost. Tear down session",
@@ -3207,13 +3196,26 @@
                                 + " on session with token "
                                 + mCurrentToken);
 
+                final int token = mCurrentToken;
                 // Delay the teardown in case a new network will be available soon. For example,
                 // during handover between two WiFi networks, Android will disconnect from the
                 // first WiFi and then connects to the second WiFi.
-                mScheduledHandleNetworkLostTimeout =
+                mScheduledHandleNetworkLostFuture =
                         mExecutor.schedule(
                                 () -> {
-                                    handleSessionLost(null, network);
+                                    if (isActiveToken(token)) {
+                                        handleSessionLost(null, network);
+                                    } else {
+                                        Log.d(
+                                                TAG,
+                                                "Scheduled handleSessionLost fired for "
+                                                        + "obsolete token "
+                                                        + token);
+                                    }
+
+                                    // Reset mScheduledHandleNetworkLostFuture since it's
+                                    // already run on executor thread.
+                                    mScheduledHandleNetworkLostFuture = null;
                                 },
                                 NETWORK_LOST_TIMEOUT_MS,
                                 TimeUnit.MILLISECONDS);
@@ -3224,28 +3226,26 @@
         }
 
         private void cancelHandleNetworkLostTimeout() {
-            if (mScheduledHandleNetworkLostTimeout != null
-                    && !mScheduledHandleNetworkLostTimeout.isDone()) {
+            if (mScheduledHandleNetworkLostFuture != null) {
                 // It does not matter what to put in #cancel(boolean), because it is impossible
-                // that the task tracked by mScheduledHandleNetworkLostTimeout is
+                // that the task tracked by mScheduledHandleNetworkLostFuture is
                 // in-progress since both that task and onDefaultNetworkChanged are submitted to
                 // mExecutor who has only one thread.
                 Log.d(TAG, "Cancel the task for handling network lost timeout");
-                mScheduledHandleNetworkLostTimeout.cancel(false /* mayInterruptIfRunning */);
-                mScheduledHandleNetworkLostTimeout = null;
+                mScheduledHandleNetworkLostFuture.cancel(false /* mayInterruptIfRunning */);
+                mScheduledHandleNetworkLostFuture = null;
             }
         }
 
         private void cancelRetryNewIkeSessionFuture() {
-            if (mScheduledHandleRetryIkeSessionTimeout != null
-                    && !mScheduledHandleRetryIkeSessionTimeout.isDone()) {
+            if (mScheduledHandleRetryIkeSessionFuture != null) {
                 // It does not matter what to put in #cancel(boolean), because it is impossible
-                // that the task tracked by mScheduledHandleRetryIkeSessionTimeout is
+                // that the task tracked by mScheduledHandleRetryIkeSessionFuture is
                 // in-progress since both that task and onDefaultNetworkChanged are submitted to
                 // mExecutor who has only one thread.
                 Log.d(TAG, "Cancel the task for handling new ike session timeout");
-                mScheduledHandleRetryIkeSessionTimeout.cancel(false /* mayInterruptIfRunning */);
-                mScheduledHandleRetryIkeSessionTimeout = null;
+                mScheduledHandleRetryIkeSessionFuture.cancel(false /* mayInterruptIfRunning */);
+                mScheduledHandleRetryIkeSessionFuture = null;
             }
         }
 
@@ -3285,13 +3285,18 @@
         }
 
         private void handleSessionLost(@Nullable Exception exception, @Nullable Network network) {
-            // Cancel mScheduledHandleNetworkLostTimeout if the session it is going to terminate is
+            // Cancel mScheduledHandleNetworkLostFuture if the session it is going to terminate is
             // already terminated due to other failures.
             cancelHandleNetworkLostTimeout();
 
             synchronized (Vpn.this) {
+                String category = null;
+                int errorClass = -1;
+                int errorCode = -1;
                 if (exception instanceof IkeProtocolException) {
                     final IkeProtocolException ikeException = (IkeProtocolException) exception;
+                    category = VpnManager.CATEGORY_EVENT_IKE_ERROR;
+                    errorCode = ikeException.getErrorType();
 
                     switch (ikeException.getErrorType()) {
                         case IkeProtocolException.ERROR_TYPE_NO_PROPOSAL_CHOSEN: // Fallthrough
@@ -3301,105 +3306,53 @@
                         case IkeProtocolException.ERROR_TYPE_FAILED_CP_REQUIRED: // Fallthrough
                         case IkeProtocolException.ERROR_TYPE_TS_UNACCEPTABLE:
                             // All the above failures are configuration errors, and are terminal
-                            // TODO(b/230548427): Remove SDK check once VPN related stuff are
-                            //  decoupled from ConnectivityServiceTest.
-                            if (SdkLevel.isAtLeastT()) {
-                                sendEventToVpnManagerApp(VpnManager.CATEGORY_EVENT_IKE_ERROR,
-                                        VpnManager.ERROR_CLASS_NOT_RECOVERABLE,
-                                        ikeException.getErrorType(),
-                                        getPackage(), mSessionKey, makeVpnProfileStateLocked(),
-                                        network,
-                                        getRedactedNetworkCapabilitiesOfUnderlyingNetwork(
-                                                mUnderlyingNetworkCapabilities),
-                                        getRedactedLinkPropertiesOfUnderlyingNetwork(
-                                                mUnderlyingLinkProperties));
-                            }
-                            markFailedAndDisconnect(exception);
-                            return;
+                            errorClass = VpnManager.ERROR_CLASS_NOT_RECOVERABLE;
+                            break;
                         // All other cases possibly recoverable.
                         default:
                             // All the above failures are configuration errors, and are terminal
-                            // TODO(b/230548427): Remove SDK check once VPN related stuff are
-                            //  decoupled from ConnectivityServiceTest.
-                            if (SdkLevel.isAtLeastT()) {
-                                sendEventToVpnManagerApp(VpnManager.CATEGORY_EVENT_IKE_ERROR,
-                                        VpnManager.ERROR_CLASS_RECOVERABLE,
-                                        ikeException.getErrorType(),
-                                        getPackage(), mSessionKey, makeVpnProfileStateLocked(),
-                                        network,
-                                        getRedactedNetworkCapabilitiesOfUnderlyingNetwork(
-                                                mUnderlyingNetworkCapabilities),
-                                        getRedactedLinkPropertiesOfUnderlyingNetwork(
-                                                mUnderlyingLinkProperties));
-                            }
+                            errorClass = VpnManager.ERROR_CLASS_RECOVERABLE;
                     }
                 } else if (exception instanceof IllegalArgumentException) {
                     // Failed to build IKE/ChildSessionParams; fatal profile configuration error
                     markFailedAndDisconnect(exception);
                     return;
                 } else if (exception instanceof IkeNetworkLostException) {
-                    // TODO(b/230548427): Remove SDK check once VPN related stuff are
-                    //  decoupled from ConnectivityServiceTest.
-                    if (SdkLevel.isAtLeastT()) {
-                        sendEventToVpnManagerApp(VpnManager.CATEGORY_EVENT_NETWORK_ERROR,
-                                VpnManager.ERROR_CLASS_RECOVERABLE,
-                                VpnManager.ERROR_CODE_NETWORK_LOST,
-                                getPackage(), mSessionKey, makeVpnProfileStateLocked(),
-                                network,
-                                getRedactedNetworkCapabilitiesOfUnderlyingNetwork(
-                                        mUnderlyingNetworkCapabilities),
-                                getRedactedLinkPropertiesOfUnderlyingNetwork(
-                                        mUnderlyingLinkProperties));
-                    }
+                    category = VpnManager.CATEGORY_EVENT_NETWORK_ERROR;
+                    errorClass = VpnManager.ERROR_CLASS_RECOVERABLE;
+                    errorCode = VpnManager.ERROR_CODE_NETWORK_LOST;
                 } else if (exception instanceof IkeNonProtocolException) {
+                    category = VpnManager.CATEGORY_EVENT_NETWORK_ERROR;
+                    errorClass = VpnManager.ERROR_CLASS_RECOVERABLE;
                     if (exception.getCause() instanceof UnknownHostException) {
-                        // TODO(b/230548427): Remove SDK check once VPN related stuff are
-                        //  decoupled from ConnectivityServiceTest.
-                        if (SdkLevel.isAtLeastT()) {
-                            sendEventToVpnManagerApp(VpnManager.CATEGORY_EVENT_NETWORK_ERROR,
-                                    VpnManager.ERROR_CLASS_RECOVERABLE,
-                                    VpnManager.ERROR_CODE_NETWORK_UNKNOWN_HOST,
-                                    getPackage(), mSessionKey, makeVpnProfileStateLocked(),
-                                    network,
-                                    getRedactedNetworkCapabilitiesOfUnderlyingNetwork(
-                                            mUnderlyingNetworkCapabilities),
-                                    getRedactedLinkPropertiesOfUnderlyingNetwork(
-                                            mUnderlyingLinkProperties));
-                        }
+                        errorCode = VpnManager.ERROR_CODE_NETWORK_UNKNOWN_HOST;
                     } else if (exception.getCause() instanceof IkeTimeoutException) {
-                        // TODO(b/230548427): Remove SDK check once VPN related stuff are
-                        //  decoupled from ConnectivityServiceTest.
-                        if (SdkLevel.isAtLeastT()) {
-                            sendEventToVpnManagerApp(VpnManager.CATEGORY_EVENT_NETWORK_ERROR,
-                                    VpnManager.ERROR_CLASS_RECOVERABLE,
-                                    VpnManager.ERROR_CODE_NETWORK_PROTOCOL_TIMEOUT,
-                                    getPackage(), mSessionKey, makeVpnProfileStateLocked(),
-                                    network,
-                                    getRedactedNetworkCapabilitiesOfUnderlyingNetwork(
-                                            mUnderlyingNetworkCapabilities),
-                                    getRedactedLinkPropertiesOfUnderlyingNetwork(
-                                            mUnderlyingLinkProperties));
-                        }
+                        errorCode = VpnManager.ERROR_CODE_NETWORK_PROTOCOL_TIMEOUT;
                     } else if (exception.getCause() instanceof IOException) {
-                        // TODO(b/230548427): Remove SDK check once VPN related stuff are
-                        //  decoupled from ConnectivityServiceTest.
-                        if (SdkLevel.isAtLeastT()) {
-                            sendEventToVpnManagerApp(VpnManager.CATEGORY_EVENT_NETWORK_ERROR,
-                                    VpnManager.ERROR_CLASS_RECOVERABLE,
-                                    VpnManager.ERROR_CODE_NETWORK_IO,
-                                    getPackage(), mSessionKey, makeVpnProfileStateLocked(),
-                                    network,
-                                    getRedactedNetworkCapabilitiesOfUnderlyingNetwork(
-                                            mUnderlyingNetworkCapabilities),
-                                    getRedactedLinkPropertiesOfUnderlyingNetwork(
-                                            mUnderlyingLinkProperties));
-                        }
+                        errorCode = VpnManager.ERROR_CODE_NETWORK_IO;
                     }
                 } else if (exception != null) {
                     Log.wtf(TAG, "onSessionLost: exception = " + exception);
                 }
 
-                scheduleRetryNewIkeSession();
+                // TODO(b/230548427): Remove SDK check once VPN related stuff are
+                //  decoupled from ConnectivityServiceTest.
+                if (SdkLevel.isAtLeastT() && category != null) {
+                    sendEventToVpnManagerApp(category, errorClass, errorCode,
+                            getPackage(), mSessionKey, makeVpnProfileStateLocked(),
+                            mActiveNetwork,
+                            getRedactedNetworkCapabilitiesOfUnderlyingNetwork(
+                                    mUnderlyingNetworkCapabilities),
+                            getRedactedLinkPropertiesOfUnderlyingNetwork(
+                                    mUnderlyingLinkProperties));
+                }
+
+                if (errorClass == VpnManager.ERROR_CLASS_NOT_RECOVERABLE) {
+                    markFailedAndDisconnect(exception);
+                    return;
+                } else {
+                    scheduleRetryNewIkeSession();
+                }
             }
 
             mUnderlyingNetworkCapabilities = null;
@@ -4079,7 +4032,25 @@
         // To stop the VPN profile, the caller must be the current prepared package and must be
         // running an Ikev2VpnProfile.
         if (isCurrentIkev2VpnLocked(packageName)) {
-            prepareInternal(VpnConfig.LEGACY_VPN);
+            notifyVpnManagerVpnStopped(packageName, mOwnerUID);
+
+            mVpnRunner.exit();
+        }
+    }
+
+    private synchronized void notifyVpnManagerVpnStopped(String packageName, int ownerUID) {
+        mAppOpsManager.finishOp(
+                AppOpsManager.OPSTR_ESTABLISH_VPN_MANAGER, ownerUID, packageName, null);
+        // The underlying network, NetworkCapabilities and LinkProperties are not
+        // necessary to send to VPN app since the purpose of this event is to notify
+        // VPN app that VPN is deactivated by the user.
+        // TODO(b/230548427): Remove SDK check once VPN related stuff are decoupled from
+        //  ConnectivityServiceTest.
+        if (SdkLevel.isAtLeastT()) {
+            sendEventToVpnManagerApp(VpnManager.CATEGORY_EVENT_DEACTIVATED_BY_USER,
+                    -1 /* errorClass */, -1 /* errorCode*/, packageName,
+                    getSessionKeyLocked(), makeVpnProfileStateLocked(),
+                    null /* underlyingNetwork */, null /* nc */, null /* lp */);
         }
     }
 
@@ -4121,6 +4092,20 @@
             @NonNull List<String> excludedApps) {
         enforceNotRestrictedUser();
         if (!storeAppExclusionList(packageName, excludedApps)) return false;
+
+        updateAppExclusionList(excludedApps);
+
+        return true;
+    }
+
+    /**
+     * Triggers an update of the VPN network's excluded UIDs if a VPN is running.
+     */
+    public synchronized void refreshPlatformVpnAppExclusionList() {
+        updateAppExclusionList(getAppExclusionList(mPackage));
+    }
+
+    private synchronized void updateAppExclusionList(@NonNull List<String> excludedApps) {
         // Re-build and update NetworkCapabilities via NetworkAgent.
         if (mNetworkAgent != null) {
             // Only update the platform VPN
@@ -4133,8 +4118,6 @@
                 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
             }
         }
-
-        return true;
     }
 
     /**
diff --git a/services/core/java/com/android/server/dreams/OWNERS b/services/core/java/com/android/server/dreams/OWNERS
index 426f002..7302f6e 100644
--- a/services/core/java/com/android/server/dreams/OWNERS
+++ b/services/core/java/com/android/server/dreams/OWNERS
@@ -1,3 +1,4 @@
+brycelee@google.com
 dsandler@android.com
 michaelwr@google.com
 roosa@google.com
diff --git a/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java b/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java
index 601a572..4631570 100644
--- a/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java
+++ b/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java
@@ -116,9 +116,9 @@
     // 256-bit synthetic password
     private static final byte SYNTHETIC_PASSWORD_LENGTH = 256 / 8;
 
-    private static final int PASSWORD_SCRYPT_N = 11;
-    private static final int PASSWORD_SCRYPT_R = 3;
-    private static final int PASSWORD_SCRYPT_P = 1;
+    private static final int PASSWORD_SCRYPT_LOG_N = 11;
+    private static final int PASSWORD_SCRYPT_LOG_R = 3;
+    private static final int PASSWORD_SCRYPT_LOG_P = 1;
     private static final int PASSWORD_SALT_LENGTH = 16;
     private static final int PASSWORD_TOKEN_LENGTH = 32;
     private static final String TAG = "SyntheticPasswordManager";
@@ -186,7 +186,11 @@
             mVersion = version;
         }
 
-        private byte[] derivePassword(byte[] personalization) {
+        /**
+         * Derives a subkey from the synthetic password. For v3 and later synthetic passwords the
+         * subkeys are 256-bit; for v1 and v2 they are 512-bit.
+         */
+        private byte[] deriveSubkey(byte[] personalization) {
             if (mVersion == SYNTHETIC_PASSWORD_VERSION_V3) {
                 return (new SP800Derive(mSyntheticPassword))
                     .withContext(personalization, PERSONALISATION_CONTEXT);
@@ -197,28 +201,28 @@
         }
 
         public byte[] deriveKeyStorePassword() {
-            return bytesToHex(derivePassword(PERSONALIZATION_KEY_STORE_PASSWORD));
+            return bytesToHex(deriveSubkey(PERSONALIZATION_KEY_STORE_PASSWORD));
         }
 
         public byte[] deriveGkPassword() {
-            return derivePassword(PERSONALIZATION_SP_GK_AUTH);
+            return deriveSubkey(PERSONALIZATION_SP_GK_AUTH);
         }
 
         public byte[] deriveDiskEncryptionKey() {
-            return derivePassword(PERSONALIZATION_FBE_KEY);
+            return deriveSubkey(PERSONALIZATION_FBE_KEY);
         }
 
         public byte[] deriveVendorAuthSecret() {
-            return derivePassword(PERSONALIZATION_AUTHSECRET_KEY);
+            return deriveSubkey(PERSONALIZATION_AUTHSECRET_KEY);
         }
 
         public byte[] derivePasswordHashFactor() {
-            return derivePassword(PERSONALIZATION_PASSWORD_HASH);
+            return deriveSubkey(PERSONALIZATION_PASSWORD_HASH);
         }
 
         /** Derives key used to encrypt password metrics */
         public byte[] deriveMetricsKey() {
-            return derivePassword(PERSONALIZATION_PASSWORD_METRICS);
+            return deriveSubkey(PERSONALIZATION_PASSWORD_METRICS);
         }
 
         /**
@@ -268,9 +272,8 @@
          * AuthenticationToken.mSyntheticPassword for details on what each block means.
          */
         private void recreate(byte[] escrowSplit0, byte[] escrowSplit1) {
-            mSyntheticPassword = String.valueOf(HexEncoding.encode(
-                    SyntheticPasswordCrypto.personalisedHash(
-                            PERSONALIZATION_SP_SPLIT, escrowSplit0, escrowSplit1))).getBytes();
+            mSyntheticPassword = bytesToHex(SyntheticPasswordCrypto.personalisedHash(
+                    PERSONALIZATION_SP_SPLIT, escrowSplit0, escrowSplit1));
         }
 
         /**
@@ -304,9 +307,9 @@
     }
 
     static class PasswordData {
-        byte scryptN;
-        byte scryptR;
-        byte scryptP;
+        byte scryptLogN;
+        byte scryptLogR;
+        byte scryptLogP;
         public int credentialType;
         byte[] salt;
         // For GateKeeper-based credential, this is the password handle returned by GK,
@@ -315,9 +318,9 @@
 
         public static PasswordData create(int passwordType) {
             PasswordData result = new PasswordData();
-            result.scryptN = PASSWORD_SCRYPT_N;
-            result.scryptR = PASSWORD_SCRYPT_R;
-            result.scryptP = PASSWORD_SCRYPT_P;
+            result.scryptLogN = PASSWORD_SCRYPT_LOG_N;
+            result.scryptLogR = PASSWORD_SCRYPT_LOG_R;
+            result.scryptLogP = PASSWORD_SCRYPT_LOG_P;
             result.credentialType = passwordType;
             result.salt = secureRandom(PASSWORD_SALT_LENGTH);
             return result;
@@ -329,9 +332,9 @@
             buffer.put(data, 0, data.length);
             buffer.flip();
             result.credentialType = buffer.getInt();
-            result.scryptN = buffer.get();
-            result.scryptR = buffer.get();
-            result.scryptP = buffer.get();
+            result.scryptLogN = buffer.get();
+            result.scryptLogR = buffer.get();
+            result.scryptLogP = buffer.get();
             int saltLen = buffer.getInt();
             result.salt = new byte[saltLen];
             buffer.get(result.salt);
@@ -351,9 +354,9 @@
                     + Integer.BYTES + salt.length + Integer.BYTES +
                     (passwordHandle != null ? passwordHandle.length : 0));
             buffer.putInt(credentialType);
-            buffer.put(scryptN);
-            buffer.put(scryptR);
-            buffer.put(scryptP);
+            buffer.put(scryptLogN);
+            buffer.put(scryptLogR);
+            buffer.put(scryptLogP);
             buffer.putInt(salt.length);
             buffer.put(salt);
             if (passwordHandle != null && passwordHandle.length > 0) {
@@ -1369,8 +1372,8 @@
 
     private byte[] computePasswordToken(LockscreenCredential credential, PasswordData data) {
         final byte[] password = credential.isNone() ? DEFAULT_PASSWORD : credential.getCredential();
-        return scrypt(password, data.salt, 1 << data.scryptN, 1 << data.scryptR, 1 << data.scryptP,
-                PASSWORD_TOKEN_LENGTH);
+        return scrypt(password, data.salt, 1 << data.scryptLogN, 1 << data.scryptLogR,
+                1 << data.scryptLogP, PASSWORD_TOKEN_LENGTH);
     }
 
     private byte[] passwordTokenToGkInput(byte[] token) {
@@ -1411,18 +1414,9 @@
         return result;
     }
 
-    protected static final byte[] HEX_ARRAY = "0123456789ABCDEF".getBytes();
-    private static byte[] bytesToHex(byte[] bytes) {
-        if (bytes == null) {
-            return "null".getBytes();
-        }
-        byte[] hexBytes = new byte[bytes.length * 2];
-        for ( int j = 0; j < bytes.length; j++ ) {
-            int v = bytes[j] & 0xFF;
-            hexBytes[j * 2] = HEX_ARRAY[v >>> 4];
-            hexBytes[j * 2 + 1] = HEX_ARRAY[v & 0x0F];
-        }
-        return hexBytes;
+    @VisibleForTesting
+    static byte[] bytesToHex(byte[] bytes) {
+        return HexEncoding.encodeToString(bytes).getBytes();
     }
 
     /**
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 39d501b..d162ce2 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -15962,7 +15962,7 @@
             final BroadcastOptions bOptions = getTemporaryAppAllowlistBroadcastOptions(
                     REASON_LOCKED_BOOT_COMPLETED);
             am.broadcastIntentWithFeature(null, null, lockedBcIntent, null, null, 0, null, null,
-                    requiredPermissions, null, android.app.AppOpsManager.OP_NONE,
+                    requiredPermissions, null, null, android.app.AppOpsManager.OP_NONE,
                     bOptions.toBundle(), false, false, userId);
 
             // Deliver BOOT_COMPLETED only if user is unlocked
@@ -15973,7 +15973,7 @@
                     bcIntent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
                 }
                 am.broadcastIntentWithFeature(null, null, bcIntent, null, null, 0, null, null,
-                        requiredPermissions, null, android.app.AppOpsManager.OP_NONE,
+                        requiredPermissions, null, null, android.app.AppOpsManager.OP_NONE,
                         bOptions.toBundle(), false, false, userId);
             }
         } catch (RemoteException e) {
@@ -22869,7 +22869,7 @@
             intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
             try {
                 am.broadcastIntentWithFeature(null, null, intent, null, null,
-                        0, null, null, null, null, android.app.AppOpsManager.OP_NONE,
+                        0, null, null, null, null, null, android.app.AppOpsManager.OP_NONE,
                         null, false, false, userId);
             } catch (RemoteException e) {
             }
@@ -28766,8 +28766,8 @@
             };
             try {
                 am.broadcastIntentWithFeature(null, null, intent, null, null, 0, null, null,
-                        requiredPermissions, null, android.app.AppOpsManager.OP_NONE, null, false,
-                        false, UserHandle.USER_ALL);
+                        requiredPermissions, null, null, android.app.AppOpsManager.OP_NONE, null,
+                        false, false, UserHandle.USER_ALL);
             } catch (RemoteException e) {
                 throw e.rethrowFromSystemServer();
             }
diff --git a/services/core/java/com/android/server/pm/UserDataPreparer.java b/services/core/java/com/android/server/pm/UserDataPreparer.java
index 1ca7bcd..479701e 100644
--- a/services/core/java/com/android/server/pm/UserDataPreparer.java
+++ b/services/core/java/com/android/server/pm/UserDataPreparer.java
@@ -125,8 +125,11 @@
                     flags | StorageManager.FLAG_STORAGE_DE, false);
             } else {
                 try {
-                    Log.e(TAG, "prepareUserData failed", e);
-                    RecoverySystem.rebootPromptAndWipeUserData(mContext, "prepareUserData failed");
+                    Log.wtf(TAG, "prepareUserData failed for user " + userId, e);
+                    if (userId == UserHandle.USER_SYSTEM) {
+                        RecoverySystem.rebootPromptAndWipeUserData(mContext,
+                                "prepareUserData failed for system user");
+                    }
                 } catch (IOException e2) {
                     throw new RuntimeException("error rebooting into recovery", e2);
                 }
diff --git a/services/core/java/com/android/server/pm/UserManagerInternal.java b/services/core/java/com/android/server/pm/UserManagerInternal.java
index eb2de60..0e6d5e5 100644
--- a/services/core/java/com/android/server/pm/UserManagerInternal.java
+++ b/services/core/java/com/android/server/pm/UserManagerInternal.java
@@ -312,4 +312,12 @@
      */
     public abstract void setDefaultCrossProfileIntentFilters(
             @UserIdInt int parentUserId, @UserIdInt int profileUserId);
+
+    /**
+     * Returns {@code true} if the system should ignore errors when preparing
+     * the storage directories for the user with ID {@code userId}. This will
+     * return {@code false} for all new users; it will only return {@code true}
+     * for users that already existed on-disk from an older version of Android.
+     */
+    public abstract boolean shouldIgnorePrepareStorageErrors(int userId);
 }
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 374a5c2..af3dafc 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -204,6 +204,8 @@
     private static final String TAG_SEED_ACCOUNT_OPTIONS = "seedAccountOptions";
     private static final String TAG_LAST_REQUEST_QUIET_MODE_ENABLED_CALL =
             "lastRequestQuietModeEnabledCall";
+    private static final String TAG_IGNORE_PREPARE_STORAGE_ERRORS =
+            "ignorePrepareStorageErrors";
     private static final String ATTR_KEY = "key";
     private static final String ATTR_VALUE_TYPE = "type";
     private static final String ATTR_MULTIPLE = "m";
@@ -313,6 +315,14 @@
 
         private long mLastRequestQuietModeEnabledMillis;
 
+        /**
+         * {@code true} if the system should ignore errors when preparing the
+         * storage directories for this user. This is {@code false} for all new
+         * users; it will only be {@code true} for users that already existed
+         * on-disk from an older version of Android.
+         */
+        private boolean mIgnorePrepareStorageErrors;
+
         void setLastRequestQuietModeEnabledMillis(long millis) {
             mLastRequestQuietModeEnabledMillis = millis;
         }
@@ -321,6 +331,14 @@
             return mLastRequestQuietModeEnabledMillis;
         }
 
+        boolean getIgnorePrepareStorageErrors() {
+            return mIgnorePrepareStorageErrors;
+        }
+
+        void setIgnorePrepareStorageErrors() {
+            mIgnorePrepareStorageErrors = true;
+        }
+
         void clearSeedAccountData() {
             seedAccountName = null;
             seedAccountType = null;
@@ -3180,6 +3198,10 @@
             serializer.endTag(/* namespace */ null, TAG_LAST_REQUEST_QUIET_MODE_ENABLED_CALL);
         }
 
+        serializer.startTag(/* namespace */ null, TAG_IGNORE_PREPARE_STORAGE_ERRORS);
+        serializer.text(String.valueOf(userData.getIgnorePrepareStorageErrors()));
+        serializer.endTag(/* namespace */ null, TAG_IGNORE_PREPARE_STORAGE_ERRORS);
+
         serializer.endTag(null, TAG_USER);
 
         serializer.endDocument();
@@ -3289,6 +3311,7 @@
         Bundle legacyLocalRestrictions = null;
         RestrictionsSet localRestrictions = null;
         Bundle globalRestrictions = null;
+        boolean ignorePrepareStorageErrors = true; // default is true for old users
 
         final TypedXmlPullParser parser = Xml.resolvePullParser(is);
         int type;
@@ -3367,6 +3390,11 @@
                     if (type == XmlPullParser.TEXT) {
                         lastRequestQuietModeEnabledTimestamp = Long.parseLong(parser.getText());
                     }
+                } else if (TAG_IGNORE_PREPARE_STORAGE_ERRORS.equals(tag)) {
+                    type = parser.next();
+                    if (type == XmlPullParser.TEXT) {
+                        ignorePrepareStorageErrors = Boolean.parseBoolean(parser.getText());
+                    }
                 }
             }
         }
@@ -3394,6 +3422,9 @@
         userData.persistSeedData = persistSeedData;
         userData.seedAccountOptions = seedAccountOptions;
         userData.setLastRequestQuietModeEnabledMillis(lastRequestQuietModeEnabledTimestamp);
+        if (ignorePrepareStorageErrors) {
+            userData.setIgnorePrepareStorageErrors();
+        }
 
         synchronized (mRestrictionsLock) {
             if (baseRestrictions != null) {
@@ -5238,6 +5269,9 @@
                             pw.println();
                         }
                     }
+
+                    pw.println("    Ignore errors preparing storage: "
+                            + userData.getIgnorePrepareStorageErrors());
                 }
             }
 
@@ -5727,6 +5761,14 @@
             UserManagerService.this.setDefaultCrossProfileIntentFilters(
                     profileUserId, userTypeDetails, restrictions, parentUserId);
         }
+
+        @Override
+        public boolean shouldIgnorePrepareStorageErrors(int userId) {
+            synchronized (mUsersLock) {
+                UserData userData = mUsers.get(userId);
+                return userData != null && userData.getIgnorePrepareStorageErrors();
+            }
+        }
     }
 
     /**
diff --git a/services/core/java/com/android/server/testharness/TestHarnessModeService.java b/services/core/java/com/android/server/testharness/TestHarnessModeService.java
index b6a4135..452bdf4 100644
--- a/services/core/java/com/android/server/testharness/TestHarnessModeService.java
+++ b/services/core/java/com/android/server/testharness/TestHarnessModeService.java
@@ -189,6 +189,7 @@
         if (adbManager.getAdbTempKeysFile() != null) {
             writeBytesToFile(persistentData.mAdbTempKeys, adbManager.getAdbTempKeysFile().toPath());
         }
+        adbManager.notifyKeyFilesUpdated();
     }
 
     private void configureUser() {
diff --git a/services/core/java/com/android/server/timezone/CheckToken.java b/services/core/java/com/android/server/timezone/CheckToken.java
deleted file mode 100644
index 4c4a8d7..0000000
--- a/services/core/java/com/android/server/timezone/CheckToken.java
+++ /dev/null
@@ -1,98 +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.timezone;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.DataInputStream;
-import java.io.DataOutputStream;
-import java.io.IOException;
-import java.util.Arrays;
-
-/**
- * A deserialized version of the byte[] sent to the time zone update application to identify a
- * triggered time zone update check. It encodes the optimistic lock ID used to detect
- * concurrent checks and the minimal package versions that will have been checked.
- */
-final class CheckToken {
-
-    final int mOptimisticLockId;
-    final PackageVersions mPackageVersions;
-
-    CheckToken(int optimisticLockId, PackageVersions packageVersions) {
-        this.mOptimisticLockId = optimisticLockId;
-
-        if (packageVersions == null) {
-            throw new NullPointerException("packageVersions == null");
-        }
-        this.mPackageVersions = packageVersions;
-    }
-
-    byte[] toByteArray() {
-        ByteArrayOutputStream baos = new ByteArrayOutputStream(12 /* (3 * sizeof(int)) */);
-        try (DataOutputStream dos = new DataOutputStream(baos)) {
-            dos.writeInt(mOptimisticLockId);
-            dos.writeLong(mPackageVersions.mUpdateAppVersion);
-            dos.writeLong(mPackageVersions.mDataAppVersion);
-        } catch (IOException e) {
-            throw new RuntimeException("Unable to write into a ByteArrayOutputStream", e);
-        }
-        return baos.toByteArray();
-    }
-
-    static CheckToken fromByteArray(byte[] tokenBytes) throws IOException {
-        ByteArrayInputStream bais = new ByteArrayInputStream(tokenBytes);
-        try (DataInputStream dis = new DataInputStream(bais)) {
-            int versionId = dis.readInt();
-            long updateAppVersion = dis.readLong();
-            long dataAppVersion = dis.readLong();
-            return new CheckToken(versionId, new PackageVersions(updateAppVersion, dataAppVersion));
-        }
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) {
-            return true;
-        }
-        if (o == null || getClass() != o.getClass()) {
-            return false;
-        }
-
-        CheckToken checkToken = (CheckToken) o;
-
-        if (mOptimisticLockId != checkToken.mOptimisticLockId) {
-            return false;
-        }
-        return mPackageVersions.equals(checkToken.mPackageVersions);
-    }
-
-    @Override
-    public int hashCode() {
-        int result = mOptimisticLockId;
-        result = 31 * result + mPackageVersions.hashCode();
-        return result;
-    }
-
-    @Override
-    public String toString() {
-        return "Token{" +
-                "mOptimisticLockId=" + mOptimisticLockId +
-                ", mPackageVersions=" + mPackageVersions +
-                '}';
-    }
-}
diff --git a/services/core/java/com/android/server/timezone/ConfigHelper.java b/services/core/java/com/android/server/timezone/ConfigHelper.java
deleted file mode 100644
index f9984fa..0000000
--- a/services/core/java/com/android/server/timezone/ConfigHelper.java
+++ /dev/null
@@ -1,34 +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.timezone;
-
-/**
- * An easy-to-mock interface around device config for use by {@link PackageTracker}; it is not
- * possible to test various states with the real one because config is fixed in the system image.
- */
-interface ConfigHelper {
-
-    boolean isTrackingEnabled();
-
-    String getUpdateAppPackageName();
-
-    String getDataAppPackageName();
-
-    int getCheckTimeAllowedMillis();
-
-    int getFailedCheckRetryCount();
-}
diff --git a/services/core/java/com/android/server/timezone/PackageManagerHelper.java b/services/core/java/com/android/server/timezone/PackageManagerHelper.java
deleted file mode 100644
index f6e35e8..0000000
--- a/services/core/java/com/android/server/timezone/PackageManagerHelper.java
+++ /dev/null
@@ -1,41 +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.timezone;
-
-import android.content.Intent;
-import android.content.pm.PackageManager;
-
-/**
- * An easy-to-mock facade around PackageManager for use by {@link PackageTracker}; it is not
- * possible to test various cases with the real one because of the need to simulate package versions
- * and manifest configurations.
- */
-interface PackageManagerHelper {
-
-    long getInstalledPackageVersion(String packageName)
-            throws PackageManager.NameNotFoundException;
-
-    boolean isPrivilegedApp(String packageName) throws PackageManager.NameNotFoundException;
-
-    boolean usesPermission(String packageName, String requiredPermissionName)
-                    throws PackageManager.NameNotFoundException;
-
-    boolean contentProviderRegistered(String authority, String requiredPackageName);
-
-    boolean receiverRegistered(Intent intent, String requiredPermissionName)
-                            throws PackageManager.NameNotFoundException;
-}
diff --git a/services/core/java/com/android/server/timezone/PackageStatus.java b/services/core/java/com/android/server/timezone/PackageStatus.java
deleted file mode 100644
index 63790961..0000000
--- a/services/core/java/com/android/server/timezone/PackageStatus.java
+++ /dev/null
@@ -1,89 +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.timezone;
-
-import android.annotation.IntDef;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * Information about the status of the time zone update / data packages that are persisted by the
- * Android system.
- */
-final class PackageStatus {
-
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef({ CHECK_STARTED, CHECK_COMPLETED_SUCCESS, CHECK_COMPLETED_FAILURE })
-    @interface CheckStatus {}
-
-    /** A time zone update check has been started but not yet completed. */
-    static final int CHECK_STARTED = 1;
-    /** A time zone update check has been completed and succeeded. */
-    static final int CHECK_COMPLETED_SUCCESS = 2;
-    /** A time zone update check has been completed and failed. */
-    static final int CHECK_COMPLETED_FAILURE = 3;
-
-    @CheckStatus
-    final int mCheckStatus;
-
-    // Non-null
-    final PackageVersions mVersions;
-
-    PackageStatus(@CheckStatus int checkStatus, PackageVersions versions) {
-        this.mCheckStatus = checkStatus;
-        if (checkStatus < 1 || checkStatus > 3) {
-            throw new IllegalArgumentException("Unknown checkStatus " + checkStatus);
-        }
-        if (versions == null) {
-            throw new NullPointerException("versions == null");
-        }
-        this.mVersions = versions;
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) {
-            return true;
-        }
-        if (o == null || getClass() != o.getClass()) {
-            return false;
-        }
-
-        PackageStatus that = (PackageStatus) o;
-
-        if (mCheckStatus != that.mCheckStatus) {
-            return false;
-        }
-        return mVersions.equals(that.mVersions);
-    }
-
-    @Override
-    public int hashCode() {
-        int result = mCheckStatus;
-        result = 31 * result + mVersions.hashCode();
-        return result;
-    }
-
-    @Override
-    public String toString() {
-        return "PackageStatus{" +
-                "mCheckStatus=" + mCheckStatus +
-                ", mVersions=" + mVersions +
-                '}';
-    }
-}
diff --git a/services/core/java/com/android/server/timezone/PackageStatusStorage.java b/services/core/java/com/android/server/timezone/PackageStatusStorage.java
deleted file mode 100644
index fd0df8d..0000000
--- a/services/core/java/com/android/server/timezone/PackageStatusStorage.java
+++ /dev/null
@@ -1,389 +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.timezone;
-
-import com.android.internal.annotations.GuardedBy;
-import com.android.internal.util.FastXmlSerializer;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-import org.xmlpull.v1.XmlSerializer;
-
-import android.util.AtomicFile;
-import android.util.Slog;
-import android.util.TypedXmlPullParser;
-import android.util.TypedXmlSerializer;
-import android.util.Xml;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.nio.charset.StandardCharsets;
-import java.text.ParseException;
-import java.io.PrintWriter;
-
-import static com.android.server.timezone.PackageStatus.CHECK_COMPLETED_FAILURE;
-import static com.android.server.timezone.PackageStatus.CHECK_COMPLETED_SUCCESS;
-import static com.android.server.timezone.PackageStatus.CHECK_STARTED;
-import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
-import static org.xmlpull.v1.XmlPullParser.START_TAG;
-
-/**
- * Storage logic for accessing/mutating the Android system's persistent state related to time zone
- * update checking. There is expected to be a single instance. All non-private methods are thread
- * safe.
- */
-final class PackageStatusStorage {
-
-    private static final String LOG_TAG = "timezone.PackageStatusStorage";
-
-    private static final String TAG_PACKAGE_STATUS = "PackageStatus";
-
-    /**
-     * Attribute that stores a monotonically increasing lock ID, used to detect concurrent update
-     * issues without on-line locks. Incremented on every write.
-     */
-    private static final String ATTRIBUTE_OPTIMISTIC_LOCK_ID = "optimisticLockId";
-
-    /**
-     * Attribute that stores the current "check status" of the time zone update application
-     * packages.
-     */
-    private static final String ATTRIBUTE_CHECK_STATUS = "checkStatus";
-
-    /**
-     * Attribute that stores the version of the time zone rules update application being checked
-     * / last checked.
-     */
-    private static final String ATTRIBUTE_UPDATE_APP_VERSION = "updateAppPackageVersion";
-
-    /**
-     * Attribute that stores the version of the time zone rules data application being checked
-     * / last checked.
-     */
-    private static final String ATTRIBUTE_DATA_APP_VERSION = "dataAppPackageVersion";
-
-    private static final long UNKNOWN_PACKAGE_VERSION = -1;
-
-    private final AtomicFile mPackageStatusFile;
-
-    PackageStatusStorage(File storageDir) {
-        mPackageStatusFile = new AtomicFile(new File(storageDir, "package-status.xml"), "timezone-status");
-    }
-
-    /**
-     * Initialize any storage, as needed.
-     *
-     * @throws IOException if the storage could not be initialized
-     */
-    void initialize() throws IOException {
-        if (!mPackageStatusFile.getBaseFile().exists()) {
-            insertInitialPackageStatus();
-        }
-    }
-
-    void deleteFileForTests() {
-        synchronized(this) {
-            mPackageStatusFile.delete();
-        }
-    }
-
-    /**
-     * Obtain the current check status of the application packages. Returns {@code null} the first
-     * time it is called, or after {@link #resetCheckState()}.
-     */
-    PackageStatus getPackageStatus() {
-        synchronized (this) {
-            try {
-                return getPackageStatusLocked();
-            } catch (ParseException e) {
-                // This means that data exists in the file but it was bad.
-                Slog.e(LOG_TAG, "Package status invalid, resetting and retrying", e);
-
-                // Reset the storage so it is in a good state again.
-                recoverFromBadData(e);
-                try {
-                    return getPackageStatusLocked();
-                } catch (ParseException e2) {
-                    throw new IllegalStateException("Recovery from bad file failed", e2);
-                }
-            }
-        }
-    }
-
-    @GuardedBy("this")
-    private PackageStatus getPackageStatusLocked() throws ParseException {
-        try (FileInputStream fis = mPackageStatusFile.openRead()) {
-            TypedXmlPullParser parser = parseToPackageStatusTag(fis);
-            Integer checkStatus = getNullableIntAttribute(parser, ATTRIBUTE_CHECK_STATUS);
-            if (checkStatus == null) {
-                return null;
-            }
-            int updateAppVersion = getIntAttribute(parser, ATTRIBUTE_UPDATE_APP_VERSION);
-            int dataAppVersion = getIntAttribute(parser, ATTRIBUTE_DATA_APP_VERSION);
-            return new PackageStatus(checkStatus,
-                    new PackageVersions(updateAppVersion, dataAppVersion));
-        } catch (IOException e) {
-            ParseException e2 = new ParseException("Error reading package status", 0);
-            e2.initCause(e);
-            throw e2;
-        }
-    }
-
-    @GuardedBy("this")
-    private int recoverFromBadData(Exception cause) {
-        mPackageStatusFile.delete();
-        try {
-            return insertInitialPackageStatus();
-        } catch (IOException e) {
-            IllegalStateException fatal = new IllegalStateException(e);
-            fatal.addSuppressed(cause);
-            throw fatal;
-        }
-    }
-
-    /** Insert the initial data, returning the optimistic lock ID */
-    private int insertInitialPackageStatus() throws IOException {
-        // Doesn't matter what it is, but we avoid the obvious starting value each time the data
-        // is reset to ensure that old tokens are unlikely to work.
-        final int initialOptimisticLockId = (int) System.currentTimeMillis();
-
-        writePackageStatusLocked(null /* status */, initialOptimisticLockId,
-                null /* packageVersions */);
-        return initialOptimisticLockId;
-    }
-
-    /**
-     * Generate a new {@link CheckToken} that can be passed to the time zone rules update
-     * application.
-     */
-    CheckToken generateCheckToken(PackageVersions currentInstalledVersions) {
-        if (currentInstalledVersions == null) {
-            throw new NullPointerException("currentInstalledVersions == null");
-        }
-
-        synchronized (this) {
-            int optimisticLockId;
-            try {
-                optimisticLockId = getCurrentOptimisticLockId();
-            } catch (ParseException e) {
-                Slog.w(LOG_TAG, "Unable to find optimistic lock ID from package status");
-
-                // Recover.
-                optimisticLockId = recoverFromBadData(e);
-            }
-
-            int newOptimisticLockId = optimisticLockId + 1;
-            try {
-                boolean statusUpdated = writePackageStatusWithOptimisticLockCheck(
-                        optimisticLockId, newOptimisticLockId, CHECK_STARTED,
-                        currentInstalledVersions);
-                if (!statusUpdated) {
-                    throw new IllegalStateException("Unable to update status to CHECK_STARTED."
-                            + " synchronization failure?");
-                }
-                return new CheckToken(newOptimisticLockId, currentInstalledVersions);
-            } catch (IOException e) {
-                throw new IllegalStateException(e);
-            }
-        }
-    }
-
-    /**
-     * Reset the current device state to "unknown".
-     */
-    void resetCheckState() {
-        synchronized(this) {
-            int optimisticLockId;
-            try {
-                optimisticLockId = getCurrentOptimisticLockId();
-            } catch (ParseException e) {
-                Slog.w(LOG_TAG, "resetCheckState: Unable to find optimistic lock ID from package"
-                        + " status");
-                // Attempt to recover the storage state.
-                optimisticLockId = recoverFromBadData(e);
-            }
-
-            int newOptimisticLockId = optimisticLockId + 1;
-            try {
-                if (!writePackageStatusWithOptimisticLockCheck(optimisticLockId,
-                        newOptimisticLockId, null /* status */, null /* packageVersions */)) {
-                    throw new IllegalStateException("resetCheckState: Unable to reset package"
-                            + " status, newOptimisticLockId=" + newOptimisticLockId);
-                }
-            } catch (IOException e) {
-                throw new IllegalStateException(e);
-            }
-        }
-    }
-
-    /**
-     * Update the current device state if possible. Returns true if the update was successful.
-     * {@code false} indicates the storage has been changed since the {@link CheckToken} was
-     * generated and the update was discarded.
-     */
-    boolean markChecked(CheckToken checkToken, boolean succeeded) {
-        synchronized (this) {
-            int optimisticLockId = checkToken.mOptimisticLockId;
-            int newOptimisticLockId = optimisticLockId + 1;
-            int status = succeeded ? CHECK_COMPLETED_SUCCESS : CHECK_COMPLETED_FAILURE;
-            try {
-                return writePackageStatusWithOptimisticLockCheck(optimisticLockId,
-                        newOptimisticLockId, status, checkToken.mPackageVersions);
-            } catch (IOException e) {
-                throw new IllegalStateException(e);
-            }
-        }
-    }
-
-    @GuardedBy("this")
-    private int getCurrentOptimisticLockId() throws ParseException {
-        try (FileInputStream fis = mPackageStatusFile.openRead()) {
-            TypedXmlPullParser parser = parseToPackageStatusTag(fis);
-            return getIntAttribute(parser, ATTRIBUTE_OPTIMISTIC_LOCK_ID);
-        } catch (IOException e) {
-            ParseException e2 = new ParseException("Unable to read file", 0);
-            e2.initCause(e);
-            throw e2;
-        }
-    }
-
-    /** Returns a parser or throws ParseException, never returns null. */
-    private static TypedXmlPullParser parseToPackageStatusTag(FileInputStream fis)
-            throws ParseException {
-        try {
-            TypedXmlPullParser parser = Xml.resolvePullParser(fis);
-            int type;
-            while ((type = parser.next()) != END_DOCUMENT) {
-                final String tag = parser.getName();
-                if (type == START_TAG && TAG_PACKAGE_STATUS.equals(tag)) {
-                    return parser;
-                }
-            }
-            throw new ParseException("Unable to find " + TAG_PACKAGE_STATUS + " tag", 0);
-        } catch (XmlPullParserException e) {
-            throw new IllegalStateException("Unable to configure parser", e);
-        } catch (IOException e) {
-            ParseException e2 = new ParseException("Error reading XML", 0);
-            e.initCause(e);
-            throw e2;
-        }
-    }
-
-    @GuardedBy("this")
-    private boolean writePackageStatusWithOptimisticLockCheck(int optimisticLockId,
-            int newOptimisticLockId, Integer status, PackageVersions packageVersions)
-            throws IOException {
-
-        int currentOptimisticLockId;
-        try {
-            currentOptimisticLockId = getCurrentOptimisticLockId();
-            if (currentOptimisticLockId != optimisticLockId) {
-                return false;
-            }
-        } catch (ParseException e) {
-            recoverFromBadData(e);
-            return false;
-        }
-
-        writePackageStatusLocked(status, newOptimisticLockId, packageVersions);
-        return true;
-    }
-
-    @GuardedBy("this")
-    private void writePackageStatusLocked(Integer status, int optimisticLockId,
-            PackageVersions packageVersions) throws IOException {
-        if ((status == null) != (packageVersions == null)) {
-            throw new IllegalArgumentException(
-                    "Provide both status and packageVersions, or neither.");
-        }
-
-        FileOutputStream fos = null;
-        try {
-            fos = mPackageStatusFile.startWrite();
-            TypedXmlSerializer serializer = Xml.resolveSerializer(fos);
-            serializer.startDocument(null /* encoding */, true /* standalone */);
-            final String namespace = null;
-            serializer.startTag(namespace, TAG_PACKAGE_STATUS);
-            String statusAttributeValue = status == null ? "" : Integer.toString(status);
-            serializer.attribute(namespace, ATTRIBUTE_CHECK_STATUS, statusAttributeValue);
-            serializer.attribute(namespace, ATTRIBUTE_OPTIMISTIC_LOCK_ID,
-                    Integer.toString(optimisticLockId));
-            long updateAppVersion = status == null
-                    ? UNKNOWN_PACKAGE_VERSION : packageVersions.mUpdateAppVersion;
-            serializer.attribute(namespace, ATTRIBUTE_UPDATE_APP_VERSION,
-                    Long.toString(updateAppVersion));
-            long dataAppVersion = status == null
-                    ? UNKNOWN_PACKAGE_VERSION : packageVersions.mDataAppVersion;
-            serializer.attribute(namespace, ATTRIBUTE_DATA_APP_VERSION,
-                    Long.toString(dataAppVersion));
-            serializer.endTag(namespace, TAG_PACKAGE_STATUS);
-            serializer.endDocument();
-            serializer.flush();
-            mPackageStatusFile.finishWrite(fos);
-        } catch (IOException e) {
-            if (fos != null) {
-                mPackageStatusFile.failWrite(fos);
-            }
-            throw e;
-        }
-
-    }
-
-    /** Only used during tests to force a known table state. */
-    public void forceCheckStateForTests(int checkStatus, PackageVersions packageVersions)
-            throws IOException {
-        synchronized (this) {
-            try {
-                final int initialOptimisticLockId = (int) System.currentTimeMillis();
-                writePackageStatusLocked(checkStatus, initialOptimisticLockId, packageVersions);
-            } catch (IOException e) {
-                throw new IllegalStateException(e);
-            }
-        }
-    }
-
-    private static Integer getNullableIntAttribute(TypedXmlPullParser parser, String attributeName)
-            throws ParseException {
-        String attributeValue = parser.getAttributeValue(null, attributeName);
-        try {
-            if (attributeValue == null) {
-                throw new ParseException("Attribute " + attributeName + " missing", 0);
-            } else if (attributeValue.isEmpty()) {
-                return null;
-            }
-            return Integer.parseInt(attributeValue);
-        } catch (NumberFormatException e) {
-            throw new ParseException(
-                    "Bad integer for attributeName=" + attributeName + ": " + attributeValue, 0);
-        }
-    }
-
-    private static int getIntAttribute(TypedXmlPullParser parser, String attributeName)
-            throws ParseException {
-        Integer value = getNullableIntAttribute(parser, attributeName);
-        if (value == null) {
-            throw new ParseException("Missing attribute " + attributeName, 0);
-        }
-        return value;
-    }
-
-    public void dump(PrintWriter printWriter) {
-        printWriter.println("Package status: " + getPackageStatus());
-    }
-}
diff --git a/services/core/java/com/android/server/timezone/PackageTracker.java b/services/core/java/com/android/server/timezone/PackageTracker.java
deleted file mode 100644
index 8f4cada..0000000
--- a/services/core/java/com/android/server/timezone/PackageTracker.java
+++ /dev/null
@@ -1,545 +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.timezone;
-
-import com.android.internal.annotations.VisibleForTesting;
-
-import android.app.timezone.RulesUpdaterContract;
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.os.Environment;
-import android.os.FileUtils;
-import android.os.SystemClock;
-import android.provider.TimeZoneRulesDataContract;
-import android.util.Slog;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.time.Clock;
-
-/**
- * Monitors the installed applications associated with time zone updates. If the app packages are
- * updated it indicates there <em>might</em> be a time zone rules update to apply so a targeted
- * broadcast intent is used to trigger the time zone updater app.
- *
- * <p>The "update triggering" behavior of this component can be disabled via device configuration.
- *
- * <p>The package tracker listens for package updates of the time zone "updater app" and "data app".
- * It also listens for "reliability" triggers. Reliability triggers are there to ensure that the
- * package tracker handles failures reliably and are "idle maintenance" events or something similar.
- * Reliability triggers can cause a time zone update check to take place if the current state is
- * unclear. For example, it can be unclear after boot or after a failure. If there are repeated
- * failures reliability updates are halted until the next boot.
- *
- * <p>This component keeps persistent track of the most recent app packages checked to avoid
- * unnecessary expense from broadcasting intents (which will cause other app processes to spawn).
- * The current status is also stored to detect whether the most recently-generated check is
- * complete successfully. For example, if the device was interrupted while doing a check and never
- * acknowledged a check then a check will be retried the next time a "reliability trigger" event
- * happens.
- */
-// Also made non-final so it can be mocked.
-@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
-public class PackageTracker {
-    private static final String TAG = "timezone.PackageTracker";
-
-    private final PackageManagerHelper mPackageManagerHelper;
-    private final PackageTrackerIntentHelper mIntentHelper;
-    private final ConfigHelper mConfigHelper;
-    private final PackageStatusStorage mPackageStatusStorage;
-    private final Clock mElapsedRealtimeClock;
-
-    // False if tracking is disabled.
-    private boolean mTrackingEnabled;
-
-    // These fields may be null if package tracking is disabled.
-    private String mUpdateAppPackageName;
-    private String mDataAppPackageName;
-
-    // The time a triggered check is allowed to take before it is considered overdue.
-    private int mCheckTimeAllowedMillis;
-    // The number of failed checks in a row before reliability checks should stop happening.
-    private long mFailedCheckRetryCount;
-
-    /*
-     * The minimum delay between a successive reliability triggers / other operations. Should to be
-     * larger than mCheckTimeAllowedMillis to avoid reliability triggers happening during package
-     * update checks.
-     */
-    private int mDelayBeforeReliabilityCheckMillis;
-
-    // Reliability check state: If a check was triggered but not acknowledged within
-    // mCheckTimeAllowedMillis then another one can be triggered.
-    private Long mLastTriggerTimestamp = null;
-
-    // Reliability check state: Whether any checks have been triggered at all.
-    private boolean mCheckTriggered;
-
-    // Reliability check state: A count of how many failures have occurred consecutively.
-    private int mCheckFailureCount;
-
-    /** Creates the {@link PackageTracker} for normal use. */
-    static PackageTracker create(Context context) {
-        Clock elapsedRealtimeClock = SystemClock.elapsedRealtimeClock();
-        PackageTrackerHelperImpl helperImpl = new PackageTrackerHelperImpl(context);
-        File storageDir = FileUtils.createDir(Environment.getDataSystemDirectory(), "timezone");
-        return new PackageTracker(
-                elapsedRealtimeClock /* elapsedRealtimeClock */,
-                helperImpl /* configHelper */,
-                helperImpl /* packageManagerHelper */,
-                new PackageStatusStorage(storageDir),
-                new PackageTrackerIntentHelperImpl(context));
-    }
-
-    // A constructor that can be used by tests to supply mocked / faked dependencies.
-    PackageTracker(Clock elapsedRealtimeClock, ConfigHelper configHelper,
-            PackageManagerHelper packageManagerHelper, PackageStatusStorage packageStatusStorage,
-            PackageTrackerIntentHelper intentHelper) {
-        mElapsedRealtimeClock = elapsedRealtimeClock;
-        mConfigHelper = configHelper;
-        mPackageManagerHelper = packageManagerHelper;
-        mPackageStatusStorage = packageStatusStorage;
-        mIntentHelper = intentHelper;
-    }
-
-    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
-    protected synchronized boolean start() {
-        mTrackingEnabled = mConfigHelper.isTrackingEnabled();
-        if (!mTrackingEnabled) {
-            Slog.i(TAG, "Time zone updater / data package tracking explicitly disabled.");
-            return false;
-        }
-
-        mUpdateAppPackageName = mConfigHelper.getUpdateAppPackageName();
-        mDataAppPackageName = mConfigHelper.getDataAppPackageName();
-        mCheckTimeAllowedMillis = mConfigHelper.getCheckTimeAllowedMillis();
-        mFailedCheckRetryCount = mConfigHelper.getFailedCheckRetryCount();
-        mDelayBeforeReliabilityCheckMillis = mCheckTimeAllowedMillis + (60 * 1000);
-
-        // Validate the device configuration including the application packages.
-        // The manifest entries in the apps themselves are not validated until use as they can
-        // change and we don't want to prevent the system server starting due to a bad application.
-        throwIfDeviceSettingsOrAppsAreBad();
-
-        // Explicitly start in a reliability state where reliability triggering will do something.
-        mCheckTriggered = false;
-        mCheckFailureCount = 0;
-
-        // Initialize the storage, as needed.
-        try {
-            mPackageStatusStorage.initialize();
-        } catch (IOException e) {
-            Slog.w(TAG, "PackageTracker storage could not be initialized.", e);
-            return false;
-        }
-
-        // Initialize the intent helper.
-        mIntentHelper.initialize(mUpdateAppPackageName, mDataAppPackageName, this);
-
-        // Schedule a reliability trigger so we will have at least one after boot. This will allow
-        // us to catch if a package updated wasn't handled to completion. There's no hurry: it's ok
-        // to delay for a while before doing this even if idle.
-        mIntentHelper.scheduleReliabilityTrigger(mDelayBeforeReliabilityCheckMillis);
-
-        Slog.i(TAG, "Time zone updater / data package tracking enabled");
-        return true;
-    }
-
-    /**
-     * Performs checks that confirm the system image has correctly configured package
-     * tracking configuration. Only called if package tracking is enabled. Throws an exception if
-     * the device is configured badly which will prevent the device booting.
-     */
-    private void throwIfDeviceSettingsOrAppsAreBad() {
-        // None of the checks below can be based on application manifest settings, otherwise a bad
-        // update could leave the device in an unbootable state. See validateDataAppManifest() and
-        // validateUpdaterAppManifest() for softer errors.
-
-        throwRuntimeExceptionIfNullOrEmpty(
-                mUpdateAppPackageName, "Update app package name missing.");
-        throwRuntimeExceptionIfNullOrEmpty(mDataAppPackageName, "Data app package name missing.");
-        if (mFailedCheckRetryCount < 1) {
-            throw logAndThrowRuntimeException("mFailedRetryCount=" + mFailedCheckRetryCount, null);
-        }
-        if (mCheckTimeAllowedMillis < 1000) {
-            throw logAndThrowRuntimeException(
-                    "mCheckTimeAllowedMillis=" + mCheckTimeAllowedMillis, null);
-        }
-
-        // Validate the updater application package.
-        try {
-            if (!mPackageManagerHelper.isPrivilegedApp(mUpdateAppPackageName)) {
-                throw logAndThrowRuntimeException(
-                        "Update app " + mUpdateAppPackageName + " must be a priv-app.", null);
-            }
-        } catch (PackageManager.NameNotFoundException e) {
-            throw logAndThrowRuntimeException("Could not determine update app package details for "
-                    + mUpdateAppPackageName, e);
-        }
-        Slog.d(TAG, "Update app " + mUpdateAppPackageName + " is valid.");
-
-        // Validate the data application package.
-        try {
-            if (!mPackageManagerHelper.isPrivilegedApp(mDataAppPackageName)) {
-                throw logAndThrowRuntimeException(
-                        "Data app " + mDataAppPackageName + " must be a priv-app.", null);
-            }
-        } catch (PackageManager.NameNotFoundException e) {
-            throw logAndThrowRuntimeException("Could not determine data app package details for "
-                    + mDataAppPackageName, e);
-        }
-        Slog.d(TAG, "Data app " + mDataAppPackageName + " is valid.");
-    }
-
-    /**
-     * Inspects the current in-memory state, installed packages and storage state to determine if an
-     * update check is needed and then trigger if it is.
-     *
-     * @param packageChanged true if this method was called because a known packaged definitely
-     *     changed, false if the cause is a reliability trigger
-     */
-    public synchronized void triggerUpdateIfNeeded(boolean packageChanged) {
-        if (!mTrackingEnabled) {
-            throw new IllegalStateException("Unexpected call. Tracking is disabled.");
-        }
-
-        // Validate the applications' current manifest entries: make sure they are configured as
-        // they should be. These are not fatal and just means that no update is triggered: we don't
-        // want to take down the system server if an OEM or Google have pushed a bad update to
-        // an application.
-        boolean updaterAppManifestValid = validateUpdaterAppManifest();
-        boolean dataAppManifestValid = validateDataAppManifest();
-        if (!updaterAppManifestValid || !dataAppManifestValid) {
-            Slog.e(TAG, "No update triggered due to invalid application manifest entries."
-                    + " updaterApp=" + updaterAppManifestValid
-                    + ", dataApp=" + dataAppManifestValid);
-
-            // There's no point in doing any reliability triggers if the current packages are bad.
-            mIntentHelper.unscheduleReliabilityTrigger();
-            return;
-        }
-
-        if (!packageChanged) {
-            // This call was made because the device is doing a "reliability" check.
-            // 4 possible cases:
-            // 1) No check has previously triggered since restart. We want to trigger in this case.
-            // 2) A check has previously triggered and it is in progress. We want to trigger if
-            //    the response is overdue.
-            // 3) A check has previously triggered and it failed. We want to trigger, but only if
-            //    we're not in a persistent failure state.
-            // 4) A check has previously triggered and it succeeded.
-            //    We don't want to trigger, and want to stop future triggers.
-
-            if (!mCheckTriggered) {
-                // Case 1.
-                Slog.d(TAG, "triggerUpdateIfNeeded: First reliability trigger.");
-            } else if (isCheckInProgress()) {
-                // Case 2.
-                if (!isCheckResponseOverdue()) {
-                    // A check is in progress but hasn't been given time to succeed.
-                    Slog.d(TAG,
-                            "triggerUpdateIfNeeded: checkComplete call is not yet overdue."
-                                    + " Not triggering.");
-                    // Don't do any work now but we do schedule a future reliability trigger.
-                    mIntentHelper.scheduleReliabilityTrigger(mDelayBeforeReliabilityCheckMillis);
-                    return;
-                }
-            } else if (mCheckFailureCount > mFailedCheckRetryCount) {
-                // Case 3. If the system is in some kind of persistent failure state we don't want
-                // to keep checking, so just stop.
-                Slog.i(TAG, "triggerUpdateIfNeeded: number of allowed consecutive check failures"
-                        + " exceeded. Stopping reliability triggers until next reboot or package"
-                        + " update.");
-                mIntentHelper.unscheduleReliabilityTrigger();
-                return;
-            } else if (mCheckFailureCount == 0) {
-                // Case 4.
-                Slog.i(TAG, "triggerUpdateIfNeeded: No reliability check required. Last check was"
-                        + " successful.");
-                mIntentHelper.unscheduleReliabilityTrigger();
-                return;
-            }
-        }
-
-        // Read the currently installed data / updater package versions.
-        PackageVersions currentInstalledVersions = lookupInstalledPackageVersions();
-        if (currentInstalledVersions == null) {
-            // This should not happen if the device is configured in a valid way.
-            Slog.e(TAG, "triggerUpdateIfNeeded: currentInstalledVersions was null");
-            mIntentHelper.unscheduleReliabilityTrigger();
-            return;
-        }
-
-        // Establish the current state using package manager and stored state. Determine if we have
-        // already successfully checked the installed versions.
-        PackageStatus packageStatus = mPackageStatusStorage.getPackageStatus();
-        if (packageStatus == null) {
-            // This can imply corrupt, uninitialized storage state (e.g. first check ever on a
-            // device) or after some kind of reset.
-            Slog.i(TAG, "triggerUpdateIfNeeded: No package status data found. Data check needed.");
-        } else if (!packageStatus.mVersions.equals(currentInstalledVersions)) {
-            // The stored package version information differs from the installed version.
-            // Trigger the check in all cases.
-            Slog.i(TAG, "triggerUpdateIfNeeded: Stored package versions="
-                    + packageStatus.mVersions + ", do not match current package versions="
-                    + currentInstalledVersions + ". Triggering check.");
-        } else {
-            Slog.i(TAG, "triggerUpdateIfNeeded: Stored package versions match currently"
-                    + " installed versions, currentInstalledVersions=" + currentInstalledVersions
-                    + ", packageStatus.mCheckStatus=" + packageStatus.mCheckStatus);
-            if (packageStatus.mCheckStatus == PackageStatus.CHECK_COMPLETED_SUCCESS) {
-                // The last check succeeded and nothing has changed. Do nothing and disable
-                // reliability checks.
-                Slog.i(TAG, "triggerUpdateIfNeeded: Prior check succeeded. No need to trigger.");
-                mIntentHelper.unscheduleReliabilityTrigger();
-                return;
-            }
-        }
-
-        // Generate a token to send to the updater app.
-        CheckToken checkToken =
-                mPackageStatusStorage.generateCheckToken(currentInstalledVersions);
-        if (checkToken == null) {
-            Slog.w(TAG, "triggerUpdateIfNeeded: Unable to generate check token."
-                    + " Not sending check request.");
-            // Trigger again later: perhaps we'll have better luck.
-            mIntentHelper.scheduleReliabilityTrigger(mDelayBeforeReliabilityCheckMillis);
-            return;
-        }
-
-        // Trigger the update check.
-        mIntentHelper.sendTriggerUpdateCheck(checkToken);
-        mCheckTriggered = true;
-
-        // Update the reliability check state in case the update fails.
-        setCheckInProgress();
-
-        // Schedule a reliability trigger in case the update check doesn't succeed and there is no
-        // response at all. It will be cancelled if the check is successful in recordCheckResult.
-        mIntentHelper.scheduleReliabilityTrigger(mDelayBeforeReliabilityCheckMillis);
-    }
-
-    /**
-     * Used to record the result of a check. Can be called even if active package tracking is
-     * disabled.
-     */
-    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
-    protected synchronized void recordCheckResult(CheckToken checkToken, boolean success) {
-        Slog.i(TAG, "recordOperationResult: checkToken=" + checkToken + " success=" + success);
-
-        // If package tracking is disabled it means no record-keeping is required. However, we do
-        // want to clear out any stored state to make it clear that the current state is unknown and
-        // should tracking become enabled again (perhaps through an OTA) we'd need to perform an
-        // update check.
-        if (!mTrackingEnabled) {
-            // This means an updater has spontaneously modified time zone data without having been
-            // triggered. This can happen if the OEM is handling their own updates, but we don't
-            // need to do any tracking in this case.
-
-            if (checkToken == null) {
-                // This is the expected case if tracking is disabled but an OEM is handling time
-                // zone installs using their own mechanism.
-                Slog.d(TAG, "recordCheckResult: Tracking is disabled and no token has been"
-                        + " provided. Resetting tracking state.");
-            } else {
-                // This is unexpected. If tracking is disabled then no check token should have been
-                // generated by the package tracker. An updater should never create its own token.
-                // This could be a bug in the updater.
-                Slog.w(TAG, "recordCheckResult: Tracking is disabled and a token " + checkToken
-                        + " has been unexpectedly provided. Resetting tracking state.");
-            }
-            mPackageStatusStorage.resetCheckState();
-            return;
-        }
-
-        if (checkToken == null) {
-            /*
-             * If the checkToken is null it suggests an install / uninstall / acknowledgement has
-             * occurred without a prior trigger (or the client didn't return the token it was given
-             * for some reason, perhaps a bug).
-             *
-             * This shouldn't happen under normal circumstances:
-             *
-             * If package tracking is enabled, we assume it is the package tracker responsible for
-             * triggering updates and a token should have been produced and returned.
-             *
-             * If the OEM is handling time zone updates case package tracking should be disabled.
-             *
-             * This could happen in tests. The device should recover back to a known state by
-             * itself rather than be left in an invalid state.
-             *
-             * We treat this as putting the device into an unknown state and make sure that
-             * reliability triggering is enabled so we should recover.
-             */
-            Slog.i(TAG, "recordCheckResult: Unexpectedly missing checkToken, resetting"
-                    + " storage state.");
-            mPackageStatusStorage.resetCheckState();
-
-            // Schedule a reliability trigger and reset the failure count so we know that the
-            // next reliability trigger will do something.
-            mIntentHelper.scheduleReliabilityTrigger(mDelayBeforeReliabilityCheckMillis);
-            mCheckFailureCount = 0;
-        } else {
-            // This is the expected case when tracking is enabled: a check was triggered and it has
-            // completed.
-            boolean recordedCheckCompleteSuccessfully =
-                    mPackageStatusStorage.markChecked(checkToken, success);
-            if (recordedCheckCompleteSuccessfully) {
-                // If we have recorded the result (whatever it was) we know there is no check in
-                // progress.
-                setCheckComplete();
-
-                if (success) {
-                    // Since the check was successful, no reliability trigger is required until
-                    // there is a package change.
-                    mIntentHelper.unscheduleReliabilityTrigger();
-                    mCheckFailureCount = 0;
-                } else {
-                    // Enable schedule a reliability trigger to check again in future.
-                    mIntentHelper.scheduleReliabilityTrigger(mDelayBeforeReliabilityCheckMillis);
-                    mCheckFailureCount++;
-                }
-            } else {
-                // The failure to record the check means an optimistic lock failure and suggests
-                // that another check was triggered after the token was generated.
-                Slog.i(TAG, "recordCheckResult: could not update token=" + checkToken
-                        + " with success=" + success + ". Optimistic lock failure");
-
-                // Schedule a reliability trigger to potentially try again in future.
-                mIntentHelper.scheduleReliabilityTrigger(mDelayBeforeReliabilityCheckMillis);
-                mCheckFailureCount++;
-            }
-        }
-    }
-
-    /** Access to consecutive failure counts for use in tests. */
-    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
-    protected int getCheckFailureCountForTests() {
-        return mCheckFailureCount;
-    }
-
-    private void setCheckInProgress() {
-        mLastTriggerTimestamp = mElapsedRealtimeClock.millis();
-    }
-
-    private void setCheckComplete() {
-        mLastTriggerTimestamp = null;
-    }
-
-    private boolean isCheckInProgress() {
-        return mLastTriggerTimestamp != null;
-    }
-
-    private boolean isCheckResponseOverdue() {
-        if (mLastTriggerTimestamp == null) {
-            return false;
-        }
-        // Risk of overflow, but highly unlikely given the implementation and not problematic.
-        return mElapsedRealtimeClock.millis() > mLastTriggerTimestamp + mCheckTimeAllowedMillis;
-    }
-
-    private PackageVersions lookupInstalledPackageVersions() {
-        long updatePackageVersion;
-        long dataPackageVersion;
-        try {
-            updatePackageVersion =
-                    mPackageManagerHelper.getInstalledPackageVersion(mUpdateAppPackageName);
-            dataPackageVersion =
-                    mPackageManagerHelper.getInstalledPackageVersion(mDataAppPackageName);
-        } catch (PackageManager.NameNotFoundException e) {
-            Slog.w(TAG, "lookupInstalledPackageVersions: Unable to resolve installed package"
-                    + " versions", e);
-            return null;
-        }
-        return new PackageVersions(updatePackageVersion, dataPackageVersion);
-    }
-
-    private boolean validateDataAppManifest() {
-        // We only want to talk to a provider that exposed by the known data app package
-        // so we look up the providers exposed by that app and check the well-known authority is
-        // there. This prevents the case where *even if* the data app doesn't expose the provider
-        // required, another app cannot expose one to replace it.
-        if (!mPackageManagerHelper.contentProviderRegistered(
-                TimeZoneRulesDataContract.AUTHORITY, mDataAppPackageName)) {
-            // Error! Found the package but it didn't expose the correct provider.
-            Slog.w(TAG, "validateDataAppManifest: Data app " + mDataAppPackageName
-                    + " does not expose the required provider with authority="
-                    + TimeZoneRulesDataContract.AUTHORITY);
-            return false;
-        }
-        return true;
-    }
-
-    private boolean validateUpdaterAppManifest() {
-        try {
-            // The updater app is expected to have the UPDATE_TIME_ZONE_RULES permission.
-            // The updater app is expected to have a receiver for the intent we are going to trigger
-            // and require the TRIGGER_TIME_ZONE_RULES_CHECK.
-            if (!mPackageManagerHelper.usesPermission(
-                    mUpdateAppPackageName,
-                    RulesUpdaterContract.UPDATE_TIME_ZONE_RULES_PERMISSION)) {
-                Slog.w(TAG, "validateUpdaterAppManifest: Updater app " + mDataAppPackageName
-                        + " does not use permission="
-                        + RulesUpdaterContract.UPDATE_TIME_ZONE_RULES_PERMISSION);
-                return false;
-            }
-            if (!mPackageManagerHelper.receiverRegistered(
-                    RulesUpdaterContract.createUpdaterIntent(mUpdateAppPackageName),
-                    RulesUpdaterContract.TRIGGER_TIME_ZONE_RULES_CHECK_PERMISSION)) {
-                return false;
-            }
-
-            return true;
-        } catch (PackageManager.NameNotFoundException e) {
-            Slog.w(TAG, "validateUpdaterAppManifest: Updater app " + mDataAppPackageName
-                    + " does not expose the required broadcast receiver.", e);
-            return false;
-        }
-    }
-
-    private static void throwRuntimeExceptionIfNullOrEmpty(String value, String message) {
-        if (value == null || value.trim().isEmpty()) {
-            throw logAndThrowRuntimeException(message, null);
-        }
-    }
-
-    private static RuntimeException logAndThrowRuntimeException(String message, Throwable cause) {
-        Slog.wtf(TAG, message, cause);
-        throw new RuntimeException(message, cause);
-    }
-
-    public void dump(PrintWriter fout) {
-        fout.println("PackageTrackerState: " + toString());
-        mPackageStatusStorage.dump(fout);
-    }
-
-    @Override
-    public String toString() {
-        return "PackageTracker{" +
-                "mTrackingEnabled=" + mTrackingEnabled +
-                ", mUpdateAppPackageName='" + mUpdateAppPackageName + '\'' +
-                ", mDataAppPackageName='" + mDataAppPackageName + '\'' +
-                ", mCheckTimeAllowedMillis=" + mCheckTimeAllowedMillis +
-                ", mDelayBeforeReliabilityCheckMillis=" + mDelayBeforeReliabilityCheckMillis +
-                ", mFailedCheckRetryCount=" + mFailedCheckRetryCount +
-                ", mLastTriggerTimestamp=" + mLastTriggerTimestamp +
-                ", mCheckTriggered=" + mCheckTriggered +
-                ", mCheckFailureCount=" + mCheckFailureCount +
-                '}';
-    }
-}
diff --git a/services/core/java/com/android/server/timezone/PackageTrackerHelperImpl.java b/services/core/java/com/android/server/timezone/PackageTrackerHelperImpl.java
deleted file mode 100644
index 5f90be1..0000000
--- a/services/core/java/com/android/server/timezone/PackageTrackerHelperImpl.java
+++ /dev/null
@@ -1,148 +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.timezone;
-
-import com.android.internal.R;
-
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.ProviderInfo;
-import android.content.pm.ResolveInfo;
-import android.content.res.Resources;
-import android.os.UserHandle;
-import android.util.Slog;
-
-import java.util.List;
-
-/**
- * A single class that implements multiple helper interfaces for use by {@link PackageTracker}.
- */
-final class PackageTrackerHelperImpl implements ConfigHelper, PackageManagerHelper {
-
-    private static final String TAG = "PackageTrackerHelperImpl";
-
-    private final Context mContext;
-    private final PackageManager mPackageManager;
-
-    PackageTrackerHelperImpl(Context context) {
-        mContext = context;
-        mPackageManager = context.getPackageManager();
-    }
-
-    @Override
-    public boolean isTrackingEnabled() {
-        return mContext.getResources().getBoolean(R.bool.config_timeZoneRulesUpdateTrackingEnabled);
-    }
-
-    @Override
-    public String getUpdateAppPackageName() {
-        return mContext.getResources().getString(R.string.config_timeZoneRulesUpdaterPackage);
-    }
-
-    @Override
-    public String getDataAppPackageName() {
-        Resources resources = mContext.getResources();
-        return resources.getString(R.string.config_timeZoneRulesDataPackage);
-    }
-
-    @Override
-    public int getCheckTimeAllowedMillis() {
-        return mContext.getResources().getInteger(
-                R.integer.config_timeZoneRulesCheckTimeMillisAllowed);
-    }
-
-    @Override
-    public int getFailedCheckRetryCount() {
-        return mContext.getResources().getInteger(R.integer.config_timeZoneRulesCheckRetryCount);
-    }
-
-    @Override
-    public long getInstalledPackageVersion(String packageName)
-            throws PackageManager.NameNotFoundException {
-        int flags = PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS;
-        PackageInfo packageInfo = mPackageManager.getPackageInfo(packageName, flags);
-        return packageInfo.getLongVersionCode();
-    }
-
-    @Override
-    public boolean isPrivilegedApp(String packageName) throws PackageManager.NameNotFoundException {
-        int flags = PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS;
-        PackageInfo packageInfo = mPackageManager.getPackageInfo(packageName, flags);
-        return packageInfo.applicationInfo.isPrivilegedApp();
-    }
-
-    @Override
-    public boolean usesPermission(String packageName, String requiredPermissionName)
-            throws PackageManager.NameNotFoundException {
-        int flags = PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS
-                | PackageManager.GET_PERMISSIONS;
-        PackageInfo packageInfo = mPackageManager.getPackageInfo(packageName, flags);
-        if (packageInfo.requestedPermissions == null) {
-            return false;
-        }
-        for (String requestedPermission : packageInfo.requestedPermissions) {
-            if (requiredPermissionName.equals(requestedPermission)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    @Override
-    public boolean contentProviderRegistered(String authority, String requiredPackageName) {
-        int flags = PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS;
-        ProviderInfo providerInfo = mPackageManager.resolveContentProviderAsUser(
-                authority, flags, UserHandle.SYSTEM.getIdentifier());
-        if (providerInfo == null) {
-            Slog.i(TAG, "contentProviderRegistered: No content provider registered with authority="
-                    + authority);
-            return false;
-        }
-        boolean packageMatches =
-                requiredPackageName.equals(providerInfo.applicationInfo.packageName);
-        if (!packageMatches) {
-            Slog.i(TAG, "contentProviderRegistered: App with packageName=" + requiredPackageName
-                    + " does not expose the a content provider with authority=" + authority);
-            return false;
-        }
-        return true;
-    }
-
-    @Override
-    public boolean receiverRegistered(Intent intent, String requiredPermissionName)
-            throws PackageManager.NameNotFoundException {
-
-        int flags = PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS;
-        List<ResolveInfo> resolveInfo = mPackageManager.queryBroadcastReceiversAsUser(
-                intent, flags, UserHandle.SYSTEM);
-        if (resolveInfo.size() != 1) {
-            Slog.i(TAG, "receiverRegistered: Zero or multiple broadcast receiver registered for"
-                    + " intent=" + intent + ", found=" + resolveInfo);
-            return false;
-        }
-
-        ResolveInfo matched = resolveInfo.get(0);
-        boolean requiresPermission = requiredPermissionName.equals(matched.activityInfo.permission);
-        if (!requiresPermission) {
-            Slog.i(TAG, "receiverRegistered: Broadcast receiver registered for intent="
-                    + intent + " must require permission " + requiredPermissionName);
-        }
-        return requiresPermission;
-    }
-}
diff --git a/services/core/java/com/android/server/timezone/PackageTrackerIntentHelper.java b/services/core/java/com/android/server/timezone/PackageTrackerIntentHelper.java
deleted file mode 100644
index 3753ece..0000000
--- a/services/core/java/com/android/server/timezone/PackageTrackerIntentHelper.java
+++ /dev/null
@@ -1,44 +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.timezone;
-
-/**
- * An easy-to-mock interface around intent sending / receiving for use by {@link PackageTracker};
- * it is not possible to test various cases with the real one because of the need to simulate
- * receiving and broadcasting intents.
- */
-interface PackageTrackerIntentHelper {
-
-    void initialize(String updateAppPackageName, String dataAppPackageName,
-            PackageTracker packageTracker);
-
-    void sendTriggerUpdateCheck(CheckToken checkToken);
-
-    /**
-     * Schedule a "reliability trigger" after at least minimumDelayMillis, replacing any existing
-     * scheduled one. A reliability trigger ensures that the {@link PackageTracker} can pick up
-     * reliably if a previous update check did not complete for some reason. It can happen when
-     * the device is idle. The trigger is expected to call
-     * {@link PackageTracker#triggerUpdateIfNeeded(boolean)} with a {@code false} value.
-     */
-    void scheduleReliabilityTrigger(long minimumDelayMillis);
-
-    /**
-     * Make sure there is no reliability trigger scheduled. No-op if there wasn't one.
-     */
-    void unscheduleReliabilityTrigger();
-}
diff --git a/services/core/java/com/android/server/timezone/PackageTrackerIntentHelperImpl.java b/services/core/java/com/android/server/timezone/PackageTrackerIntentHelperImpl.java
deleted file mode 100644
index 4110d88..0000000
--- a/services/core/java/com/android/server/timezone/PackageTrackerIntentHelperImpl.java
+++ /dev/null
@@ -1,116 +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.timezone;
-
-import com.android.server.EventLogTags;
-
-import android.app.timezone.RulesUpdaterContract;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.os.PatternMatcher;
-import android.os.UserHandle;
-import android.util.Slog;
-
-/**
- * The bona fide implementation of {@link PackageTrackerIntentHelper}.
- */
-final class PackageTrackerIntentHelperImpl implements PackageTrackerIntentHelper {
-
-    private final static String TAG = "timezone.PackageTrackerIntentHelperImpl";
-
-    private final Context mContext;
-    private String mUpdaterAppPackageName;
-
-    PackageTrackerIntentHelperImpl(Context context) {
-        mContext = context;
-    }
-
-    @Override
-    public void initialize(String updaterAppPackageName, String dataAppPackageName,
-            PackageTracker packageTracker) {
-        mUpdaterAppPackageName = updaterAppPackageName;
-
-        // Register for events of interest.
-
-        // The intent filter that triggers when package update events happen that indicate there may
-        // be work to do.
-        IntentFilter packageIntentFilter = new IntentFilter();
-
-        packageIntentFilter.addDataScheme("package");
-        packageIntentFilter.addDataSchemeSpecificPart(
-                updaterAppPackageName, PatternMatcher.PATTERN_LITERAL);
-        packageIntentFilter.addDataSchemeSpecificPart(
-                dataAppPackageName, PatternMatcher.PATTERN_LITERAL);
-
-        // ACTION_PACKAGE_ADDED is fired when a package is upgraded or downgraded (in addition to
-        // ACTION_PACKAGE_REMOVED and ACTION_PACKAGE_REPLACED). A system/priv-app can never be
-        // removed entirely so we do not need to trigger on ACTION_PACKAGE_REMOVED or
-        // ACTION_PACKAGE_FULLY_REMOVED.
-        packageIntentFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
-
-        // ACTION_PACKAGE_CHANGED is used when a package is disabled / re-enabled. It is not
-        // strictly necessary to trigger on this but it won't hurt anything and may catch some cases
-        // where a package has changed while disabled.
-        // Note: ACTION_PACKAGE_CHANGED is not fired when updating a suspended app, but
-        // ACTION_PACKAGE_ADDED, ACTION_PACKAGE_REMOVED and ACTION_PACKAGE_REPLACED are (and the app
-        // is left in an unsuspended state after this).
-        packageIntentFilter.addAction(Intent.ACTION_PACKAGE_CHANGED);
-
-        // We do not register for ACTION_PACKAGE_RESTARTED because it doesn't imply an update.
-        // We do not register for ACTION_PACKAGE_DATA_CLEARED because the updater / data apps are
-        // not expected to need local data.
-
-        Receiver packageUpdateReceiver = new Receiver(packageTracker);
-        mContext.registerReceiverAsUser(
-                packageUpdateReceiver, UserHandle.SYSTEM, packageIntentFilter,
-                null /* broadcastPermission */, null /* default handler */);
-    }
-
-    /** Sends an intent to trigger an update check. */
-    @Override
-    public void sendTriggerUpdateCheck(CheckToken checkToken) {
-        RulesUpdaterContract.sendBroadcast(
-                mContext, mUpdaterAppPackageName, checkToken.toByteArray());
-        EventLogTags.writeTimezoneTriggerCheck(checkToken.toString());
-    }
-
-    @Override
-    public synchronized void scheduleReliabilityTrigger(long minimumDelayMillis) {
-        TimeZoneUpdateIdler.schedule(mContext, minimumDelayMillis);
-    }
-
-    @Override
-    public synchronized void unscheduleReliabilityTrigger() {
-        TimeZoneUpdateIdler.unschedule(mContext);
-    }
-
-    private static class Receiver extends BroadcastReceiver {
-        private final PackageTracker mPackageTracker;
-
-        private Receiver(PackageTracker packageTracker) {
-            mPackageTracker = packageTracker;
-        }
-
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            Slog.d(TAG, "Received intent: " + intent.toString());
-            mPackageTracker.triggerUpdateIfNeeded(true /* packageChanged */);
-        }
-    }
-}
diff --git a/services/core/java/com/android/server/timezone/PackageVersions.java b/services/core/java/com/android/server/timezone/PackageVersions.java
deleted file mode 100644
index 0084c1a..0000000
--- a/services/core/java/com/android/server/timezone/PackageVersions.java
+++ /dev/null
@@ -1,63 +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.timezone;
-
-/**
- * Package version information about the time zone updater and time zone data application packages.
- */
-final class PackageVersions {
-
-    final long mUpdateAppVersion;
-    final long mDataAppVersion;
-
-    PackageVersions(long updateAppVersion, long dataAppVersion) {
-        this.mUpdateAppVersion = updateAppVersion;
-        this.mDataAppVersion = dataAppVersion;
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) {
-            return true;
-        }
-        if (o == null || getClass() != o.getClass()) {
-            return false;
-        }
-
-        PackageVersions that = (PackageVersions) o;
-
-        if (mUpdateAppVersion != that.mUpdateAppVersion) {
-            return false;
-        }
-        return mDataAppVersion == that.mDataAppVersion;
-    }
-
-    @Override
-    public int hashCode() {
-        int result = Long.hashCode(mUpdateAppVersion);
-        result = 31 * result + Long.hashCode(mDataAppVersion);
-        return result;
-    }
-
-    @Override
-    public String toString() {
-        return "PackageVersions{" +
-                "mUpdateAppVersion=" + mUpdateAppVersion +
-                ", mDataAppVersion=" + mDataAppVersion +
-                '}';
-    }
-}
diff --git a/services/core/java/com/android/server/timezone/PermissionHelper.java b/services/core/java/com/android/server/timezone/PermissionHelper.java
deleted file mode 100644
index 2ec31e2..0000000
--- a/services/core/java/com/android/server/timezone/PermissionHelper.java
+++ /dev/null
@@ -1,29 +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.timezone;
-
-import java.io.PrintWriter;
-
-/**
- * An easy-to-mock interface around permission checks for use by {@link RulesManagerService}.
- */
-public interface PermissionHelper {
-
-    void enforceCallerHasPermission(String requiredPermission) throws SecurityException;
-
-    boolean checkDumpPermission(String tag, PrintWriter printWriter);
-}
diff --git a/services/core/java/com/android/server/timezone/RulesManagerIntentHelper.java b/services/core/java/com/android/server/timezone/RulesManagerIntentHelper.java
deleted file mode 100644
index bb317cf..0000000
--- a/services/core/java/com/android/server/timezone/RulesManagerIntentHelper.java
+++ /dev/null
@@ -1,35 +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.timezone;
-
-/**
- * An easy-to-mock interface around intent sending / receiving for use by
- * {@link RulesManagerService}; it is not possible to test various cases with the real one because
- * of the need to simulate broadcasting intents.
- */
-interface RulesManagerIntentHelper {
-
-    /**
-     * Send a broadcast informing listeners that a time zone operation is staged.
-     */
-    void sendTimeZoneOperationStaged();
-
-    /**
-     * Send a broadcast informing listeners that a time zone operation is no longer staged.
-     */
-    void sendTimeZoneOperationUnstaged();
-}
diff --git a/services/core/java/com/android/server/timezone/RulesManagerService.java b/services/core/java/com/android/server/timezone/RulesManagerService.java
deleted file mode 100644
index fd5c6e9..0000000
--- a/services/core/java/com/android/server/timezone/RulesManagerService.java
+++ /dev/null
@@ -1,602 +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.timezone;
-
-import static android.app.timezone.RulesState.DISTRO_STATUS_INSTALLED;
-import static android.app.timezone.RulesState.DISTRO_STATUS_NONE;
-import static android.app.timezone.RulesState.DISTRO_STATUS_UNKNOWN;
-import static android.app.timezone.RulesState.STAGED_OPERATION_INSTALL;
-import static android.app.timezone.RulesState.STAGED_OPERATION_NONE;
-import static android.app.timezone.RulesState.STAGED_OPERATION_UNINSTALL;
-import static android.app.timezone.RulesState.STAGED_OPERATION_UNKNOWN;
-
-import android.app.timezone.Callback;
-import android.app.timezone.DistroFormatVersion;
-import android.app.timezone.DistroRulesVersion;
-import android.app.timezone.ICallback;
-import android.app.timezone.IRulesManager;
-import android.app.timezone.RulesManager;
-import android.app.timezone.RulesState;
-import android.content.Context;
-import android.icu.util.TimeZone;
-import android.os.ParcelFileDescriptor;
-import android.os.RemoteException;
-import android.util.Slog;
-
-import com.android.i18n.timezone.TimeZoneDataFiles;
-import com.android.i18n.timezone.TimeZoneFinder;
-import com.android.i18n.timezone.TzDataSetVersion;
-import com.android.i18n.timezone.ZoneInfoDb;
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.server.EventLogTags;
-import com.android.server.SystemService;
-import com.android.timezone.distro.DistroException;
-import com.android.timezone.distro.DistroVersion;
-import com.android.timezone.distro.StagedDistroOperation;
-import com.android.timezone.distro.TimeZoneDistro;
-import com.android.timezone.distro.installer.TimeZoneDistroInstaller;
-
-
-import java.io.File;
-import java.io.FileDescriptor;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.PrintWriter;
-import java.util.Arrays;
-import java.util.concurrent.Executor;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-public final class RulesManagerService extends IRulesManager.Stub {
-
-    private static final String TAG = "timezone.RulesManagerService";
-
-    /** The distro format supported by this device. */
-    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
-    static final DistroFormatVersion DISTRO_FORMAT_VERSION_SUPPORTED =
-            new DistroFormatVersion(
-                    TzDataSetVersion.currentFormatMajorVersion(),
-                    TzDataSetVersion.currentFormatMinorVersion());
-
-    public static class Lifecycle extends SystemService {
-        public Lifecycle(Context context) {
-            super(context);
-        }
-
-        @Override
-        public void onStart() {
-            RulesManagerService service = RulesManagerService.create(getContext());
-            service.start();
-
-            // Publish the binder service so it can be accessed from other (appropriately
-            // permissioned) processes.
-            publishBinderService(Context.TIME_ZONE_RULES_MANAGER_SERVICE, service);
-
-            // Publish the service instance locally so we can use it directly from within the system
-            // server from TimeZoneUpdateIdler.
-            publishLocalService(RulesManagerService.class, service);
-        }
-    }
-
-    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
-    static final String REQUIRED_UPDATER_PERMISSION =
-            android.Manifest.permission.UPDATE_TIME_ZONE_RULES;
-    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
-    static final String REQUIRED_QUERY_PERMISSION =
-            android.Manifest.permission.QUERY_TIME_ZONE_RULES;
-
-    private final AtomicBoolean mOperationInProgress = new AtomicBoolean(false);
-    private final PermissionHelper mPermissionHelper;
-    private final PackageTracker mPackageTracker;
-    private final Executor mExecutor;
-    private final RulesManagerIntentHelper mIntentHelper;
-    private final TimeZoneDistroInstaller mInstaller;
-
-    private static RulesManagerService create(Context context) {
-        RulesManagerServiceHelperImpl helper = new RulesManagerServiceHelperImpl(context);
-        File baseVersionFile = new File(TimeZoneDataFiles.getTimeZoneModuleTzVersionFile());
-        File tzDataDir = new File(TimeZoneDataFiles.getDataTimeZoneRootDir());
-        return new RulesManagerService(
-                helper /* permissionHelper */,
-                helper /* executor */,
-                helper /* intentHelper */,
-                PackageTracker.create(context),
-                new TimeZoneDistroInstaller(TAG, baseVersionFile, tzDataDir));
-    }
-
-    // A constructor that can be used by tests to supply mocked / faked dependencies.
-    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
-    RulesManagerService(PermissionHelper permissionHelper, Executor executor,
-            RulesManagerIntentHelper intentHelper, PackageTracker packageTracker,
-            TimeZoneDistroInstaller timeZoneDistroInstaller) {
-        mPermissionHelper = permissionHelper;
-        mExecutor = executor;
-        mIntentHelper = intentHelper;
-        mPackageTracker = packageTracker;
-        mInstaller = timeZoneDistroInstaller;
-    }
-
-    public void start() {
-        // Return value deliberately ignored: no action required on failure to start.
-        mPackageTracker.start();
-    }
-
-    @Override // Binder call
-    public RulesState getRulesState() {
-        mPermissionHelper.enforceCallerHasPermission(REQUIRED_QUERY_PERMISSION);
-
-        return getRulesStateInternal();
-    }
-
-    /** Like {@link #getRulesState()} without the permission check. */
-    private RulesState getRulesStateInternal() {
-        synchronized(this) {
-            TzDataSetVersion baseVersion;
-            try {
-                baseVersion = mInstaller.readBaseVersion();
-            } catch (IOException e) {
-                Slog.w(TAG, "Failed to read base rules version", e);
-                return null;
-            }
-
-            // Determine the installed distro state. This should be possible regardless of whether
-            // there's an operation in progress.
-            DistroVersion installedDistroVersion;
-            int distroStatus = DISTRO_STATUS_UNKNOWN;
-            DistroRulesVersion installedDistroRulesVersion = null;
-            try {
-                installedDistroVersion = mInstaller.getInstalledDistroVersion();
-                if (installedDistroVersion == null) {
-                    distroStatus = DISTRO_STATUS_NONE;
-                    installedDistroRulesVersion = null;
-                } else {
-                    distroStatus = DISTRO_STATUS_INSTALLED;
-                    installedDistroRulesVersion = new DistroRulesVersion(
-                            installedDistroVersion.rulesVersion,
-                            installedDistroVersion.revision);
-                }
-            } catch (DistroException | IOException e) {
-                Slog.w(TAG, "Failed to read installed distro.", e);
-            }
-
-            boolean operationInProgress = this.mOperationInProgress.get();
-
-            // Determine the staged operation status, if possible.
-            DistroRulesVersion stagedDistroRulesVersion = null;
-            int stagedOperationStatus = STAGED_OPERATION_UNKNOWN;
-            if (!operationInProgress) {
-                StagedDistroOperation stagedDistroOperation;
-                try {
-                    stagedDistroOperation = mInstaller.getStagedDistroOperation();
-                    if (stagedDistroOperation == null) {
-                        stagedOperationStatus = STAGED_OPERATION_NONE;
-                    } else if (stagedDistroOperation.isUninstall) {
-                        stagedOperationStatus = STAGED_OPERATION_UNINSTALL;
-                    } else {
-                        // Must be an install.
-                        stagedOperationStatus = STAGED_OPERATION_INSTALL;
-                        DistroVersion stagedDistroVersion = stagedDistroOperation.distroVersion;
-                        stagedDistroRulesVersion = new DistroRulesVersion(
-                                stagedDistroVersion.rulesVersion,
-                                stagedDistroVersion.revision);
-                    }
-                } catch (DistroException | IOException e) {
-                    Slog.w(TAG, "Failed to read staged distro.", e);
-                }
-            }
-            return new RulesState(baseVersion.getRulesVersion(), DISTRO_FORMAT_VERSION_SUPPORTED,
-                    operationInProgress, stagedOperationStatus, stagedDistroRulesVersion,
-                    distroStatus, installedDistroRulesVersion);
-        }
-    }
-
-    @Override
-    public int requestInstall(ParcelFileDescriptor distroParcelFileDescriptor,
-            byte[] checkTokenBytes, ICallback callback) {
-
-        boolean closeParcelFileDescriptorOnExit = true;
-        try {
-            mPermissionHelper.enforceCallerHasPermission(REQUIRED_UPDATER_PERMISSION);
-
-            CheckToken checkToken = null;
-            if (checkTokenBytes != null) {
-                checkToken = createCheckTokenOrThrow(checkTokenBytes);
-            }
-            EventLogTags.writeTimezoneRequestInstall(toStringOrNull(checkToken));
-
-            synchronized (this) {
-                if (distroParcelFileDescriptor == null) {
-                    throw new NullPointerException("distroParcelFileDescriptor == null");
-                }
-                if (callback == null) {
-                    throw new NullPointerException("observer == null");
-                }
-                if (mOperationInProgress.get()) {
-                    return RulesManager.ERROR_OPERATION_IN_PROGRESS;
-                }
-                mOperationInProgress.set(true);
-
-                // Execute the install asynchronously.
-                mExecutor.execute(
-                        new InstallRunnable(distroParcelFileDescriptor, checkToken, callback));
-
-                // The InstallRunnable now owns the ParcelFileDescriptor, so it will close it after
-                // it executes (and we do not have to).
-                closeParcelFileDescriptorOnExit = false;
-
-                return RulesManager.SUCCESS;
-            }
-        } finally {
-            // We should close() the local ParcelFileDescriptor we were passed if it hasn't been
-            // passed to another thread to handle.
-            if (distroParcelFileDescriptor != null && closeParcelFileDescriptorOnExit) {
-                try {
-                    distroParcelFileDescriptor.close();
-                } catch (IOException e) {
-                    Slog.w(TAG, "Failed to close distroParcelFileDescriptor", e);
-                }
-            }
-        }
-    }
-
-    private class InstallRunnable implements Runnable {
-
-        private final ParcelFileDescriptor mDistroParcelFileDescriptor;
-        private final CheckToken mCheckToken;
-        private final ICallback mCallback;
-
-        InstallRunnable(ParcelFileDescriptor distroParcelFileDescriptor, CheckToken checkToken,
-                ICallback callback) {
-            mDistroParcelFileDescriptor = distroParcelFileDescriptor;
-            mCheckToken = checkToken;
-            mCallback = callback;
-        }
-
-        @Override
-        public void run() {
-            EventLogTags.writeTimezoneInstallStarted(toStringOrNull(mCheckToken));
-
-            boolean success = false;
-            // Adopt the ParcelFileDescriptor into this try-with-resources so it is closed
-            // when we are done.
-            try (ParcelFileDescriptor pfd = mDistroParcelFileDescriptor) {
-                // The ParcelFileDescriptor owns the underlying FileDescriptor and we'll close
-                // it at the end of the try-with-resources.
-                final boolean isFdOwner = false;
-                InputStream is = new FileInputStream(pfd.getFileDescriptor(), isFdOwner);
-
-                TimeZoneDistro distro = new TimeZoneDistro(is);
-                int installerResult = mInstaller.stageInstallWithErrorCode(distro);
-
-                // Notify interested parties that something is staged.
-                sendInstallNotificationIntentIfRequired(installerResult);
-
-                int resultCode = mapInstallerResultToApiCode(installerResult);
-                EventLogTags.writeTimezoneInstallComplete(toStringOrNull(mCheckToken), resultCode);
-                sendFinishedStatus(mCallback, resultCode);
-
-                // All the installer failure modes are currently non-recoverable and won't be
-                // improved by trying again. Therefore success = true.
-                success = true;
-            } catch (Exception e) {
-                Slog.w(TAG, "Failed to install distro.", e);
-                EventLogTags.writeTimezoneInstallComplete(
-                        toStringOrNull(mCheckToken), Callback.ERROR_UNKNOWN_FAILURE);
-                sendFinishedStatus(mCallback, Callback.ERROR_UNKNOWN_FAILURE);
-            } finally {
-                // Notify the package tracker that the operation is now complete.
-                mPackageTracker.recordCheckResult(mCheckToken, success);
-
-                mOperationInProgress.set(false);
-            }
-        }
-
-        private void sendInstallNotificationIntentIfRequired(int installerResult) {
-            if (installerResult == TimeZoneDistroInstaller.INSTALL_SUCCESS) {
-                mIntentHelper.sendTimeZoneOperationStaged();
-            }
-        }
-
-        private int mapInstallerResultToApiCode(int installerResult) {
-            switch (installerResult) {
-                case TimeZoneDistroInstaller.INSTALL_SUCCESS:
-                    return Callback.SUCCESS;
-                case TimeZoneDistroInstaller.INSTALL_FAIL_BAD_DISTRO_STRUCTURE:
-                    return Callback.ERROR_INSTALL_BAD_DISTRO_STRUCTURE;
-                case TimeZoneDistroInstaller.INSTALL_FAIL_RULES_TOO_OLD:
-                    return Callback.ERROR_INSTALL_RULES_TOO_OLD;
-                case TimeZoneDistroInstaller.INSTALL_FAIL_BAD_DISTRO_FORMAT_VERSION:
-                    return Callback.ERROR_INSTALL_BAD_DISTRO_FORMAT_VERSION;
-                case TimeZoneDistroInstaller.INSTALL_FAIL_VALIDATION_ERROR:
-                    return Callback.ERROR_INSTALL_VALIDATION_ERROR;
-                default:
-                    return Callback.ERROR_UNKNOWN_FAILURE;
-            }
-        }
-    }
-
-    @Override
-    public int requestUninstall(byte[] checkTokenBytes, ICallback callback) {
-        mPermissionHelper.enforceCallerHasPermission(REQUIRED_UPDATER_PERMISSION);
-
-        CheckToken checkToken = null;
-        if (checkTokenBytes != null) {
-            checkToken = createCheckTokenOrThrow(checkTokenBytes);
-        }
-        EventLogTags.writeTimezoneRequestUninstall(toStringOrNull(checkToken));
-        synchronized(this) {
-            if (callback == null) {
-                throw new NullPointerException("callback == null");
-            }
-
-            if (mOperationInProgress.get()) {
-                return RulesManager.ERROR_OPERATION_IN_PROGRESS;
-            }
-            mOperationInProgress.set(true);
-
-            // Execute the uninstall asynchronously.
-            mExecutor.execute(new UninstallRunnable(checkToken, callback));
-
-            return RulesManager.SUCCESS;
-        }
-    }
-
-    private class UninstallRunnable implements Runnable {
-
-        private final CheckToken mCheckToken;
-        private final ICallback mCallback;
-
-        UninstallRunnable(CheckToken checkToken, ICallback callback) {
-            mCheckToken = checkToken;
-            mCallback = callback;
-        }
-
-        @Override
-        public void run() {
-            EventLogTags.writeTimezoneUninstallStarted(toStringOrNull(mCheckToken));
-            boolean packageTrackerStatus = false;
-            try {
-                int uninstallResult = mInstaller.stageUninstall();
-
-                // Notify interested parties that something is staged.
-                sendUninstallNotificationIntentIfRequired(uninstallResult);
-
-                packageTrackerStatus = (uninstallResult == TimeZoneDistroInstaller.UNINSTALL_SUCCESS
-                        || uninstallResult == TimeZoneDistroInstaller.UNINSTALL_NOTHING_INSTALLED);
-
-                // Right now we just have Callback.SUCCESS / Callback.ERROR_UNKNOWN_FAILURE for
-                // uninstall. All clients should be checking against SUCCESS. More granular failures
-                // may be added in future.
-                int callbackResultCode =
-                        packageTrackerStatus ? Callback.SUCCESS : Callback.ERROR_UNKNOWN_FAILURE;
-                EventLogTags.writeTimezoneUninstallComplete(
-                        toStringOrNull(mCheckToken), callbackResultCode);
-                sendFinishedStatus(mCallback, callbackResultCode);
-            } catch (Exception e) {
-                EventLogTags.writeTimezoneUninstallComplete(
-                        toStringOrNull(mCheckToken), Callback.ERROR_UNKNOWN_FAILURE);
-                Slog.w(TAG, "Failed to uninstall distro.", e);
-                sendFinishedStatus(mCallback, Callback.ERROR_UNKNOWN_FAILURE);
-            } finally {
-                // Notify the package tracker that the operation is now complete.
-                mPackageTracker.recordCheckResult(mCheckToken, packageTrackerStatus);
-
-                mOperationInProgress.set(false);
-            }
-        }
-
-        private void sendUninstallNotificationIntentIfRequired(int uninstallResult) {
-            switch (uninstallResult) {
-                case TimeZoneDistroInstaller.UNINSTALL_SUCCESS:
-                    mIntentHelper.sendTimeZoneOperationStaged();
-                    break;
-                case TimeZoneDistroInstaller.UNINSTALL_NOTHING_INSTALLED:
-                    mIntentHelper.sendTimeZoneOperationUnstaged();
-                    break;
-                case TimeZoneDistroInstaller.UNINSTALL_FAIL:
-                default:
-                    // No-op - unknown or nothing to notify about.
-            }
-        }
-    }
-
-    private void sendFinishedStatus(ICallback callback, int resultCode) {
-        try {
-            callback.onFinished(resultCode);
-        } catch (RemoteException e) {
-            Slog.e(TAG, "Unable to notify observer of result", e);
-        }
-    }
-
-    @Override
-    public void requestNothing(byte[] checkTokenBytes, boolean success) {
-        mPermissionHelper.enforceCallerHasPermission(REQUIRED_UPDATER_PERMISSION);
-        CheckToken checkToken = null;
-        if (checkTokenBytes != null) {
-            checkToken = createCheckTokenOrThrow(checkTokenBytes);
-        }
-        EventLogTags.writeTimezoneRequestNothing(toStringOrNull(checkToken));
-        mPackageTracker.recordCheckResult(checkToken, success);
-        EventLogTags.writeTimezoneNothingComplete(toStringOrNull(checkToken));
-    }
-
-    @Override
-    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-        if (!mPermissionHelper.checkDumpPermission(TAG, pw)) {
-            return;
-        }
-
-        RulesState rulesState = getRulesStateInternal();
-        if (args != null && args.length == 2) {
-            // Formatting options used for automated tests. The format is less free-form than
-            // the -format options, which are intended to be easier to parse.
-            if ("-format_state".equals(args[0]) && args[1] != null) {
-                for (char c : args[1].toCharArray()) {
-                    switch (c) {
-                        case 'p': {
-                            // Report operation in progress
-                            String value = "Unknown";
-                            if (rulesState != null) {
-                                value = Boolean.toString(rulesState.isOperationInProgress());
-                            }
-                            pw.println("Operation in progress: " + value);
-                            break;
-                        }
-                        case 'b': {
-                            // Report base rules version
-                            String value = "Unknown";
-                            if (rulesState != null) {
-                                value = rulesState.getBaseRulesVersion();
-                            }
-                            pw.println("Base rules version: " + value);
-                            break;
-                        }
-                        case 'c': {
-                            // Report current installation state
-                            String value = "Unknown";
-                            if (rulesState != null) {
-                                value = distroStatusToString(rulesState.getDistroStatus());
-                            }
-                            pw.println("Current install state: " + value);
-                            break;
-                        }
-                        case 'i': {
-                            // Report currently installed version
-                            String value = "Unknown";
-                            if (rulesState != null) {
-                                DistroRulesVersion installedRulesVersion =
-                                        rulesState.getInstalledDistroRulesVersion();
-                                if (installedRulesVersion == null) {
-                                    value = "<None>";
-                                } else {
-                                    value = installedRulesVersion.toDumpString();
-                                }
-                            }
-                            pw.println("Installed rules version: " + value);
-                            break;
-                        }
-                        case 'o': {
-                            // Report staged operation type
-                            String value = "Unknown";
-                            if (rulesState != null) {
-                                int stagedOperationType = rulesState.getStagedOperationType();
-                                value = stagedOperationToString(stagedOperationType);
-                            }
-                            pw.println("Staged operation: " + value);
-                            break;
-                        }
-                        case 't': {
-                            // Report staged version (i.e. the one that will be installed next boot
-                            // if the staged operation is an install).
-                            String value = "Unknown";
-                            if (rulesState != null) {
-                                DistroRulesVersion stagedDistroRulesVersion =
-                                        rulesState.getStagedDistroRulesVersion();
-                                if (stagedDistroRulesVersion == null) {
-                                    value = "<None>";
-                                } else {
-                                    value = stagedDistroRulesVersion.toDumpString();
-                                }
-                            }
-                            pw.println("Staged rules version: " + value);
-                            break;
-                        }
-                        case 'a': {
-                            // Report the active rules version (i.e. the rules in use by the current
-                            // process).
-                            pw.println("Active rules version (ICU, ZoneInfoDb, TimeZoneFinder): "
-                                    + TimeZone.getTZDataVersion() + ","
-                                    + ZoneInfoDb.getInstance().getVersion() + ","
-                                    + TimeZoneFinder.getInstance().getIanaVersion());
-                            break;
-                        }
-                        default: {
-                            pw.println("Unknown option: " + c);
-                        }
-                    }
-                }
-                return;
-            }
-        }
-
-        pw.println("RulesManagerService state: " + toString());
-        pw.println("Active rules version (ICU, ZoneInfoDB, TimeZoneFinder): "
-                + TimeZone.getTZDataVersion() + ","
-                + ZoneInfoDb.getInstance().getVersion() + ","
-                + TimeZoneFinder.getInstance().getIanaVersion());
-        pw.println("Distro state: " + rulesState.toString());
-        mPackageTracker.dump(pw);
-    }
-
-    /**
-     * Called when the device is considered idle.
-     */
-    void notifyIdle() {
-        // No package has changed: we are just triggering because the device is idle and there
-        // *might* be work to do.
-        final boolean packageChanged = false;
-        mPackageTracker.triggerUpdateIfNeeded(packageChanged);
-    }
-
-    @Override
-    public String toString() {
-        return "RulesManagerService{" +
-                "mOperationInProgress=" + mOperationInProgress +
-                '}';
-    }
-
-    private static CheckToken createCheckTokenOrThrow(byte[] checkTokenBytes) {
-        CheckToken checkToken;
-        try {
-            checkToken = CheckToken.fromByteArray(checkTokenBytes);
-        } catch (IOException e) {
-            throw new IllegalArgumentException("Unable to read token bytes "
-                    + Arrays.toString(checkTokenBytes), e);
-        }
-        return checkToken;
-    }
-
-    private static String distroStatusToString(int distroStatus) {
-        switch(distroStatus) {
-            case DISTRO_STATUS_NONE:
-                return "None";
-            case DISTRO_STATUS_INSTALLED:
-                return "Installed";
-            case DISTRO_STATUS_UNKNOWN:
-            default:
-                return "Unknown";
-        }
-    }
-
-    private static String stagedOperationToString(int stagedOperationType) {
-        switch(stagedOperationType) {
-            case STAGED_OPERATION_NONE:
-                return "None";
-            case STAGED_OPERATION_UNINSTALL:
-                return "Uninstall";
-            case STAGED_OPERATION_INSTALL:
-                return "Install";
-            case STAGED_OPERATION_UNKNOWN:
-            default:
-                return "Unknown";
-        }
-    }
-
-    private static String toStringOrNull(Object obj) {
-        return obj == null ? null : obj.toString();
-    }
-}
diff --git a/services/core/java/com/android/server/timezone/RulesManagerServiceHelperImpl.java b/services/core/java/com/android/server/timezone/RulesManagerServiceHelperImpl.java
deleted file mode 100644
index 8f5c7a7..0000000
--- a/services/core/java/com/android/server/timezone/RulesManagerServiceHelperImpl.java
+++ /dev/null
@@ -1,74 +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.timezone;
-
-import com.android.internal.util.DumpUtils;
-
-import android.app.timezone.RulesManager;
-import android.content.Context;
-import android.content.Intent;
-import android.os.AsyncTask;
-import android.os.UserHandle;
-
-import java.io.PrintWriter;
-import java.util.concurrent.Executor;
-
-/**
- * A single class that implements multiple helper interfaces for use by {@link RulesManagerService}.
- */
-final class RulesManagerServiceHelperImpl
-        implements PermissionHelper, Executor, RulesManagerIntentHelper {
-
-    private final Context mContext;
-
-    RulesManagerServiceHelperImpl(Context context) {
-        mContext = context;
-    }
-
-    @Override
-    public void enforceCallerHasPermission(String requiredPermission) {
-        mContext.enforceCallingPermission(requiredPermission, null /* message */);
-    }
-
-    @Override
-    public boolean checkDumpPermission(String tag, PrintWriter pw) {
-        return DumpUtils.checkDumpPermission(mContext, tag, pw);
-    }
-
-    @Override
-    public void execute(Runnable runnable) {
-        AsyncTask.execute(runnable);
-    }
-
-    @Override
-    public void sendTimeZoneOperationStaged() {
-        sendOperationIntent(true /* staged */);
-    }
-
-    @Override
-    public void sendTimeZoneOperationUnstaged() {
-        sendOperationIntent(false /* staged */);
-    }
-
-    private void sendOperationIntent(boolean staged) {
-        Intent intent = new Intent(RulesManager.ACTION_RULES_UPDATE_OPERATION);
-        intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
-        intent.putExtra(RulesManager.EXTRA_OPERATION_STAGED, staged);
-        mContext.sendBroadcastAsUser(intent, UserHandle.SYSTEM);
-    }
-
-}
diff --git a/services/core/java/com/android/server/timezone/TimeZoneUpdateIdler.java b/services/core/java/com/android/server/timezone/TimeZoneUpdateIdler.java
deleted file mode 100644
index 23e3eba..0000000
--- a/services/core/java/com/android/server/timezone/TimeZoneUpdateIdler.java
+++ /dev/null
@@ -1,100 +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.timezone;
-
-import android.app.job.JobInfo;
-import android.app.job.JobParameters;
-import android.app.job.JobScheduler;
-import android.app.job.JobService;
-import android.content.ComponentName;
-import android.content.Context;
-import android.util.Slog;
-
-import com.android.server.LocalServices;
-
-/**
- * A JobService used to trigger time zone rules update work when a device falls idle.
- */
-public final class TimeZoneUpdateIdler extends JobService {
-
-    private static final String TAG = "timezone.TimeZoneUpdateIdler";
-
-    /** The static job ID used to handle on-idle work. */
-    // Must be unique within UID (system service)
-    private static final int TIME_ZONE_UPDATE_IDLE_JOB_ID = 27042305;
-
-    @Override
-    public boolean onStartJob(JobParameters params) {
-        RulesManagerService rulesManagerService =
-                LocalServices.getService(RulesManagerService.class);
-
-        Slog.d(TAG, "onStartJob() called");
-
-        // Note: notifyIdle() explicitly handles canceling / re-scheduling so no need to reschedule
-        // here.
-        rulesManagerService.notifyIdle();
-
-        // Everything is handled synchronously. We are done.
-        return false;
-    }
-
-    @Override
-    public boolean onStopJob(JobParameters params) {
-        // Reschedule if stopped unless it was cancelled due to unschedule().
-        boolean reschedule = params.getStopReason() != JobParameters.STOP_REASON_CANCELLED_BY_APP;
-        Slog.d(TAG, "onStopJob() called: Reschedule=" + reschedule);
-        return reschedule;
-    }
-
-    /**
-     * Schedules the TimeZoneUpdateIdler job service to run once.
-     *
-     * @param context Context to use to get a job scheduler.
-     */
-    public static void schedule(Context context, long minimumDelayMillis) {
-        // Request that the JobScheduler tell us when the device falls idle.
-        JobScheduler jobScheduler =
-                (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
-
-        // The TimeZoneUpdateIdler will send an intent that will trigger the Receiver.
-        ComponentName idlerJobServiceName =
-                new ComponentName(context, TimeZoneUpdateIdler.class);
-
-        // We require the device is idle, but also that it is charging to be as non-invasive as
-        // we can.
-        JobInfo.Builder jobInfoBuilder =
-                new JobInfo.Builder(TIME_ZONE_UPDATE_IDLE_JOB_ID, idlerJobServiceName)
-                        .setRequiresDeviceIdle(true)
-                        .setRequiresCharging(true)
-                        .setMinimumLatency(minimumDelayMillis);
-
-        Slog.d(TAG, "schedule() called: minimumDelayMillis=" + minimumDelayMillis);
-        jobScheduler.schedule(jobInfoBuilder.build());
-    }
-
-    /**
-     * Unschedules the TimeZoneUpdateIdler job service.
-     *
-     * @param context Context to use to get a job scheduler.
-     */
-    public static void unschedule(Context context) {
-        JobScheduler jobScheduler =
-                (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
-        Slog.d(TAG, "unschedule() called");
-        jobScheduler.cancel(TIME_ZONE_UPDATE_IDLE_JOB_ID);
-    }
-}
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index b184d5c..42c6dd43 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -4193,17 +4193,17 @@
      */
     @VisibleForTesting
     SurfaceControl computeImeParent() {
-        if (mImeLayeringTarget != null && mImeInputTarget != null
-                && mImeLayeringTarget.mActivityRecord != mImeInputTarget.mActivityRecord) {
-            // Do not change parent if the window hasn't requested IME.
-            return null;
-        }
         // Attach it to app if the target is part of an app and such app is covering the entire
         // screen. If it's not covering the entire screen the IME might extend beyond the apps
         // bounds.
         if (shouldImeAttachedToApp()) {
+            if (mImeLayeringTarget.mActivityRecord != mImeInputTarget.mActivityRecord) {
+                // Do not change parent if the window hasn't requested IME.
+                return null;
+            }
             return mImeLayeringTarget.mActivityRecord.getSurfaceControl();
         }
+
         // Otherwise, we just attach it to where the display area policy put it.
         return mImeWindowsContainer.getParent() != null
                 ? mImeWindowsContainer.getParent().getSurfaceControl() : null;
diff --git a/services/core/java/com/android/server/wm/InsetsPolicy.java b/services/core/java/com/android/server/wm/InsetsPolicy.java
index 5124841..10ae152 100644
--- a/services/core/java/com/android/server/wm/InsetsPolicy.java
+++ b/services/core/java/com/android/server/wm/InsetsPolicy.java
@@ -265,12 +265,14 @@
                 return state;
             }
         } else if (w.mActivityRecord != null && w.mActivityRecord.mImeInsetsFrozenUntilStartInput) {
-            // During switching tasks with gestural navigation, before the next IME input target
-            // starts the input, we should adjust and freeze the last IME visibility of the window
-            // in case delivering obsoleted IME insets state during transitioning.
+            // During switching tasks with gestural navigation, if the IME is attached to
+            // one app window on that time, even the next app window is behind the IME window,
+            // conceptually the window should not receive the IME insets if the next window is
+            // not eligible IME requester and ready to show IME on top of it.
+            final boolean shouldImeAttachedToApp = mDisplayContent.shouldImeAttachedToApp();
             final InsetsSource originalImeSource = originalState.peekSource(ITYPE_IME);
 
-            if (originalImeSource != null) {
+            if (shouldImeAttachedToApp && originalImeSource != null) {
                 final boolean imeVisibility =
                         w.mActivityRecord.mLastImeShown || w.getRequestedVisibility(ITYPE_IME);
                 final InsetsState state = copyState ? new InsetsState(originalState)
diff --git a/services/core/java/com/android/server/wm/SafeActivityOptions.java b/services/core/java/com/android/server/wm/SafeActivityOptions.java
index 2d4aef6..66d0230 100644
--- a/services/core/java/com/android/server/wm/SafeActivityOptions.java
+++ b/services/core/java/com/android/server/wm/SafeActivityOptions.java
@@ -25,7 +25,9 @@
 import static android.app.WindowConfiguration.activityTypeToString;
 import static android.content.pm.PackageManager.PERMISSION_DENIED;
 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.Display.INVALID_DISPLAY;
+import static android.window.DisplayAreaOrganizer.FEATURE_UNDEFINED;
 
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
@@ -248,8 +250,25 @@
         }
         // Check if the caller is allowed to launch on the specified display area.
         final WindowContainerToken daToken = options.getLaunchTaskDisplayArea();
-        final TaskDisplayArea taskDisplayArea = daToken != null
+        TaskDisplayArea taskDisplayArea = daToken != null
                 ? (TaskDisplayArea) WindowContainer.fromBinder(daToken.asBinder()) : null;
+
+        // If we do not have a task display area token, check if the launch task display area
+        // feature id is specified.
+        if (taskDisplayArea == null) {
+            final int launchTaskDisplayAreaFeatureId = options.getLaunchTaskDisplayAreaFeatureId();
+            if (launchTaskDisplayAreaFeatureId != FEATURE_UNDEFINED) {
+                final int launchDisplayId = options.getLaunchDisplayId() == INVALID_DISPLAY
+                        ? DEFAULT_DISPLAY : options.getLaunchDisplayId();
+                final DisplayContent dc = supervisor.mRootWindowContainer
+                        .getDisplayContent(launchDisplayId);
+                if (dc != null) {
+                    taskDisplayArea = dc.getItemFromTaskDisplayAreas(tda ->
+                            tda.mFeatureId == launchTaskDisplayAreaFeatureId ? tda : null);
+                }
+            }
+        }
+
         if (aInfo != null && taskDisplayArea != null
                 && !supervisor.isCallerAllowedToLaunchOnTaskDisplayArea(callingPid, callingUid,
                 taskDisplayArea, aInfo)) {
diff --git a/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java b/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java
index b8ceb4a..24a745b 100644
--- a/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java
+++ b/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java
@@ -35,6 +35,7 @@
 import static android.util.DisplayMetrics.DENSITY_DEFAULT;
 import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.Display.INVALID_DISPLAY;
+import static android.window.DisplayAreaOrganizer.FEATURE_UNDEFINED;
 
 import static com.android.server.wm.ActivityStarter.Request;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
@@ -293,7 +294,8 @@
         TaskDisplayArea taskDisplayArea = suggestedDisplayArea;
         // If launch task display area is set in options we should just use it. We assume the
         // suggestedDisplayArea has the right one in this case.
-        if (options == null || options.getLaunchTaskDisplayArea() == null) {
+        if (options == null || (options.getLaunchTaskDisplayArea() == null
+                && options.getLaunchTaskDisplayAreaFeatureId() == FEATURE_UNDEFINED)) {
             final int activityType =
                     mSupervisor.mRootWindowContainer.resolveActivityType(root, options, task);
             display.forAllTaskDisplayAreas(displayArea -> {
@@ -377,7 +379,22 @@
         if (optionLaunchTaskDisplayAreaToken != null) {
             taskDisplayArea = (TaskDisplayArea) WindowContainer.fromBinder(
                     optionLaunchTaskDisplayAreaToken.asBinder());
-            if (DEBUG) appendLog("display-area-from-option=" + taskDisplayArea);
+            if (DEBUG) appendLog("display-area-token-from-option=" + taskDisplayArea);
+        }
+
+        if (taskDisplayArea == null && options != null) {
+            final int launchTaskDisplayAreaFeatureId = options.getLaunchTaskDisplayAreaFeatureId();
+            if (launchTaskDisplayAreaFeatureId != FEATURE_UNDEFINED) {
+                final int launchDisplayId = options.getLaunchDisplayId() == INVALID_DISPLAY
+                        ? DEFAULT_DISPLAY : options.getLaunchDisplayId();
+                final DisplayContent dc = mSupervisor.mRootWindowContainer
+                        .getDisplayContent(launchDisplayId);
+                if (dc != null) {
+                    taskDisplayArea = dc.getItemFromTaskDisplayAreas(tda ->
+                            tda.mFeatureId == launchTaskDisplayAreaFeatureId ? tda : null);
+                    if (DEBUG) appendLog("display-area-feature-from-option=" + taskDisplayArea);
+                }
+            }
         }
 
         // If task display area is not specified in options - try display id
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index dc729f2..d3b928f 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -326,8 +326,6 @@
             "com.android.server.systemcaptions.SystemCaptionsManagerService";
     private static final String TEXT_TO_SPEECH_MANAGER_SERVICE_CLASS =
             "com.android.server.texttospeech.TextToSpeechManagerService";
-    private static final String TIME_ZONE_RULES_MANAGER_SERVICE_CLASS =
-            "com.android.server.timezone.RulesManagerService$Lifecycle";
     private static final String IOT_SERVICE_CLASS =
             "com.android.things.server.IoTSystemService";
     private static final String SLICE_MANAGER_SERVICE_CLASS =
@@ -2183,19 +2181,6 @@
             }
             t.traceEnd();
 
-            // timezone.RulesManagerService will prevent a device starting up if the chain of trust
-            // required for safe time zone updates might be broken. RuleManagerService cannot do
-            // this check when mOnlyCore == true, so we don't enable the service in this case.
-            // This service requires that JobSchedulerService is already started when it starts.
-            final boolean startRulesManagerService =
-                    !mOnlyCore && context.getResources().getBoolean(
-                            R.bool.config_enableUpdateableTimeZoneRules);
-            if (startRulesManagerService) {
-                t.traceBegin("StartTimeZoneRulesManagerService");
-                mSystemServiceManager.startService(TIME_ZONE_RULES_MANAGER_SERVICE_CLASS);
-                t.traceEnd();
-            }
-
             if (!isWatch && !disableNetworkTime) {
                 t.traceBegin("StartNetworkTimeUpdateService");
                 try {
diff --git a/services/net/Android.bp b/services/net/Android.bp
index 886a397..804ccc5 100644
--- a/services/net/Android.bp
+++ b/services/net/Android.bp
@@ -28,30 +28,6 @@
     ],
 }
 
-// Version of services.net for usage by the wifi mainline module.
-// Note: This is compiled against module_current.
-// TODO(b/172457099): This should be moved to networkstack-client,
-// with dependencies moved to frameworks/libs/net right.
-java_library {
-    name: "services.net-module-wifi",
-    sdk_version: "module_current",
-    min_sdk_version: "30",
-    static_libs: [
-        // All the classes in netd_aidl_interface must be jarjar so they do not conflict with the
-        // classes generated by netd_aidl_interfaces-platform-java above.
-        "netd_aidl_interface-V3-java",
-        "networkstack-client",
-        "net-utils-services-common",
-    ],
-    apex_available: [
-        "com.android.wifi",
-    ],
-    visibility: [
-        "//packages/modules/Wifi/service",
-        "//packages/modules/Wifi/service/tests/wifitests",
-    ],
-}
-
 filegroup {
     name: "services-tethering-shared-srcs",
     srcs: [
diff --git a/services/net/java/android/net/ConnectivityModuleConnector.java b/services/net/java/android/net/ConnectivityModuleConnector.java
index c6b15c1..6bf6349 100644
--- a/services/net/java/android/net/ConnectivityModuleConnector.java
+++ b/services/net/java/android/net/ConnectivityModuleConnector.java
@@ -25,7 +25,6 @@
 import android.content.ServiceConnection;
 import android.content.SharedPreferences;
 import android.content.pm.PackageManager;
-import android.net.util.SharedLog;
 import android.os.Build;
 import android.os.Environment;
 import android.os.IBinder;
@@ -35,13 +34,13 @@
 import android.provider.DeviceConfig;
 import android.text.format.DateUtils;
 import android.util.ArraySet;
+import android.util.Log;
 import android.util.Slog;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 
 import java.io.File;
-import java.io.PrintWriter;
 
 /**
  * Class used to communicate to the various networking mainline modules running in the network stack
@@ -73,8 +72,6 @@
     private static ConnectivityModuleConnector sInstance;
 
     private Context mContext;
-    @GuardedBy("mLog")
-    private final SharedLog mLog = new SharedLog(TAG);
     @GuardedBy("mHealthListeners")
     private final ArraySet<ConnectivityModuleHealthListener> mHealthListeners = new ArraySet<>();
     @NonNull
@@ -384,38 +381,19 @@
     }
 
     private void log(@NonNull String message) {
-        Slog.d(TAG, message);
-        synchronized (mLog) {
-            mLog.log(message);
-        }
+        Log.d(TAG, message);
     }
 
     private void logWtf(@NonNull String message, @Nullable Throwable e) {
         Slog.wtf(TAG, message, e);
-        synchronized (mLog) {
-            mLog.e(message);
-        }
+        Log.e(TAG, message, e);
     }
 
     private void loge(@NonNull String message, @Nullable Throwable e) {
-        Slog.e(TAG, message, e);
-        synchronized (mLog) {
-            mLog.e(message);
-        }
+        Log.e(TAG, message, e);
     }
 
     private void logi(@NonNull String message) {
-        Slog.i(TAG, message);
-        synchronized (mLog) {
-            mLog.i(message);
-        }
-    }
-
-    /**
-     * Dump ConnectivityModuleConnector logs to the specified {@link PrintWriter}.
-     */
-    public void dump(PrintWriter pw) {
-        // dump is thread-safe on SharedLog
-        mLog.dump(null, pw, null);
+        Log.i(TAG, message);
     }
 }
diff --git a/services/net/java/android/net/NetworkStackClient.java b/services/net/java/android/net/NetworkStackClient.java
index 865e3b8..b7eb5cd 100644
--- a/services/net/java/android/net/NetworkStackClient.java
+++ b/services/net/java/android/net/NetworkStackClient.java
@@ -25,19 +25,18 @@
 import android.net.dhcp.DhcpServingParamsParcel;
 import android.net.dhcp.IDhcpServerCallbacks;
 import android.net.ip.IIpClientCallbacks;
-import android.net.util.SharedLog;
 import android.os.Binder;
 import android.os.IBinder;
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.UserHandle;
+import android.util.Log;
 import android.util.Slog;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 
-import java.io.PrintWriter;
 import java.util.ArrayList;
 
 /**
@@ -61,9 +60,6 @@
     @GuardedBy("mPendingNetStackRequests")
     private INetworkStackConnector mConnector;
 
-    @GuardedBy("mLog")
-    private final SharedLog mLog = new SharedLog(TAG);
-
     private volatile boolean mWasSystemServerInitialized = false;
 
     private interface NetworkStackCallback {
@@ -237,34 +233,23 @@
     }
 
     /**
-     * Log a message in the local log.
+     * Log a debug message.
      */
     private void log(@NonNull String message) {
-        synchronized (mLog) {
-            mLog.log(message);
-        }
+        Log.d(TAG, message);
     }
 
     private void logWtf(@NonNull String message, @Nullable Throwable e) {
         Slog.wtf(TAG, message);
-        synchronized (mLog) {
-            mLog.e(message, e);
-        }
+        Log.e(TAG, message, e);
     }
 
     private void loge(@NonNull String message, @Nullable Throwable e) {
-        synchronized (mLog) {
-            mLog.e(message, e);
-        }
+        Log.e(TAG, message, e);
     }
 
-    /**
-     * Log a message in the local and system logs.
-     */
     private void logi(@NonNull String message) {
-        synchronized (mLog) {
-            mLog.i(message);
-        }
+        Log.i(TAG, message);
     }
 
     /**
@@ -320,22 +305,4 @@
 
         request.onNetworkStackConnected(connector);
     }
-
-    /**
-     * Dump NetworkStackClient logs to the specified {@link PrintWriter}.
-     */
-    public void dump(PrintWriter pw) {
-        // dump is thread-safe on SharedLog
-        mLog.dump(null, pw, null);
-        // dump connectivity module connector logs.
-        ConnectivityModuleConnector.getInstance().dump(pw);
-
-        final int requestsQueueLength;
-        synchronized (mPendingNetStackRequests) {
-            requestsQueueLength = mPendingNetStackRequests.size();
-        }
-
-        pw.println();
-        pw.println("pendingNetStackRequests length: " + requestsQueueLength);
-    }
 }
diff --git a/services/smartspace/OWNERS b/services/smartspace/OWNERS
index 19ef9d7..4d9a633 100644
--- a/services/smartspace/OWNERS
+++ b/services/smartspace/OWNERS
@@ -1,2 +1 @@
-srazdan@google.com
-alexmang@google.com
\ No newline at end of file
+include /core/java/android/service/smartspace/OWNERS
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/SettingsToPropertiesMapperTest.java b/services/tests/mockingservicestests/src/com/android/server/am/SettingsToPropertiesMapperTest.java
index 5db8867..de27d77 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/SettingsToPropertiesMapperTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/SettingsToPropertiesMapperTest.java
@@ -204,7 +204,7 @@
 
     @Test
     public void testUpdatePropertiesFromSettings_PropertyAndSettingNotPresent() {
-        // Test that empty property will not not be set if setting is not set
+        // Test that empty property will not be set if setting is not set
         mTestMapper.updatePropertiesFromSettings();
         String propValue = mSystemSettingsMap.get("TestProperty");
         Assert.assertNull("Property should not be set if setting is null", propValue);
diff --git a/services/tests/servicestests/src/com/android/server/adb/AdbDebuggingManagerTest.java b/services/tests/servicestests/src/com/android/server/adb/AdbDebuggingManagerTest.java
index 02cf971..336fd5c 100644
--- a/services/tests/servicestests/src/com/android/server/adb/AdbDebuggingManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/adb/AdbDebuggingManagerTest.java
@@ -36,8 +36,6 @@
 
 import androidx.test.InstrumentationRegistry;
 
-import com.android.server.FgThread;
-
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -48,6 +46,11 @@
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.FileReader;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.StandardCopyOption;
+import java.util.ArrayList;
+import java.util.List;
 import java.util.concurrent.ArrayBlockingQueue;
 import java.util.concurrent.BlockingQueue;
 import java.util.concurrent.CountDownLatch;
@@ -88,6 +91,7 @@
     private long mOriginalAllowedConnectionTime;
     private File mAdbKeyXmlFile;
     private File mAdbKeyFile;
+    private FakeTicker mFakeTicker;
 
     @Before
     public void setUp() throws Exception {
@@ -96,14 +100,25 @@
         if (mAdbKeyFile.exists()) {
             mAdbKeyFile.delete();
         }
-        mManager = new AdbDebuggingManager(mContext, ADB_CONFIRM_COMPONENT, mAdbKeyFile);
         mAdbKeyXmlFile = new File(mContext.getFilesDir(), "test_adb_keys.xml");
         if (mAdbKeyXmlFile.exists()) {
             mAdbKeyXmlFile.delete();
         }
+
+        mFakeTicker = new FakeTicker();
+        // Set the ticker time to October 22, 2008 (the day the T-Mobile G1 was released)
+        mFakeTicker.advance(1224658800L);
+
         mThread = new AdbDebuggingThreadTest();
-        mKeyStore = mManager.new AdbKeyStore(mAdbKeyXmlFile);
-        mHandler = mManager.new AdbDebuggingHandler(FgThread.get().getLooper(), mThread, mKeyStore);
+        mManager = new AdbDebuggingManager(
+                mContext, ADB_CONFIRM_COMPONENT, mAdbKeyFile, mAdbKeyXmlFile, mThread, mFakeTicker);
+
+        mHandler = mManager.mHandler;
+        mThread.setHandler(mHandler);
+
+        mHandler.initKeyStore();
+        mKeyStore = mHandler.mAdbKeyStore;
+
         mOriginalAllowedConnectionTime = mKeyStore.getAllowedConnectionTime();
         mBlockingQueue = new ArrayBlockingQueue<>(1);
     }
@@ -122,7 +137,7 @@
     private void setAllowedConnectionTime(long connectionTime) {
         Settings.Global.putLong(mContext.getContentResolver(),
                 Settings.Global.ADB_ALLOWED_CONNECTION_TIME, connectionTime);
-    };
+    }
 
     @Test
     public void testAllowNewKeyOnce() throws Exception {
@@ -158,20 +173,15 @@
         // Allow a connection from a new key with the 'Always allow' option selected.
         runAdbTest(TEST_KEY_1, true, true, false);
 
-        // Get the last connection time for the currently connected key to verify that it is updated
-        // after the disconnect.
-        long lastConnectionTime = mKeyStore.getLastConnectionTime(TEST_KEY_1);
-
-        // Sleep for a small amount of time to ensure a difference can be observed in the last
-        // connection time after a disconnect.
-        Thread.sleep(10);
+        // Advance the clock by 10ms to ensure there's a difference
+        mFakeTicker.advance(10 * 1_000_000);
 
         // Send the disconnect message for the currently connected key to trigger an update of the
         // last connection time.
         disconnectKey(TEST_KEY_1);
-        assertNotEquals(
+        assertEquals(
                 "The last connection time was not updated after the disconnect",
-                lastConnectionTime,
+                mFakeTicker.currentTimeMillis(),
                 mKeyStore.getLastConnectionTime(TEST_KEY_1));
     }
 
@@ -244,8 +254,8 @@
         // Get the current last connection time for comparison after the scheduled job is run
         long lastConnectionTime = mKeyStore.getLastConnectionTime(TEST_KEY_1);
 
-        // Sleep a small amount of time to ensure that the updated connection time changes
-        Thread.sleep(10);
+        // Advance a small amount of time to ensure that the updated connection time changes
+        mFakeTicker.advance(10);
 
         // Send a message to the handler to update the last connection time for the active key
         updateKeyStore();
@@ -269,13 +279,13 @@
         persistKeyStore();
         assertTrue(
                 "The key with the 'Always allow' option selected was not persisted in the keystore",
-                mManager.new AdbKeyStore(mAdbKeyXmlFile).isKeyAuthorized(TEST_KEY_1));
+                mManager.new AdbKeyStore().isKeyAuthorized(TEST_KEY_1));
 
         // Get the current last connection time to ensure it is updated in the persisted keystore.
         long lastConnectionTime = mKeyStore.getLastConnectionTime(TEST_KEY_1);
 
-        // Sleep a small amount of time to ensure the last connection time is updated.
-        Thread.sleep(10);
+        // Advance a small amount of time to ensure the last connection time is updated.
+        mFakeTicker.advance(10);
 
         // Send a message to the handler to update the last connection time for the active key.
         updateKeyStore();
@@ -286,7 +296,7 @@
         assertNotEquals(
                 "The last connection time in the key file was not updated after the update "
                         + "connection time message", lastConnectionTime,
-                mManager.new AdbKeyStore(mAdbKeyXmlFile).getLastConnectionTime(TEST_KEY_1));
+                mManager.new AdbKeyStore().getLastConnectionTime(TEST_KEY_1));
         // Verify that the key is in the adb_keys file
         assertTrue("The key was not in the adb_keys file after persisting the keystore",
                 isKeyInFile(TEST_KEY_1, mAdbKeyFile));
@@ -327,8 +337,8 @@
         // Set the allowed window to a small value to ensure the time is beyond the allowed window.
         setAllowedConnectionTime(1);
 
-        // Sleep for a small amount of time to exceed the allowed window.
-        Thread.sleep(10);
+        // Advance a small amount of time to exceed the allowed window.
+        mFakeTicker.advance(10);
 
         // The AdbKeyStore has a method to get the time of the next key expiration to ensure the
         // scheduled job runs at the time of the next expiration or after 24 hours, whichever occurs
@@ -478,9 +488,12 @@
         // Set the current expiration time to a minute from expiration and verify this new value is
         // returned.
         final long newExpirationTime = 60000;
-        mKeyStore.setLastConnectionTime(TEST_KEY_1,
-                System.currentTimeMillis() - Settings.Global.DEFAULT_ADB_ALLOWED_CONNECTION_TIME
-                        + newExpirationTime, true);
+        mKeyStore.setLastConnectionTime(
+                TEST_KEY_1,
+                mFakeTicker.currentTimeMillis()
+                        - Settings.Global.DEFAULT_ADB_ALLOWED_CONNECTION_TIME
+                        + newExpirationTime,
+                true);
         expirationTime = mKeyStore.getNextExpirationTime();
         if (Math.abs(expirationTime - newExpirationTime) > epsilon) {
             fail("The expiration time for a key about to expire, " + expirationTime
@@ -525,7 +538,7 @@
         // Get the last connection time for the key to verify that it is updated when the connected
         // key message is sent.
         long connectionTime = mKeyStore.getLastConnectionTime(TEST_KEY_1);
-        Thread.sleep(10);
+        mFakeTicker.advance(10);
         mHandler.obtainMessage(AdbDebuggingManager.AdbDebuggingHandler.MESSAGE_ADB_CONNECTED_KEY,
                 TEST_KEY_1).sendToTarget();
         flushHandlerQueue();
@@ -536,7 +549,7 @@
 
         // Verify that the scheduled job updates the connection time of the key.
         connectionTime = mKeyStore.getLastConnectionTime(TEST_KEY_1);
-        Thread.sleep(10);
+        mFakeTicker.advance(10);
         updateKeyStore();
         assertNotEquals(
                 "The connection time for the key must be updated when the update keystore message"
@@ -545,7 +558,7 @@
 
         // Verify that the connection time is updated when the key is disconnected.
         connectionTime = mKeyStore.getLastConnectionTime(TEST_KEY_1);
-        Thread.sleep(10);
+        mFakeTicker.advance(10);
         disconnectKey(TEST_KEY_1);
         assertNotEquals(
                 "The connection time for the key must be updated when the disconnected message is"
@@ -628,11 +641,11 @@
         setAllowedConnectionTime(Settings.Global.DEFAULT_ADB_ALLOWED_CONNECTION_TIME);
 
         // The untracked keys should be added to the keystore as part of the constructor.
-        AdbDebuggingManager.AdbKeyStore adbKeyStore = mManager.new AdbKeyStore(mAdbKeyXmlFile);
+        AdbDebuggingManager.AdbKeyStore adbKeyStore = mManager.new AdbKeyStore();
 
         // Verify that the connection time for each test key is within a small value of the current
         // time.
-        long time = System.currentTimeMillis();
+        long time = mFakeTicker.currentTimeMillis();
         for (String key : testKeys) {
             long connectionTime = adbKeyStore.getLastConnectionTime(key);
             if (Math.abs(connectionTime - connectionTime) > epsilon) {
@@ -651,11 +664,11 @@
         runAdbTest(TEST_KEY_1, true, true, false);
         runAdbTest(TEST_KEY_2, true, true, false);
 
-        // Sleep a small amount of time to ensure the connection time is updated by the scheduled
+        // Advance a small amount of time to ensure the connection time is updated by the scheduled
         // job.
         long connectionTime1 = mKeyStore.getLastConnectionTime(TEST_KEY_1);
         long connectionTime2 = mKeyStore.getLastConnectionTime(TEST_KEY_2);
-        Thread.sleep(10);
+        mFakeTicker.advance(10);
         updateKeyStore();
         assertNotEquals(
                 "The connection time for test key 1 must be updated after the scheduled job runs",
@@ -669,7 +682,7 @@
         disconnectKey(TEST_KEY_2);
         connectionTime1 = mKeyStore.getLastConnectionTime(TEST_KEY_1);
         connectionTime2 = mKeyStore.getLastConnectionTime(TEST_KEY_2);
-        Thread.sleep(10);
+        mFakeTicker.advance(10);
         updateKeyStore();
         assertNotEquals(
                 "The connection time for test key 1 must be updated after another key is "
@@ -686,8 +699,6 @@
         // to clear the adb authorizations when adb is disabled after a boot a NullPointerException
         // was thrown as deleteKeyStore is invoked against the key store. This test ensures the
         // key store can be successfully cleared when adb is disabled.
-        mHandler = mManager.new AdbDebuggingHandler(FgThread.get().getLooper());
-
         clearKeyStore();
     }
 
@@ -723,6 +734,9 @@
 
         // Now remove one of the keys and make sure the other key is still there
         mKeyStore.removeKey(TEST_KEY_1);
+        // Wait for the handler queue to receive the MESSAGE_ADB_PERSIST_KEYSTORE
+        flushHandlerQueue();
+
         assertFalse("The key was still in the adb_keys file after removing the key",
                 isKeyInFile(TEST_KEY_1, mAdbKeyFile));
         assertTrue("The key was not in the adb_keys file after removing a different key",
@@ -730,6 +744,95 @@
     }
 
     @Test
+    public void testAdbKeyStore_addDuplicateKey_doesNotAddDuplicateToAdbKeyFile() throws Exception {
+        setAllowedConnectionTime(0);
+
+        runAdbTest(TEST_KEY_1, true, true, false);
+        persistKeyStore();
+        runAdbTest(TEST_KEY_1, true, true, false);
+        persistKeyStore();
+
+        assertEquals("adb_keys contains duplicate keys", 1, adbKeyFileKeys(mAdbKeyFile).size());
+    }
+
+    @Test
+    public void testAdbKeyStore_adbTempKeysFile_readsLastConnectionTimeFromXml() throws Exception {
+        long insertTime = mFakeTicker.currentTimeMillis();
+        runAdbTest(TEST_KEY_1, true, true, false);
+        persistKeyStore();
+
+        mFakeTicker.advance(10);
+        AdbDebuggingManager.AdbKeyStore newKeyStore = mManager.new AdbKeyStore();
+
+        assertEquals(
+                "KeyStore not populated from the XML file.",
+                insertTime,
+                newKeyStore.getLastConnectionTime(TEST_KEY_1));
+    }
+
+    @Test
+    public void test_notifyKeyFilesUpdated_filesDeletedRemovesPreviouslyAddedKey()
+            throws Exception {
+        runAdbTest(TEST_KEY_1, true, true, false);
+        persistKeyStore();
+
+        Files.delete(mAdbKeyXmlFile.toPath());
+        Files.delete(mAdbKeyFile.toPath());
+
+        mManager.notifyKeyFilesUpdated();
+        flushHandlerQueue();
+
+        assertFalse(
+                "Key is authorized after reloading deleted key files. Was state preserved?",
+                mKeyStore.isKeyAuthorized(TEST_KEY_1));
+    }
+
+    @Test
+    public void test_notifyKeyFilesUpdated_newKeyIsAuthorized() throws Exception {
+        runAdbTest(TEST_KEY_1, true, true, false);
+        persistKeyStore();
+
+        // Back up the existing key files
+        Path tempXmlFile = Files.createTempFile("adbKeyXmlFile", ".tmp");
+        Path tempAdbKeysFile = Files.createTempFile("adb_keys", ".tmp");
+        Files.copy(mAdbKeyXmlFile.toPath(), tempXmlFile, StandardCopyOption.REPLACE_EXISTING);
+        Files.copy(mAdbKeyFile.toPath(), tempAdbKeysFile, StandardCopyOption.REPLACE_EXISTING);
+
+        // Delete the existing key files
+        Files.delete(mAdbKeyXmlFile.toPath());
+        Files.delete(mAdbKeyFile.toPath());
+
+        // Notify the manager that adb key files have changed.
+        mManager.notifyKeyFilesUpdated();
+        flushHandlerQueue();
+
+        // Copy the files back
+        Files.copy(tempXmlFile, mAdbKeyXmlFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
+        Files.copy(tempAdbKeysFile, mAdbKeyFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
+
+        // Tell the manager that the key files have changed.
+        mManager.notifyKeyFilesUpdated();
+        flushHandlerQueue();
+
+        assertTrue(
+                "Key is not authorized after reloading key files.",
+                mKeyStore.isKeyAuthorized(TEST_KEY_1));
+    }
+
+    @Test
+    public void testAdbKeyStore_adbWifiConnect_storesBssidWhenAlwaysAllow() throws Exception {
+        String trustedNetwork = "My Network";
+        mKeyStore.addTrustedNetwork(trustedNetwork);
+        persistKeyStore();
+
+        AdbDebuggingManager.AdbKeyStore newKeyStore = mManager.new AdbKeyStore();
+
+        assertTrue(
+                "Persisted trusted network not found in new keystore instance.",
+                newKeyStore.isTrustedNetwork(trustedNetwork));
+    }
+
+    @Test
     public void testIsValidMdnsServiceName() {
         // Longer than 15 characters
         assertFalse(isValidMdnsServiceName("abcd1234abcd1234"));
@@ -1030,28 +1133,27 @@
         if (key == null) {
             return false;
         }
+        return adbKeyFileKeys(keyFile).contains(key);
+    }
+
+    private static List<String> adbKeyFileKeys(File keyFile) throws Exception {
+        List<String> keys = new ArrayList<>();
         if (keyFile.exists()) {
             try (BufferedReader in = new BufferedReader(new FileReader(keyFile))) {
                 String currKey;
                 while ((currKey = in.readLine()) != null) {
-                    if (key.equals(currKey)) {
-                        return true;
-                    }
+                    keys.add(currKey);
                 }
             }
         }
-        return false;
+        return keys;
     }
 
     /**
      * Helper class that extends AdbDebuggingThread to receive the response from AdbDebuggingManager
      * indicating whether the key should be allowed to  connect.
      */
-    class AdbDebuggingThreadTest extends AdbDebuggingManager.AdbDebuggingThread {
-        AdbDebuggingThreadTest() {
-            mManager.super();
-        }
-
+    private class AdbDebuggingThreadTest extends AdbDebuggingManager.AdbDebuggingThread {
         @Override
         public void sendResponse(String msg) {
             TestResult result = new TestResult(TestResult.RESULT_RESPONSE_RECEIVED, msg);
@@ -1091,4 +1193,17 @@
             return "{mReturnCode = " + mReturnCode + ", mMessage = " + mMessage + "}";
         }
     }
+
+    private static class FakeTicker implements AdbDebuggingManager.Ticker {
+        private long mCurrentTime;
+
+        private void advance(long milliseconds) {
+            mCurrentTime += milliseconds;
+        }
+
+        @Override
+        public long currentTimeMillis() {
+            return mCurrentTime;
+        }
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/am/BroadcastRecordTest.java b/services/tests/servicestests/src/com/android/server/am/BroadcastRecordTest.java
index e9b5b62..f44104e 100644
--- a/services/tests/servicestests/src/com/android/server/am/BroadcastRecordTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/BroadcastRecordTest.java
@@ -185,6 +185,7 @@
                 null /* resolvedType */,
                 null /* requiredPermissions */,
                 null /* excludedPermissions */,
+                null /* excludedPackages */,
                 0 /* appOp */,
                 null /* options */,
                 new ArrayList<>(receivers), // Make a copy to not affect the original list.
diff --git a/services/tests/servicestests/src/com/android/server/apphibernation/AppHibernationServiceTest.java b/services/tests/servicestests/src/com/android/server/apphibernation/AppHibernationServiceTest.java
index 1c49e6e..70853b6 100644
--- a/services/tests/servicestests/src/com/android/server/apphibernation/AppHibernationServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/apphibernation/AppHibernationServiceTest.java
@@ -298,7 +298,7 @@
         ArgumentCaptor<Intent> intentArgumentCaptor = ArgumentCaptor.forClass(Intent.class);
         verify(mIActivityManager, times(2)).broadcastIntentWithFeature(any(), any(),
                 intentArgumentCaptor.capture(), any(), any(), anyInt(), any(), any(), any(), any(),
-                anyInt(), any(), anyBoolean(), anyBoolean(), eq(USER_ID_1));
+                any(), anyInt(), any(), anyBoolean(), anyBoolean(), eq(USER_ID_1));
         List<Intent> capturedIntents = intentArgumentCaptor.getAllValues();
         assertEquals(capturedIntents.get(0).getAction(), Intent.ACTION_LOCKED_BOOT_COMPLETED);
         assertEquals(capturedIntents.get(1).getAction(), Intent.ACTION_BOOT_COMPLETED);
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java b/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java
index c0a38b8..09d3b48 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java
@@ -461,18 +461,18 @@
     @Test
     public void testPasswordData_serializeDeserialize() {
         PasswordData data = new PasswordData();
-        data.scryptN = 11;
-        data.scryptR = 22;
-        data.scryptP = 33;
+        data.scryptLogN = 11;
+        data.scryptLogR = 22;
+        data.scryptLogP = 33;
         data.credentialType = CREDENTIAL_TYPE_PASSWORD;
         data.salt = PAYLOAD;
         data.passwordHandle = PAYLOAD2;
 
         PasswordData deserialized = PasswordData.fromBytes(data.toBytes());
 
-        assertEquals(11, deserialized.scryptN);
-        assertEquals(22, deserialized.scryptR);
-        assertEquals(33, deserialized.scryptP);
+        assertEquals(11, deserialized.scryptLogN);
+        assertEquals(22, deserialized.scryptLogR);
+        assertEquals(33, deserialized.scryptLogP);
         assertEquals(CREDENTIAL_TYPE_PASSWORD, deserialized.credentialType);
         assertArrayEquals(PAYLOAD, deserialized.salt);
         assertArrayEquals(PAYLOAD2, deserialized.passwordHandle);
@@ -484,9 +484,9 @@
         // wire format.
         byte[] serialized = new byte[] {
                 0, 0, 0, 2, /* CREDENTIAL_TYPE_PASSWORD_OR_PIN */
-                11, /* scryptN */
-                22, /* scryptR */
-                33, /* scryptP */
+                11, /* scryptLogN */
+                22, /* scryptLogR */
+                33, /* scryptLogP */
                 0, 0, 0, 5, /* salt.length */
                 1, 2, -1, -2, 55, /* salt */
                 0, 0, 0, 6, /* passwordHandle.length */
@@ -494,9 +494,9 @@
         };
         PasswordData deserialized = PasswordData.fromBytes(serialized);
 
-        assertEquals(11, deserialized.scryptN);
-        assertEquals(22, deserialized.scryptR);
-        assertEquals(33, deserialized.scryptP);
+        assertEquals(11, deserialized.scryptLogN);
+        assertEquals(22, deserialized.scryptLogR);
+        assertEquals(33, deserialized.scryptLogP);
         assertEquals(CREDENTIAL_TYPE_PASSWORD_OR_PIN, deserialized.credentialType);
         assertArrayEquals(PAYLOAD, deserialized.salt);
         assertArrayEquals(PAYLOAD2, deserialized.passwordHandle);
@@ -567,6 +567,13 @@
         }
     }
 
+    @Test
+    public void testHexEncodingIsUppercase() {
+        final byte[] raw = new byte[] { (byte)0xAB, (byte)0xCD, (byte)0xEF };
+        final byte[] expected = new byte[] { 'A', 'B', 'C', 'D', 'E', 'F' };
+        assertArrayEquals(expected, SyntheticPasswordManager.bytesToHex(raw));
+    }
+
     // b/62213311
     //TODO: add non-migration work profile case, and unify/un-unify transition.
     //TODO: test token after user resets password
diff --git a/services/tests/servicestests/src/com/android/server/timezone/CheckTokenTest.java b/services/tests/servicestests/src/com/android/server/timezone/CheckTokenTest.java
deleted file mode 100644
index f7d282b..0000000
--- a/services/tests/servicestests/src/com/android/server/timezone/CheckTokenTest.java
+++ /dev/null
@@ -1,75 +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.timezone;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.fail;
-
-import androidx.test.filters.SmallTest;
-
-import org.junit.Test;
-
-import java.io.IOException;
-
-@SmallTest
-public class CheckTokenTest {
-
-    @Test
-    public void toByteArray() throws Exception {
-        PackageVersions packageVersions =
-                new PackageVersions(1 /* updateAppVersion */, 1 /* dataAppVersion */);
-        CheckToken originalToken = new CheckToken(1 /* optimisticLockId */, packageVersions);
-        assertEquals(originalToken, CheckToken.fromByteArray(originalToken.toByteArray()));
-    }
-
-    @Test
-    public void fromByteArray() {
-        PackageVersions packageVersions =
-                new PackageVersions(1 /* updateAppVersion */, 1 /* dataAppVersion */);
-        CheckToken token = new CheckToken(1, packageVersions);
-        byte[] validTokenBytes = token.toByteArray();
-        byte[] shortTokenBytes = new byte[validTokenBytes.length - 1];
-        System.arraycopy(validTokenBytes, 0, shortTokenBytes, 0, shortTokenBytes.length);
-
-        try {
-            CheckToken.fromByteArray(shortTokenBytes);
-            fail();
-        } catch (IOException expected) {}
-    }
-
-    @Test
-    public void equals() {
-        PackageVersions packageVersions1 =
-                new PackageVersions(1 /* updateAppVersion */, 1 /* dataAppVersion */);
-        PackageVersions packageVersions2 =
-                new PackageVersions(2 /* updateAppVersion */, 2 /* dataAppVersion */);
-        assertFalse(packageVersions1.equals(packageVersions2));
-
-        CheckToken baseline = new CheckToken(1, packageVersions1);
-        assertEquals(baseline, baseline);
-
-        CheckToken deepEqual = new CheckToken(1, packageVersions1);
-        assertEquals(baseline, deepEqual);
-
-        CheckToken differentOptimisticLockId = new CheckToken(2, packageVersions1);
-        assertFalse(differentOptimisticLockId.equals(baseline));
-
-        CheckToken differentPackageVersions = new CheckToken(1, packageVersions2);
-        assertFalse(differentPackageVersions.equals(baseline));
-    }
-}
diff --git a/services/tests/servicestests/src/com/android/server/timezone/PackageStatusStorageTest.java b/services/tests/servicestests/src/com/android/server/timezone/PackageStatusStorageTest.java
deleted file mode 100644
index 090db11..0000000
--- a/services/tests/servicestests/src/com/android/server/timezone/PackageStatusStorageTest.java
+++ /dev/null
@@ -1,271 +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.timezone;
-
-import static junit.framework.Assert.assertTrue;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.fail;
-
-import android.content.Context;
-
-import androidx.test.InstrumentationRegistry;
-import androidx.test.filters.SmallTest;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.io.StringWriter;
-
-@SmallTest
-public class PackageStatusStorageTest {
-    private static final PackageVersions VALID_PACKAGE_VERSIONS = new PackageVersions(1, 2);
-
-    private PackageStatusStorage mPackageStatusStorage;
-
-    @Before
-    public void setUp() throws Exception {
-        Context context = InstrumentationRegistry.getContext();
-        File dataDir = context.getFilesDir();
-
-        // Using the instrumentation context means the database is created in a test app-specific
-        // directory.
-        mPackageStatusStorage = new PackageStatusStorage(dataDir);
-        mPackageStatusStorage.initialize();
-    }
-
-    @After
-    public void tearDown() throws Exception {
-        mPackageStatusStorage.deleteFileForTests();
-    }
-
-    @Test
-    public void initialize_fail() {
-        File readOnlyDir = new File("/system/does/not/exist");
-        PackageStatusStorage packageStatusStorage = new PackageStatusStorage(readOnlyDir);
-        try {
-            packageStatusStorage.initialize();
-            fail();
-        } catch (IOException expected) {}
-    }
-
-    @Test
-    public void getPackageStatus_initialState() {
-        assertNull(mPackageStatusStorage.getPackageStatus());
-    }
-
-    @Test
-    public void resetCheckState() {
-        // Assert initial state.
-        assertNull(mPackageStatusStorage.getPackageStatus());
-
-        CheckToken token1 = mPackageStatusStorage.generateCheckToken(VALID_PACKAGE_VERSIONS);
-
-        // There should now be a state.
-        assertNotNull(mPackageStatusStorage.getPackageStatus());
-
-        // Now clear the state.
-        mPackageStatusStorage.resetCheckState();
-
-        // After reset, there should be no package state again.
-        assertNull(mPackageStatusStorage.getPackageStatus());
-
-        CheckToken token2 = mPackageStatusStorage.generateCheckToken(VALID_PACKAGE_VERSIONS);
-
-        // Token after a reset should still be distinct.
-        assertFalse(token1.equals(token2));
-
-        // Now clear the state again.
-        mPackageStatusStorage.resetCheckState();
-
-        // After reset, there should be no package state again.
-        assertNull(mPackageStatusStorage.getPackageStatus());
-
-        CheckToken token3 = mPackageStatusStorage.generateCheckToken(VALID_PACKAGE_VERSIONS);
-
-        // A CheckToken generated after a reset should still be distinct.
-        assertFalse(token2.equals(token3));
-    }
-
-    @Test
-    public void generateCheckToken_missingFileBehavior() {
-        // Assert initial state.
-        assertNull(mPackageStatusStorage.getPackageStatus());
-
-        CheckToken token1 = mPackageStatusStorage.generateCheckToken(VALID_PACKAGE_VERSIONS);
-        assertNotNull(token1);
-
-        // There should now be state.
-        assertNotNull(mPackageStatusStorage.getPackageStatus());
-
-        // Corrupt the data by removing the file.
-        mPackageStatusStorage.deleteFileForTests();
-
-        // Check that generateCheckToken recovers.
-        assertNotNull(mPackageStatusStorage.generateCheckToken(VALID_PACKAGE_VERSIONS));
-    }
-
-    @Test
-    public void getPackageStatus_missingFileBehavior() {
-        // Assert initial state.
-        assertNull(mPackageStatusStorage.getPackageStatus());
-
-        CheckToken token1 = mPackageStatusStorage.generateCheckToken(VALID_PACKAGE_VERSIONS);
-        assertNotNull(token1);
-
-        // There should now be a state.
-        assertNotNull(mPackageStatusStorage.getPackageStatus());
-
-        // Corrupt the data by removing the file.
-        mPackageStatusStorage.deleteFileForTests();
-
-        assertNull(mPackageStatusStorage.getPackageStatus());
-    }
-
-    @Test
-    public void markChecked_missingFileBehavior() {
-        // Assert initial state.
-        CheckToken token1 = mPackageStatusStorage.generateCheckToken(VALID_PACKAGE_VERSIONS);
-        assertNotNull(token1);
-
-        // There should now be a state.
-        assertNotNull(mPackageStatusStorage.getPackageStatus());
-
-        // Corrupt the data by removing the file.
-        mPackageStatusStorage.deleteFileForTests();
-
-        // The missing file should mean token1 is now considered invalid, so we should get a false.
-        assertFalse(mPackageStatusStorage.markChecked(token1, true /* succeeded */));
-
-        // The storage should have recovered and we should be able to carry on like before.
-        CheckToken token2 = mPackageStatusStorage.generateCheckToken(VALID_PACKAGE_VERSIONS);
-        assertTrue(mPackageStatusStorage.markChecked(token2, true /* succeeded */));
-    }
-
-    @Test
-    public void checkToken_tokenIsUnique() {
-        PackageVersions packageVersions = VALID_PACKAGE_VERSIONS;
-        PackageStatus expectedPackageStatus =
-                new PackageStatus(PackageStatus.CHECK_STARTED, packageVersions);
-
-        CheckToken token1 = mPackageStatusStorage.generateCheckToken(packageVersions);
-        assertEquals(packageVersions, token1.mPackageVersions);
-
-        PackageStatus actualPackageStatus1 = mPackageStatusStorage.getPackageStatus();
-        assertEquals(expectedPackageStatus, actualPackageStatus1);
-
-        CheckToken token2 = mPackageStatusStorage.generateCheckToken(packageVersions);
-        assertEquals(packageVersions, token1.mPackageVersions);
-        assertFalse(token1.mOptimisticLockId == token2.mOptimisticLockId);
-        assertFalse(token1.equals(token2));
-    }
-
-    @Test
-    public void markChecked_checkSucceeded() {
-        PackageVersions packageVersions = VALID_PACKAGE_VERSIONS;
-
-        CheckToken token = mPackageStatusStorage.generateCheckToken(packageVersions);
-        boolean writeOk = mPackageStatusStorage.markChecked(token, true /* succeeded */);
-        assertTrue(writeOk);
-
-        PackageStatus expectedPackageStatus =
-                new PackageStatus(PackageStatus.CHECK_COMPLETED_SUCCESS, packageVersions);
-        assertEquals(expectedPackageStatus, mPackageStatusStorage.getPackageStatus());
-    }
-
-    @Test
-    public void markChecked_checkFailed() {
-        PackageVersions packageVersions = VALID_PACKAGE_VERSIONS;
-
-        CheckToken token = mPackageStatusStorage.generateCheckToken(packageVersions);
-        boolean writeOk = mPackageStatusStorage.markChecked(token, false /* succeeded */);
-        assertTrue(writeOk);
-
-        PackageStatus expectedPackageStatus =
-                new PackageStatus(PackageStatus.CHECK_COMPLETED_FAILURE, packageVersions);
-        assertEquals(expectedPackageStatus, mPackageStatusStorage.getPackageStatus());
-    }
-
-    @Test
-    public void markChecked_optimisticLocking_multipleToken() {
-        PackageVersions packageVersions = VALID_PACKAGE_VERSIONS;
-        CheckToken token1 = mPackageStatusStorage.generateCheckToken(packageVersions);
-        CheckToken token2 = mPackageStatusStorage.generateCheckToken(packageVersions);
-
-        PackageStatus packageStatusBeforeChecked = mPackageStatusStorage.getPackageStatus();
-
-        boolean writeOk1 = mPackageStatusStorage.markChecked(token1, true /* succeeded */);
-        // Generation of token2 should mean that token1 is no longer valid.
-        assertFalse(writeOk1);
-        assertEquals(packageStatusBeforeChecked, mPackageStatusStorage.getPackageStatus());
-
-        boolean writeOk2 = mPackageStatusStorage.markChecked(token2, true /* succeeded */);
-        // token2 should still be valid, and the attempt with token1 should have had no effect.
-        assertTrue(writeOk2);
-        PackageStatus expectedPackageStatus =
-                new PackageStatus(PackageStatus.CHECK_COMPLETED_SUCCESS, packageVersions);
-        assertEquals(expectedPackageStatus, mPackageStatusStorage.getPackageStatus());
-    }
-
-    @Test
-    public void markChecked_optimisticLocking_repeatedTokenUse() {
-        PackageVersions packageVersions = VALID_PACKAGE_VERSIONS;
-        CheckToken token = mPackageStatusStorage.generateCheckToken(packageVersions);
-
-        boolean writeOk1 = mPackageStatusStorage.markChecked(token, true /* succeeded */);
-        assertTrue(writeOk1);
-
-        PackageStatus expectedPackageStatus =
-                new PackageStatus(PackageStatus.CHECK_COMPLETED_SUCCESS, packageVersions);
-        assertEquals(expectedPackageStatus, mPackageStatusStorage.getPackageStatus());
-
-        // token cannot be reused.
-        boolean writeOk2 = mPackageStatusStorage.markChecked(token, true /* succeeded */);
-        assertFalse(writeOk2);
-        assertEquals(expectedPackageStatus, mPackageStatusStorage.getPackageStatus());
-    }
-
-    @Test
-    public void dump() {
-        StringWriter stringWriter = new StringWriter();
-        PrintWriter printWriter = new PrintWriter(stringWriter);
-
-        // Dump initial state.
-        mPackageStatusStorage.dump(printWriter);
-
-        // No crash and it does something.
-        assertFalse(stringWriter.toString().isEmpty());
-
-        // Reset
-        stringWriter.getBuffer().setLength(0);
-        assertTrue(stringWriter.toString().isEmpty());
-
-        // Store something.
-        mPackageStatusStorage.generateCheckToken(VALID_PACKAGE_VERSIONS);
-
-        mPackageStatusStorage.dump(printWriter);
-
-        assertFalse(stringWriter.toString().isEmpty());
-    }
-}
diff --git a/services/tests/servicestests/src/com/android/server/timezone/PackageStatusTest.java b/services/tests/servicestests/src/com/android/server/timezone/PackageStatusTest.java
deleted file mode 100644
index 9b45f05..0000000
--- a/services/tests/servicestests/src/com/android/server/timezone/PackageStatusTest.java
+++ /dev/null
@@ -1,53 +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.timezone;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-
-import androidx.test.filters.SmallTest;
-
-import org.junit.Test;
-
-@SmallTest
-public class PackageStatusTest {
-
-    @Test
-    public void equals() {
-        PackageVersions packageVersions1 =
-                new PackageVersions(1 /* updateAppVersion */, 1 /* dataAppVersion */);
-        PackageVersions packageVersions2 =
-                new PackageVersions(2 /* updateAppVersion */, 1 /* dataAppVersion */);
-        assertFalse(packageVersions1.equals(packageVersions2));
-
-        PackageStatus baseline =
-                new PackageStatus(PackageStatus.CHECK_STARTED, packageVersions1);
-        assertEquals(baseline, baseline);
-
-        PackageStatus deepEqual =
-                new PackageStatus(PackageStatus.CHECK_STARTED, packageVersions1);
-        assertEquals(baseline, deepEqual);
-
-        PackageStatus differentStatus =
-                new PackageStatus(PackageStatus.CHECK_COMPLETED_SUCCESS, packageVersions1);
-        assertFalse(differentStatus.equals(baseline));
-
-        PackageStatus differentPackageVersions =
-                new PackageStatus(PackageStatus.CHECK_STARTED, packageVersions2);
-        assertFalse(differentPackageVersions.equals(baseline));
-    }
-}
diff --git a/services/tests/servicestests/src/com/android/server/timezone/PackageTrackerTest.java b/services/tests/servicestests/src/com/android/server/timezone/PackageTrackerTest.java
deleted file mode 100644
index 1356ea2..0000000
--- a/services/tests/servicestests/src/com/android/server/timezone/PackageTrackerTest.java
+++ /dev/null
@@ -1,1527 +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.timezone;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-import static org.mockito.Mockito.eq;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-import static org.mockito.hamcrest.MockitoHamcrest.argThat;
-
-import android.app.timezone.RulesUpdaterContract;
-import android.content.Context;
-import android.content.Intent;
-import android.provider.TimeZoneRulesDataContract;
-
-import androidx.test.InstrumentationRegistry;
-import androidx.test.filters.SmallTest;
-
-import org.hamcrest.BaseMatcher;
-import org.hamcrest.Description;
-import org.hamcrest.Matcher;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-import java.io.File;
-import java.io.PrintWriter;
-import java.io.StringWriter;
-import java.time.Clock;
-import java.time.Instant;
-import java.time.ZoneId;
-
-/**
- * White box interaction / unit testing of the {@link PackageTracker}.
- */
-@SmallTest
-public class PackageTrackerTest {
-    private static final String UPDATE_APP_PACKAGE_NAME = "updateAppPackageName";
-    private static final String DATA_APP_PACKAGE_NAME = "dataAppPackageName";
-    private static final PackageVersions INITIAL_APP_PACKAGE_VERSIONS =
-            new PackageVersions(2 /* updateAppVersion */, 2 /* dataAppVersion */);
-
-    private ConfigHelper mMockConfigHelper;
-    private PackageManagerHelper mMockPackageManagerHelper;
-
-    private FakeClock mFakeClock;
-    private FakeIntentHelper mFakeIntentHelper;
-    private PackageStatusStorage mPackageStatusStorage;
-    private PackageTracker mPackageTracker;
-
-    @Before
-    public void setUp() throws Exception {
-        Context context = InstrumentationRegistry.getContext();
-
-        mFakeClock = new FakeClock();
-
-        // Read-only interfaces so are easy to mock.
-        mMockConfigHelper = mock(ConfigHelper.class);
-        mMockPackageManagerHelper = mock(PackageManagerHelper.class);
-
-        // Using the instrumentation context means the database is created in a test app-specific
-        // directory. We can use the real thing for this test.
-        mPackageStatusStorage = new PackageStatusStorage(context.getFilesDir());
-
-        // For other interactions with the Android framework we create a fake object.
-        mFakeIntentHelper = new FakeIntentHelper();
-
-        // Create the PackageTracker to use in tests.
-        mPackageTracker = new PackageTracker(
-                mFakeClock,
-                mMockConfigHelper,
-                mMockPackageManagerHelper,
-                mPackageStatusStorage,
-                mFakeIntentHelper);
-    }
-
-    @After
-    public void tearDown() throws Exception {
-        if (mPackageStatusStorage != null) {
-            mPackageStatusStorage.deleteFileForTests();
-        }
-    }
-
-    @Test
-    public void trackingDisabled_intentHelperNotUsed() {
-        // Set up device configuration.
-        configureTrackingDisabled();
-
-        // Initialize the tracker.
-        assertFalse(mPackageTracker.start());
-
-        // Check the IntentHelper was not initialized.
-        mFakeIntentHelper.assertNotInitialized();
-
-        // Check reliability triggering state.
-        mFakeIntentHelper.assertReliabilityTriggerNotScheduled();
-    }
-
-    @Test
-    public void trackingDisabled_triggerUpdateIfNeededNotAllowed() {
-        // Set up device configuration.
-        configureTrackingDisabled();
-
-        // Initialize the tracker.
-        assertFalse(mPackageTracker.start());
-
-        // Check reliability triggering state.
-        mFakeIntentHelper.assertReliabilityTriggerNotScheduled();
-
-        try {
-            // This call should also not be allowed and will throw an exception if tracking is
-            // disabled.
-            mPackageTracker.triggerUpdateIfNeeded(true);
-            fail();
-        } catch (IllegalStateException expected) {}
-
-        // Check reliability triggering state.
-        mFakeIntentHelper.assertReliabilityTriggerNotScheduled();
-    }
-
-    @Test
-    public void trackingDisabled_unsolicitedResultsIgnored_withoutToken() {
-        // Set up device configuration.
-        configureTrackingDisabled();
-
-        // Initialize the tracker.
-        assertFalse(mPackageTracker.start());
-
-        // Check reliability triggering state.
-        mFakeIntentHelper.assertReliabilityTriggerNotScheduled();
-
-        // Receiving a check result when tracking is disabled should cause the storage to be
-        // reset.
-        mPackageTracker.recordCheckResult(null /* checkToken */, true /* success */);
-
-        // Check reliability triggering state.
-        mFakeIntentHelper.assertReliabilityTriggerNotScheduled();
-
-        // Assert the storage was reset.
-        checkPackageStorageStatusIsInitialOrReset();
-    }
-
-    @Test
-    public void trackingDisabled_unsolicitedResultsIgnored_withToken() {
-        // Set up device configuration.
-        configureTrackingDisabled();
-
-        // Set the storage into an arbitrary state so we can detect a reset.
-        mPackageStatusStorage.generateCheckToken(INITIAL_APP_PACKAGE_VERSIONS);
-
-        // Initialize the tracker.
-        assertFalse(mPackageTracker.start());
-
-        // Check reliability triggering state.
-        mFakeIntentHelper.assertReliabilityTriggerNotScheduled();
-
-        // Receiving a check result when tracking is disabled should cause the storage to be reset.
-        mPackageTracker.recordCheckResult(createArbitraryCheckToken(), true /* success */);
-
-        // Check reliability triggering state.
-        mFakeIntentHelper.assertReliabilityTriggerNotScheduled();
-
-        // Assert the storage was reset.
-        checkPackageStorageStatusIsInitialOrReset();
-    }
-
-    @Test
-    public void trackingEnabled_updateAppConfigMissing() throws Exception {
-        // Set up device configuration.
-        configureTrackingEnabled();
-        configureReliabilityConfigSettingsOk();
-        configureUpdateAppPackageNameMissing();
-        configureDataAppPackageOk(DATA_APP_PACKAGE_NAME);
-
-        try {
-            // Initialize the tracker.
-            mPackageTracker.start();
-            fail();
-        } catch (RuntimeException expected) {}
-
-        mFakeIntentHelper.assertNotInitialized();
-
-        // Check reliability triggering state.
-        mFakeIntentHelper.assertReliabilityTriggerNotScheduled();
-    }
-
-    @Test
-    public void trackingEnabled_updateAppNotPrivileged() throws Exception {
-        // Set up device configuration.
-        configureTrackingEnabled();
-        configureReliabilityConfigSettingsOk();
-        configureUpdateAppPackageNotPrivileged(UPDATE_APP_PACKAGE_NAME);
-        configureDataAppPackageOk(DATA_APP_PACKAGE_NAME);
-
-        try {
-            // Initialize the tracker.
-            mPackageTracker.start();
-            fail();
-        } catch (RuntimeException expected) {}
-
-        mFakeIntentHelper.assertNotInitialized();
-
-        // Check reliability triggering state.
-        mFakeIntentHelper.assertReliabilityTriggerNotScheduled();
-    }
-
-    @Test
-    public void trackingEnabled_dataAppConfigMissing() throws Exception {
-        // Set up device configuration.
-        configureTrackingEnabled();
-        configureReliabilityConfigSettingsOk();
-        configureUpdateAppPackageOk(UPDATE_APP_PACKAGE_NAME);
-        configureDataAppPackageNameMissing();
-
-        try {
-            // Initialize the tracker.
-            mPackageTracker.start();
-            fail();
-        } catch (RuntimeException expected) {}
-
-        mFakeIntentHelper.assertNotInitialized();
-
-        // Check reliability triggering state.
-        mFakeIntentHelper.assertReliabilityTriggerNotScheduled();
-    }
-
-    @Test
-    public void trackingEnabled_dataAppNotPrivileged() throws Exception {
-        // Set up device configuration.
-        configureTrackingEnabled();
-        configureReliabilityConfigSettingsOk();
-        configureUpdateAppPackageOk(UPDATE_APP_PACKAGE_NAME);
-        configureDataAppPackageNotPrivileged(DATA_APP_PACKAGE_NAME);
-
-        try {
-            // Initialize the tracker.
-            mPackageTracker.start();
-            fail();
-        } catch (RuntimeException expected) {}
-
-        mFakeIntentHelper.assertNotInitialized();
-
-        // Check reliability triggering state.
-        mFakeIntentHelper.assertReliabilityTriggerNotScheduled();
-     }
-
-    @Test
-    public void trackingEnabled_storageInitializationFails() throws Exception {
-        // Create a PackageStateStorage that will fail to initialize.
-        PackageStatusStorage packageStatusStorage =
-                new PackageStatusStorage(new File("/system/does/not/exist"));
-
-        // Create a new PackageTracker to use the bad storage.
-        mPackageTracker = new PackageTracker(
-                mFakeClock,
-                mMockConfigHelper,
-                mMockPackageManagerHelper,
-                packageStatusStorage,
-                mFakeIntentHelper);
-
-        // Set up device configuration.
-        configureTrackingEnabled();
-        configureReliabilityConfigSettingsOk();
-        configureValidApplications();
-
-        // Initialize the tracker.
-        assertFalse(mPackageTracker.start());
-
-        // Check the IntentHelper was not initialized.
-        mFakeIntentHelper.assertNotInitialized();
-
-        // Check reliability triggering state.
-        mFakeIntentHelper.assertReliabilityTriggerNotScheduled();
-    }
-
-    @Test
-    public void trackingEnabled_packageUpdate_badUpdateAppManifestEntry() throws Exception {
-        // Set up device configuration.
-        configureTrackingEnabled();
-        configureReliabilityConfigSettingsOk();
-        configureValidApplications();
-
-        // Initialize the tracker.
-        assertTrue(mPackageTracker.start());
-
-        // Check the intent helper is properly configured.
-        checkIntentHelperInitializedAndReliabilityTrackingEnabled();
-
-        // Check the initial storage state.
-        checkPackageStorageStatusIsInitialOrReset();
-
-        // Configure a bad manifest for the update app. Should effectively turn off tracking.
-        PackageVersions packageVersions =
-                new PackageVersions(2 /* updateAppPackageVersion */, 3 /* dataAppPackageVersion */);
-        configureUpdateAppManifestBad(UPDATE_APP_PACKAGE_NAME);
-        configureDataAppManifestOk(DATA_APP_PACKAGE_NAME);
-        configureUpdateAppPackageVersion(
-                UPDATE_APP_PACKAGE_NAME, packageVersions.mUpdateAppVersion);
-        configureDataAppPackageVersion(DATA_APP_PACKAGE_NAME, packageVersions.mDataAppVersion);
-        // Simulate a tracked package being updated.
-        mFakeIntentHelper.simulatePackageUpdatedEvent();
-
-        // Assert the PackageTracker did not attempt to trigger an update.
-        mFakeIntentHelper.assertUpdateNotTriggered();
-
-        // Check reliability triggering state.
-        mFakeIntentHelper.assertReliabilityTriggerNotScheduled();
-
-        // Assert the storage was not touched.
-        checkPackageStorageStatusIsInitialOrReset();
-    }
-
-    @Test
-    public void trackingEnabled_packageUpdate_badDataAppManifestEntry() throws Exception {
-        // Set up device configuration.
-        configureTrackingEnabled();
-        configureReliabilityConfigSettingsOk();
-        configureValidApplications();
-
-        // Initialize the tracker.
-        assertTrue(mPackageTracker.start());
-
-        // Check the intent helper is properly configured.
-        checkIntentHelperInitializedAndReliabilityTrackingEnabled();
-
-        // Check the initial storage state.
-        checkPackageStorageStatusIsInitialOrReset();
-
-        // Configure a bad manifest for the data app. Should effectively turn off tracking.
-        PackageVersions packageVersions =
-                new PackageVersions(2 /* updateAppPackageVersion */, 3 /* dataAppPackageVersion */);
-        configureUpdateAppManifestOk(UPDATE_APP_PACKAGE_NAME);
-        configureDataAppManifestBad(DATA_APP_PACKAGE_NAME);
-        configureUpdateAppPackageVersion(
-                UPDATE_APP_PACKAGE_NAME, packageVersions.mUpdateAppVersion);
-        configureDataAppPackageVersion(DATA_APP_PACKAGE_NAME, packageVersions.mDataAppVersion);
-        mFakeIntentHelper.simulatePackageUpdatedEvent();
-
-        // Assert the PackageTracker did not attempt to trigger an update.
-        mFakeIntentHelper.assertUpdateNotTriggered();
-
-        // Check reliability triggering state.
-        mFakeIntentHelper.assertReliabilityTriggerNotScheduled();
-
-        // Assert the storage was not touched.
-        checkPackageStorageStatusIsInitialOrReset();
-    }
-
-    @Test
-    public void trackingEnabled_packageUpdate_responseWithToken_success() throws Exception {
-        trackingEnabled_packageUpdate_responseWithToken(true);
-    }
-
-    @Test
-    public void trackingEnabled_packageUpdate_responseWithToken_failed() throws Exception {
-        trackingEnabled_packageUpdate_responseWithToken(false);
-    }
-
-    private void trackingEnabled_packageUpdate_responseWithToken(boolean success) throws Exception {
-        // Set up device configuration.
-        configureTrackingEnabled();
-        configureReliabilityConfigSettingsOk();
-        configureValidApplications();
-
-        // Initialize the tracker.
-        assertTrue(mPackageTracker.start());
-
-        // Check the intent helper is properly configured.
-        checkIntentHelperInitializedAndReliabilityTrackingEnabled();
-
-        // Check the initial storage state.
-        checkPackageStorageStatusIsInitialOrReset();
-
-        // Simulate a tracked package being updated.
-        PackageVersions packageVersions =
-                new PackageVersions(2 /* updateAppPackageVersion */, 3 /* dataAppPackageVersion */);
-        simulatePackageInstallation(packageVersions);
-
-        // Confirm an update was triggered.
-        checkUpdateCheckTriggered(packageVersions);
-
-        // Get the token that was passed to the intent helper, and pass it back.
-        CheckToken token = mFakeIntentHelper.captureAndResetLastToken();
-        mPackageTracker.recordCheckResult(token, success);
-
-        // Check storage and reliability triggering state.
-        if (success) {
-            checkUpdateCheckSuccessful(packageVersions);
-        } else {
-            checkUpdateCheckFailed(packageVersions);
-        }
-    }
-
-    @Test
-    public void trackingEnabled_packageUpdate_responseWithoutTokenCausesStorageReset_success()
-            throws Exception {
-        trackingEnabled_packageUpdate_responseWithoutTokenCausesStorageReset(true);
-    }
-
-    @Test
-    public void trackingEnabled_packageUpdate_responseWithoutTokenCausesStorageReset_failed()
-            throws Exception {
-        trackingEnabled_packageUpdate_responseWithoutTokenCausesStorageReset(false);
-    }
-
-    private void trackingEnabled_packageUpdate_responseWithoutTokenCausesStorageReset(
-            boolean success) throws Exception {
-        // Set up device configuration.
-        configureTrackingEnabled();
-        configureReliabilityConfigSettingsOk();
-        configureValidApplications();
-
-        // Initialize the tracker.
-        assertTrue(mPackageTracker.start());
-
-        // Check the intent helper is properly configured.
-        checkIntentHelperInitializedAndReliabilityTrackingEnabled();
-
-        // Check the initial storage state.
-        checkPackageStorageStatusIsInitialOrReset();
-
-        // Set up installed app versions / manifests.
-        PackageVersions packageVersions =
-                new PackageVersions(2 /* updateAppPackageVersion */, 3 /* dataAppPackageVersion */);
-        simulatePackageInstallation(packageVersions);
-
-        // Confirm an update was triggered.
-        checkUpdateCheckTriggered(packageVersions);
-
-        // Ignore the token that was given to the intent helper, just pass null.
-        mPackageTracker.recordCheckResult(null /* checkToken */, success);
-
-        // Check reliability triggering state.
-        mFakeIntentHelper.assertReliabilityTriggerScheduled();
-
-        // Assert the storage was reset.
-        checkPackageStorageStatusIsInitialOrReset();
-    }
-
-    /**
-     * Two package updates triggered for the same package versions. The second is triggered while
-     * the first is still happening.
-     */
-    @Test
-    public void trackingEnabled_packageUpdate_twoChecksNoPackageChange_secondWhileFirstInProgress()
-            throws Exception {
-        // Set up device configuration.
-        configureTrackingEnabled();
-        configureReliabilityConfigSettingsOk();
-        configureValidApplications();
-
-        // Initialize the tracker.
-        assertTrue(mPackageTracker.start());
-
-        // Check the intent helper is properly configured.
-        checkIntentHelperInitializedAndReliabilityTrackingEnabled();
-
-        // Check the initial storage state.
-        checkPackageStorageStatusIsInitialOrReset();
-
-        // Simulate package installation.
-        PackageVersions packageVersions =
-                new PackageVersions(2 /* updateAppPackageVersion */, 3 /* dataAppPackageVersion */);
-        simulatePackageInstallation(packageVersions);
-
-        // Confirm an update was triggered.
-        checkUpdateCheckTriggered(packageVersions);
-
-        // Get the first token.
-        CheckToken token1 = mFakeIntentHelper.captureAndResetLastToken();
-        assertEquals(packageVersions, token1.mPackageVersions);
-
-        // Now attempt to generate another check while the first is in progress and without having
-        // updated the package versions. The PackageTracker should trigger again for safety.
-        simulatePackageInstallation(packageVersions);
-
-        // Confirm an update was triggered.
-        checkUpdateCheckTriggered(packageVersions);
-
-        CheckToken token2 = mFakeIntentHelper.captureAndResetLastToken();
-        assertEquals(packageVersions, token2.mPackageVersions);
-        assertEquals(token1.mPackageVersions, token2.mPackageVersions);
-        assertTrue(token1.mOptimisticLockId != token2.mOptimisticLockId);
-    }
-
-    /**
-     * Two package updates triggered for the same package versions. The second happens after
-     * the first has succeeded.
-     */
-    @Test
-    public void trackingEnabled_packageUpdate_twoChecksNoPackageChange_sequential()
-            throws Exception {
-        // Set up device configuration.
-        configureTrackingEnabled();
-        configureReliabilityConfigSettingsOk();
-        configureValidApplications();
-
-        // Initialize the tracker.
-        assertTrue(mPackageTracker.start());
-
-        // Check the intent helper is properly configured.
-        checkIntentHelperInitializedAndReliabilityTrackingEnabled();
-
-        // Check the initial storage state.
-        checkPackageStorageStatusIsInitialOrReset();
-
-        // Simulate package installation.
-        PackageVersions packageVersions =
-                new PackageVersions(2 /* updateAppPackageVersion */, 3 /* dataAppPackageVersion */);
-        simulatePackageInstallation(packageVersions);
-
-        // Confirm an update was triggered.
-        checkUpdateCheckTriggered(packageVersions);
-
-        // Get the token.
-        CheckToken token = mFakeIntentHelper.captureAndResetLastToken();
-        assertEquals(packageVersions, token.mPackageVersions);
-
-        // Simulate a successful check.
-        mPackageTracker.recordCheckResult(token, true /* success */);
-
-        // Check storage and reliability triggering state.
-        checkUpdateCheckSuccessful(packageVersions);
-
-        // Now attempt to generate another check, but without having updated the package. The
-        // PackageTracker should be smart enough to recognize there's nothing to do here.
-        simulatePackageInstallation(packageVersions);
-
-        // Assert the PackageTracker did not attempt to trigger an update.
-        mFakeIntentHelper.assertUpdateNotTriggered();
-
-        // Check storage and reliability triggering state.
-        checkUpdateCheckSuccessful(packageVersions);
-    }
-
-    /**
-     * Two package updates triggered for the same package versions. The second is triggered after
-     * the first has failed.
-     */
-    @Test
-    public void trackingEnabled_packageUpdate_afterFailure() throws Exception {
-        // Set up device configuration.
-        configureTrackingEnabled();
-        configureReliabilityConfigSettingsOk();
-        configureValidApplications();
-
-        // Initialize the tracker.
-        assertTrue(mPackageTracker.start());
-
-        // Check the intent helper is properly configured.
-        checkIntentHelperInitializedAndReliabilityTrackingEnabled();
-
-        // Check the initial storage state.
-        checkPackageStorageStatusIsInitialOrReset();
-
-        // Simulate package installation.
-        PackageVersions packageVersions =
-                new PackageVersions(2 /* updateAppPackageVersion */, 3 /* dataAppPackageVersion */);
-        simulatePackageInstallation(packageVersions);
-
-        // Confirm an update was triggered.
-        checkUpdateCheckTriggered(packageVersions);
-
-        // Get the first token.
-        CheckToken token1 = mFakeIntentHelper.captureAndResetLastToken();
-        assertEquals(packageVersions, token1.mPackageVersions);
-
-        // Simulate an *unsuccessful* check.
-        mPackageTracker.recordCheckResult(token1, false /* success */);
-
-        // Check storage and reliability triggering state.
-        checkUpdateCheckFailed(packageVersions);
-
-        // Now generate another check, but without having updated the package. The
-        // PackageTracker should recognize the last check failed and trigger again.
-        simulatePackageInstallation(packageVersions);
-
-        // Confirm an update was triggered.
-        checkUpdateCheckTriggered(packageVersions);
-
-        // Get the second token.
-        CheckToken token2 = mFakeIntentHelper.captureAndResetLastToken();
-
-        // Assert some things about the tokens.
-        assertEquals(packageVersions, token2.mPackageVersions);
-        assertTrue(token1.mOptimisticLockId != token2.mOptimisticLockId);
-
-        // For completeness, now simulate this check was successful.
-        mPackageTracker.recordCheckResult(token2, true /* success */);
-
-        // Check storage and reliability triggering state.
-        checkUpdateCheckSuccessful(packageVersions);
-    }
-
-    /**
-     * Two package updates triggered for different package versions. The second is triggered while
-     * the first is still happening.
-     */
-    @Test
-    public void trackingEnabled_packageUpdate_twoChecksWithPackageChange_firstCheckInProcess()
-            throws Exception {
-        // Set up device configuration.
-        configureTrackingEnabled();
-        configureReliabilityConfigSettingsOk();
-        configureValidApplications();
-
-        // Initialize the package tracker.
-        assertTrue(mPackageTracker.start());
-
-        // Check the intent helper is properly configured.
-        checkIntentHelperInitializedAndReliabilityTrackingEnabled();
-
-        // Check the initial storage state.
-        checkPackageStorageStatusIsInitialOrReset();
-
-        // Simulate package installation.
-        PackageVersions packageVersions1 =
-                new PackageVersions(2 /* updateAppPackageVersion */, 3 /* dataAppPackageVersion */);
-        simulatePackageInstallation(packageVersions1);
-
-        // Confirm an update was triggered.
-        checkUpdateCheckTriggered(packageVersions1);
-
-        // Get the first token.
-        CheckToken token1 = mFakeIntentHelper.captureAndResetLastToken();
-        assertEquals(packageVersions1, token1.mPackageVersions);
-
-        // Simulate a tracked package being updated a second time (before the response for the
-        // first has been received).
-        PackageVersions packageVersions2 =
-                new PackageVersions(3 /* updateAppPackageVersion */, 4 /* dataAppPackageVersion */);
-        simulatePackageInstallation(packageVersions2);
-
-        // Confirm an update was triggered.
-        checkUpdateCheckTriggered(packageVersions2);
-
-        // Get the second token.
-        CheckToken token2 = mFakeIntentHelper.captureAndResetLastToken();
-        assertEquals(packageVersions2, token2.mPackageVersions);
-
-        // token1 should be invalid because the token2 was generated.
-        mPackageTracker.recordCheckResult(token1, true /* success */);
-
-        // Reliability triggering should still be enabled.
-        mFakeIntentHelper.assertReliabilityTriggerScheduled();
-
-        // Check the expected storage state.
-        checkPackageStorageStatus(PackageStatus.CHECK_STARTED, packageVersions2);
-
-        // token2 should still be accepted.
-        mPackageTracker.recordCheckResult(token2, true /* success */);
-
-        // Check storage and reliability triggering state.
-        checkUpdateCheckSuccessful(packageVersions2);
-    }
-
-    /**
-     * Two package updates triggered for different package versions. The second is triggered after
-     * the first has completed successfully.
-     */
-    @Test
-    public void trackingEnabled_packageUpdate_twoChecksWithPackageChange_sequential()
-            throws Exception {
-        // Set up device configuration.
-        configureTrackingEnabled();
-        configureReliabilityConfigSettingsOk();
-        configureValidApplications();
-
-        // Initialize the package tracker.
-        assertTrue(mPackageTracker.start());
-
-        // Check the intent helper is properly configured.
-        checkIntentHelperInitializedAndReliabilityTrackingEnabled();
-
-        // Check the initial storage state.
-        checkPackageStorageStatusIsInitialOrReset();
-
-        // Simulate package installation.
-        PackageVersions packageVersions1 =
-                new PackageVersions(2 /* updateAppPackageVersion */, 3 /* dataAppPackageVersion */);
-        simulatePackageInstallation(packageVersions1);
-
-        // Confirm an update was triggered.
-        checkUpdateCheckTriggered(packageVersions1);
-
-        // Get the first token.
-        CheckToken token1 = mFakeIntentHelper.captureAndResetLastToken();
-        assertEquals(packageVersions1, token1.mPackageVersions);
-
-        // token1 should be accepted.
-        mPackageTracker.recordCheckResult(token1, true /* success */);
-
-        // Check storage and reliability triggering state.
-        checkUpdateCheckSuccessful(packageVersions1);
-
-        // Simulate a tracked package being updated a second time.
-        PackageVersions packageVersions2 =
-                new PackageVersions(3 /* updateAppPackageVersion */, 4 /* dataAppPackageVersion */);
-        simulatePackageInstallation(packageVersions2);
-
-        // Confirm an update was triggered.
-        checkUpdateCheckTriggered(packageVersions2);
-
-        // Get the second token.
-        CheckToken token2 = mFakeIntentHelper.captureAndResetLastToken();
-        assertEquals(packageVersions2, token2.mPackageVersions);
-
-        // token2 should still be accepted.
-        mPackageTracker.recordCheckResult(token2, true /* success */);
-
-        // Check storage and reliability triggering state.
-        checkUpdateCheckSuccessful(packageVersions2);
-    }
-
-    /**
-     * Replaying the same token twice.
-     */
-    @Test
-    public void trackingEnabled_packageUpdate_sameTokenReplayFails() throws Exception {
-        // Set up device configuration.
-        configureTrackingEnabled();
-        configureReliabilityConfigSettingsOk();
-        configureValidApplications();
-
-        // Initialize the package tracker.
-        assertTrue(mPackageTracker.start());
-
-        // Check the intent helper is properly configured.
-        checkIntentHelperInitializedAndReliabilityTrackingEnabled();
-
-        // Check the initial storage state.
-        checkPackageStorageStatusIsInitialOrReset();
-
-        // Simulate package installation.
-        PackageVersions packageVersions1 =
-                new PackageVersions(2 /* updateAppPackageVersion */, 3 /* dataAppPackageVersion */);
-        simulatePackageInstallation(packageVersions1);
-
-        // Confirm an update was triggered.
-        checkUpdateCheckTriggered(packageVersions1);
-
-        // Get the first token.
-        CheckToken token1 = mFakeIntentHelper.captureAndResetLastToken();
-        assertEquals(packageVersions1, token1.mPackageVersions);
-
-        // token1 should be accepted.
-        mPackageTracker.recordCheckResult(token1, true /* success */);
-
-        // Check storage and reliability triggering state.
-        checkUpdateCheckSuccessful(packageVersions1);
-
-        // Apply token1 again.
-        mPackageTracker.recordCheckResult(token1, true /* success */);
-
-        // Check the expected storage state. No real way to tell if it has been updated, but
-        // we can check the final state is still what it should be.
-        checkPackageStorageStatus(PackageStatus.CHECK_COMPLETED_SUCCESS, packageVersions1);
-
-        // Under the covers we expect it to fail to update because the storage should recognize that
-        // the token is no longer valid.
-        mFakeIntentHelper.assertReliabilityTriggerScheduled();
-
-        // Peek inside the package tracker to make sure it is tracking failure counts properly.
-        assertEquals(1, mPackageTracker.getCheckFailureCountForTests());
-    }
-
-    @Test
-    public void trackingEnabled_reliabilityTrigger_firstTime_initialStorage() throws Exception {
-        // Set up device configuration.
-        configureTrackingEnabled();
-        configureReliabilityConfigSettingsOk();
-        PackageVersions packageVersions = configureValidApplications();
-
-        // Initialize the package tracker.
-        assertTrue(mPackageTracker.start());
-
-        // Check the intent helper is properly configured.
-        checkIntentHelperInitializedAndReliabilityTrackingEnabled();
-
-        // Check the initial storage state.
-        checkPackageStorageStatusIsInitialOrReset();
-
-        // Simulate a reliability trigger.
-        mPackageTracker.triggerUpdateIfNeeded(false /* packageChanged */);
-
-        // Assert the PackageTracker did trigger an update.
-        checkUpdateCheckTriggered(packageVersions);
-
-        // Confirm the token was correct.
-        CheckToken token1 = mFakeIntentHelper.captureAndResetLastToken();
-        assertEquals(packageVersions, token1.mPackageVersions);
-
-        // token1 should be accepted.
-        mPackageTracker.recordCheckResult(token1, true /* success */);
-
-        // Check storage and reliability triggering state.
-        checkUpdateCheckSuccessful(packageVersions);
-    }
-
-    @Test
-    public void trackingEnabled_reliabilityTrigger_afterRebootNoTriggerNeeded() throws Exception {
-        // Set up device configuration.
-        configureTrackingEnabled();
-        configureReliabilityConfigSettingsOk();
-        PackageVersions packageVersions = configureValidApplications();
-
-        // Force the storage into a state we want.
-        mPackageStatusStorage.forceCheckStateForTests(
-                PackageStatus.CHECK_COMPLETED_SUCCESS, packageVersions);
-
-        // Initialize the package tracker.
-        assertTrue(mPackageTracker.start());
-
-        // Check the intent helper is properly configured.
-        checkIntentHelperInitializedAndReliabilityTrackingEnabled();
-
-        // Check the initial storage state.
-        checkPackageStorageStatus(PackageStatus.CHECK_COMPLETED_SUCCESS, packageVersions);
-
-        // Simulate a reliability trigger.
-        mPackageTracker.triggerUpdateIfNeeded(false /* packageChanged */);
-
-        // Assert the PackageTracker did not attempt to trigger an update.
-        mFakeIntentHelper.assertUpdateNotTriggered();
-
-        // Check storage and reliability triggering state.
-        checkUpdateCheckSuccessful(packageVersions);
-    }
-
-    /**
-     * Simulates the device starting where the storage records do not match the installed app
-     * versions. The reliability trigger should cause the package tracker to perform a check.
-     */
-    @Test
-    public void trackingEnabled_reliabilityTrigger_afterRebootTriggerNeededBecausePreviousFailed()
-            throws Exception {
-        // Set up device configuration.
-        configureTrackingEnabled();
-        configureReliabilityConfigSettingsOk();
-
-        PackageVersions oldPackageVersions = new PackageVersions(1, 1);
-        PackageVersions currentPackageVersions = new PackageVersions(2, 2);
-
-        // Simulate there being a newer version installed than the one recorded in storage.
-        configureValidApplications(currentPackageVersions);
-
-        // Force the storage into a state we want.
-        mPackageStatusStorage.forceCheckStateForTests(
-                PackageStatus.CHECK_COMPLETED_FAILURE, oldPackageVersions);
-
-        // Initialize the package tracker.
-        assertTrue(mPackageTracker.start());
-
-        // Check the intent helper is properly configured.
-        checkIntentHelperInitializedAndReliabilityTrackingEnabled();
-
-        // Check the initial storage state.
-        checkPackageStorageStatus(PackageStatus.CHECK_COMPLETED_FAILURE, oldPackageVersions);
-
-        // Simulate a reliability trigger.
-        mPackageTracker.triggerUpdateIfNeeded(false /* packageChanged */);
-
-        // Assert the PackageTracker did trigger an update.
-        checkUpdateCheckTriggered(currentPackageVersions);
-
-        // Simulate the update check completing successfully.
-        CheckToken checkToken = mFakeIntentHelper.captureAndResetLastToken();
-        mPackageTracker.recordCheckResult(checkToken, true /* success */);
-
-        // Check storage and reliability triggering state.
-        checkUpdateCheckSuccessful(currentPackageVersions);
-    }
-
-    /**
-     * Simulates persistent failures of the reliability check. It should stop after the configured
-     * number of checks.
-     */
-    @Test
-    public void trackingEnabled_reliabilityTrigger_repeatedFailures() throws Exception {
-        // Set up device configuration.
-        configureTrackingEnabled();
-
-        int retriesAllowed = 3;
-        int checkDelayMillis = 5 * 60 * 1000;
-        configureReliabilityConfigSettings(retriesAllowed, checkDelayMillis);
-
-        PackageVersions oldPackageVersions = new PackageVersions(1, 1);
-        PackageVersions currentPackageVersions = new PackageVersions(2, 2);
-
-        // Simulate there being a newer version installed than the one recorded in storage.
-        configureValidApplications(currentPackageVersions);
-
-        // Force the storage into a state we want.
-        mPackageStatusStorage.forceCheckStateForTests(
-                PackageStatus.CHECK_COMPLETED_FAILURE, oldPackageVersions);
-
-        // Initialize the package tracker.
-        assertTrue(mPackageTracker.start());
-
-        // Check the intent helper is properly configured.
-        checkIntentHelperInitializedAndReliabilityTrackingEnabled();
-
-        // Check the initial storage state.
-        checkPackageStorageStatus(PackageStatus.CHECK_COMPLETED_FAILURE, oldPackageVersions);
-
-        for (int i = 0; i < retriesAllowed + 1; i++) {
-            // Simulate a reliability trigger.
-            mPackageTracker.triggerUpdateIfNeeded(false /* packageChanged */);
-
-            // Assert the PackageTracker did trigger an update.
-            checkUpdateCheckTriggered(currentPackageVersions);
-
-            // Check the PackageTracker failure count before calling recordCheckResult.
-            assertEquals(i, mPackageTracker.getCheckFailureCountForTests());
-
-            // Simulate a check failure.
-            CheckToken checkToken = mFakeIntentHelper.captureAndResetLastToken();
-            mPackageTracker.recordCheckResult(checkToken, false /* success */);
-
-            // Peek inside the package tracker to make sure it is tracking failure counts properly.
-            assertEquals(i + 1, mPackageTracker.getCheckFailureCountForTests());
-
-            // Confirm nothing has changed.
-            mFakeIntentHelper.assertUpdateNotTriggered();
-            checkPackageStorageStatus(PackageStatus.CHECK_COMPLETED_FAILURE,
-                    currentPackageVersions);
-
-            // Check reliability triggering is in the correct state.
-            if (i <= retriesAllowed) {
-                mFakeIntentHelper.assertReliabilityTriggerScheduled();
-            } else {
-                mFakeIntentHelper.assertReliabilityTriggerNotScheduled();
-            }
-        }
-    }
-
-    @Test
-    public void trackingEnabled_reliabilityTrigger_failureCountIsReset() throws Exception {
-        // Set up device configuration.
-        configureTrackingEnabled();
-
-        int retriesAllowed = 3;
-        int checkDelayMillis = 5 * 60 * 1000;
-        configureReliabilityConfigSettings(retriesAllowed, checkDelayMillis);
-
-        PackageVersions oldPackageVersions = new PackageVersions(1, 1);
-        PackageVersions currentPackageVersions = new PackageVersions(2, 2);
-
-        // Simulate there being a newer version installed than the one recorded in storage.
-        configureValidApplications(currentPackageVersions);
-
-        // Force the storage into a state we want.
-        mPackageStatusStorage.forceCheckStateForTests(
-                PackageStatus.CHECK_COMPLETED_FAILURE, oldPackageVersions);
-
-        // Initialize the package tracker.
-        assertTrue(mPackageTracker.start());
-
-        // Check the intent helper is properly configured.
-        checkIntentHelperInitializedAndReliabilityTrackingEnabled();
-
-        // Check the initial storage state.
-        checkPackageStorageStatus(PackageStatus.CHECK_COMPLETED_FAILURE, oldPackageVersions);
-
-        // Fail (retries - 1) times.
-        for (int i = 0; i < retriesAllowed - 1; i++) {
-            // Simulate a reliability trigger.
-            mPackageTracker.triggerUpdateIfNeeded(false /* packageChanged */);
-
-            // Assert the PackageTracker did trigger an update.
-            checkUpdateCheckTriggered(currentPackageVersions);
-
-            // Check the PackageTracker failure count before calling recordCheckResult.
-            assertEquals(i, mPackageTracker.getCheckFailureCountForTests());
-
-            // Simulate a check failure.
-            CheckToken checkToken = mFakeIntentHelper.captureAndResetLastToken();
-            mPackageTracker.recordCheckResult(checkToken, false /* success */);
-
-            // Peek inside the package tracker to make sure it is tracking failure counts properly.
-            assertEquals(i + 1, mPackageTracker.getCheckFailureCountForTests());
-
-            // Confirm nothing has changed.
-            mFakeIntentHelper.assertUpdateNotTriggered();
-            checkPackageStorageStatus(PackageStatus.CHECK_COMPLETED_FAILURE,
-                    currentPackageVersions);
-
-            // Check reliability triggering is still enabled.
-            mFakeIntentHelper.assertReliabilityTriggerScheduled();
-        }
-
-        // Simulate a reliability trigger.
-        mPackageTracker.triggerUpdateIfNeeded(false /* packageChanged */);
-
-        // Assert the PackageTracker did trigger an update.
-        checkUpdateCheckTriggered(currentPackageVersions);
-
-        // Check the PackageTracker failure count before calling recordCheckResult.
-        assertEquals(retriesAllowed - 1, mPackageTracker.getCheckFailureCountForTests());
-
-        // On the last possible try, succeed.
-        CheckToken checkToken = mFakeIntentHelper.captureAndResetLastToken();
-        mPackageTracker.recordCheckResult(checkToken, true /* success */);
-
-        checkUpdateCheckSuccessful(currentPackageVersions);
-    }
-
-    /**
-     * Simulates reliability triggers happening too close together. Package tracker should ignore
-     * the ones it doesn't need.
-     */
-    @Test
-    public void trackingEnabled_reliabilityTrigger_tooSoon() throws Exception {
-        // Set up device configuration.
-        configureTrackingEnabled();
-
-        int retriesAllowed = 5;
-        int checkDelayMillis = 5 * 60 * 1000;
-        configureReliabilityConfigSettings(retriesAllowed, checkDelayMillis);
-
-        PackageVersions oldPackageVersions = new PackageVersions(1, 1);
-        PackageVersions currentPackageVersions = new PackageVersions(2, 2);
-
-        // Simulate there being a newer version installed than the one recorded in storage.
-        configureValidApplications(currentPackageVersions);
-
-        // Force the storage into a state we want.
-        mPackageStatusStorage.forceCheckStateForTests(
-                PackageStatus.CHECK_COMPLETED_FAILURE, oldPackageVersions);
-
-        // Initialize the package tracker.
-        assertTrue(mPackageTracker.start());
-
-        // Check the intent helper is properly configured.
-        checkIntentHelperInitializedAndReliabilityTrackingEnabled();
-
-        // Check the initial storage state.
-        checkPackageStorageStatus(PackageStatus.CHECK_COMPLETED_FAILURE, oldPackageVersions);
-
-        // Simulate a reliability trigger.
-        mPackageTracker.triggerUpdateIfNeeded(false /* packageChanged */);
-
-        // Assert the PackageTracker did trigger an update.
-        checkUpdateCheckTriggered(currentPackageVersions);
-        CheckToken token1 = mFakeIntentHelper.captureAndResetLastToken();
-
-        // Increment the clock, but not enough.
-        mFakeClock.incrementClock(checkDelayMillis - 1);
-
-        // Simulate a reliability trigger.
-        mPackageTracker.triggerUpdateIfNeeded(false /* packageChanged */);
-
-        // Assert the PackageTracker did not trigger an update.
-        mFakeIntentHelper.assertUpdateNotTriggered();
-        checkPackageStorageStatus(PackageStatus.CHECK_STARTED, currentPackageVersions);
-        mFakeIntentHelper.assertReliabilityTriggerScheduled();
-
-        // Increment the clock slightly more. Should now consider the response overdue.
-        mFakeClock.incrementClock(2);
-
-        // Simulate a reliability trigger.
-        mPackageTracker.triggerUpdateIfNeeded(false /* packageChanged */);
-
-        // Triggering should have happened.
-        checkUpdateCheckTriggered(currentPackageVersions);
-        CheckToken token2 = mFakeIntentHelper.captureAndResetLastToken();
-
-        // Check a new token was generated.
-        assertFalse(token1.equals(token2));
-    }
-
-    /**
-     * Tests what happens when a package update doesn't complete and a reliability trigger cleans
-     * up for it.
-     */
-    @Test
-    public void trackingEnabled_reliabilityTrigger_afterPackageUpdateDidNotComplete()
-            throws Exception {
-
-        // Set up device configuration.
-        configureTrackingEnabled();
-
-        int retriesAllowed = 5;
-        int checkDelayMillis = 5 * 60 * 1000;
-        configureReliabilityConfigSettings(retriesAllowed, checkDelayMillis);
-
-        PackageVersions currentPackageVersions = new PackageVersions(1, 1);
-        PackageVersions newPackageVersions = new PackageVersions(2, 2);
-
-        // Simulate there being a newer version installed than the one recorded in storage.
-        configureValidApplications(currentPackageVersions);
-
-        // Force the storage into a state we want.
-        mPackageStatusStorage.forceCheckStateForTests(
-                PackageStatus.CHECK_COMPLETED_SUCCESS, currentPackageVersions);
-
-        // Initialize the package tracker.
-        assertTrue(mPackageTracker.start());
-
-        // Check the intent helper is properly configured.
-        checkIntentHelperInitializedAndReliabilityTrackingEnabled();
-
-        // Simulate a reliability trigger.
-        simulatePackageInstallation(newPackageVersions);
-
-        // Assert the PackageTracker did trigger an update.
-        checkUpdateCheckTriggered(newPackageVersions);
-        CheckToken token1 = mFakeIntentHelper.captureAndResetLastToken();
-
-        // Increment the clock, but not enough.
-        mFakeClock.incrementClock(checkDelayMillis + 1);
-
-        // Simulate a reliability trigger.
-        mPackageTracker.triggerUpdateIfNeeded(false /* packageChanged */);
-
-        // Assert the PackageTracker triggered an update.
-        checkUpdateCheckTriggered(newPackageVersions);
-        CheckToken token2 = mFakeIntentHelper.captureAndResetLastToken();
-
-        // Check a new token was generated.
-        assertFalse(token1.equals(token2));
-
-        // Simulate the reliability check completing.
-        mPackageTracker.recordCheckResult(token2, true /* success */);
-
-        // Check everything is now as it should be.
-        checkUpdateCheckSuccessful(newPackageVersions);
-    }
-
-    /**
-     * Simulates a reliability trigger happening too soon after a package update trigger occurred.
-     */
-    @Test
-    public void trackingEnabled_reliabilityTriggerAfterUpdate_tooSoon() throws Exception {
-        // Set up device configuration.
-        configureTrackingEnabled();
-
-        int retriesAllowed = 5;
-        int checkDelayMillis = 5 * 60 * 1000;
-        configureReliabilityConfigSettings(retriesAllowed, checkDelayMillis);
-
-        PackageVersions currentPackageVersions = new PackageVersions(1, 1);
-        PackageVersions newPackageVersions = new PackageVersions(2, 2);
-
-        // Simulate there being a newer version installed than the one recorded in storage.
-        configureValidApplications(currentPackageVersions);
-
-        // Force the storage into a state we want.
-        mPackageStatusStorage.forceCheckStateForTests(
-                PackageStatus.CHECK_COMPLETED_SUCCESS, currentPackageVersions);
-
-        // Initialize the package tracker.
-        assertTrue(mPackageTracker.start());
-
-        // Check the intent helper is properly configured.
-        checkIntentHelperInitializedAndReliabilityTrackingEnabled();
-
-        // Check the initial storage state.
-        checkPackageStorageStatus(PackageStatus.CHECK_COMPLETED_SUCCESS, currentPackageVersions);
-
-        // Simulate a package update trigger.
-        simulatePackageInstallation(newPackageVersions);
-
-        // Assert the PackageTracker did trigger an update.
-        checkUpdateCheckTriggered(newPackageVersions);
-        CheckToken token1 = mFakeIntentHelper.captureAndResetLastToken();
-
-        // Increment the clock, but not enough.
-        mFakeClock.incrementClock(checkDelayMillis - 1);
-
-        // Simulate a reliability trigger.
-        mPackageTracker.triggerUpdateIfNeeded(false /* packageChanged */);
-
-        // Assert the PackageTracker did not trigger an update.
-        mFakeIntentHelper.assertUpdateNotTriggered();
-        checkPackageStorageStatus(PackageStatus.CHECK_STARTED, newPackageVersions);
-        mFakeIntentHelper.assertReliabilityTriggerScheduled();
-
-        // Increment the clock slightly more. Should now consider the response overdue.
-        mFakeClock.incrementClock(2);
-
-        // Simulate a reliability trigger.
-        mPackageTracker.triggerUpdateIfNeeded(false /* packageChanged */);
-
-        // Triggering should have happened.
-        checkUpdateCheckTriggered(newPackageVersions);
-        CheckToken token2 = mFakeIntentHelper.captureAndResetLastToken();
-
-        // Check a new token was generated.
-        assertFalse(token1.equals(token2));
-    }
-
-    @Test
-    public void dump() {
-        StringWriter stringWriter = new StringWriter();
-        PrintWriter printWriter = new PrintWriter(stringWriter);
-
-        mPackageTracker.dump(printWriter);
-
-        assertFalse(stringWriter.toString().isEmpty());
-    }
-
-    private void simulatePackageInstallation(PackageVersions packageVersions) throws Exception {
-        configureApplicationsValidManifests(packageVersions);
-
-        // Simulate a tracked package being updated.
-        mFakeIntentHelper.simulatePackageUpdatedEvent();
-    }
-
-    /**
-     * Checks an update check was triggered, reliability triggering is therefore enabled and the
-     * storage state reflects that there is a check in progress.
-     */
-    private void checkUpdateCheckTriggered(PackageVersions packageVersions) {
-        // Assert the PackageTracker attempted to trigger an update.
-        mFakeIntentHelper.assertUpdateTriggered();
-
-        // If an update check was triggered reliability triggering should always be enabled to
-        // ensure that it can be completed if it fails.
-        mFakeIntentHelper.assertReliabilityTriggerScheduled();
-
-        // Check the expected storage state.
-        checkPackageStorageStatus(PackageStatus.CHECK_STARTED, packageVersions);
-    }
-
-    private void checkUpdateCheckFailed(PackageVersions packageVersions) {
-        // Check reliability triggering state.
-        mFakeIntentHelper.assertReliabilityTriggerScheduled();
-
-        // Assert the storage was updated.
-        checkPackageStorageStatus(PackageStatus.CHECK_COMPLETED_FAILURE, packageVersions);
-    }
-
-    private void checkUpdateCheckSuccessful(PackageVersions packageVersions) {
-        // Check reliability triggering state.
-        mFakeIntentHelper.assertReliabilityTriggerNotScheduled();
-
-        // Assert the storage was updated.
-        checkPackageStorageStatus(PackageStatus.CHECK_COMPLETED_SUCCESS, packageVersions);
-
-        // Peek inside the package tracker to make sure it is tracking failure counts properly.
-        assertEquals(0, mPackageTracker.getCheckFailureCountForTests());
-    }
-
-    private PackageVersions configureValidApplications() throws Exception {
-        configureValidApplications(INITIAL_APP_PACKAGE_VERSIONS);
-        return INITIAL_APP_PACKAGE_VERSIONS;
-    }
-
-    private void configureValidApplications(PackageVersions versions) throws Exception {
-        configureUpdateAppPackageOk(UPDATE_APP_PACKAGE_NAME);
-        configureDataAppPackageOk(DATA_APP_PACKAGE_NAME);
-        configureApplicationsValidManifests(versions);
-    }
-
-    private void configureApplicationsValidManifests(PackageVersions versions) throws Exception {
-        configureUpdateAppManifestOk(UPDATE_APP_PACKAGE_NAME);
-        configureDataAppManifestOk(DATA_APP_PACKAGE_NAME);
-        configureUpdateAppPackageVersion(UPDATE_APP_PACKAGE_NAME, versions.mUpdateAppVersion);
-        configureDataAppPackageVersion(DATA_APP_PACKAGE_NAME, versions.mDataAppVersion);
-    }
-
-    private void configureUpdateAppPackageVersion(String updateAppPackageName,
-            long updataAppPackageVersion) throws Exception {
-        when(mMockPackageManagerHelper.getInstalledPackageVersion(updateAppPackageName))
-                .thenReturn(updataAppPackageVersion);
-    }
-
-    private void configureDataAppPackageVersion(String dataAppPackageName,
-            long dataAppPackageVersion) throws Exception {
-        when(mMockPackageManagerHelper.getInstalledPackageVersion(dataAppPackageName))
-                .thenReturn(dataAppPackageVersion);
-    }
-
-    private void configureUpdateAppManifestOk(String updateAppPackageName) throws Exception {
-        Intent expectedIntent = RulesUpdaterContract.createUpdaterIntent(updateAppPackageName);
-        when(mMockPackageManagerHelper.receiverRegistered(
-                filterEquals(expectedIntent),
-                eq(RulesUpdaterContract.TRIGGER_TIME_ZONE_RULES_CHECK_PERMISSION)))
-                .thenReturn(true);
-        when(mMockPackageManagerHelper.usesPermission(
-                updateAppPackageName, RulesUpdaterContract.UPDATE_TIME_ZONE_RULES_PERMISSION))
-                .thenReturn(true);
-    }
-
-    private void configureUpdateAppManifestBad(String updateAppPackageName) throws Exception {
-        Intent expectedIntent = RulesUpdaterContract.createUpdaterIntent(updateAppPackageName);
-        when(mMockPackageManagerHelper.receiverRegistered(
-                filterEquals(expectedIntent),
-                eq(RulesUpdaterContract.TRIGGER_TIME_ZONE_RULES_CHECK_PERMISSION)))
-                .thenReturn(false);
-        // Has permission, but that shouldn't matter if the check above is false.
-        when(mMockPackageManagerHelper.usesPermission(
-                updateAppPackageName, RulesUpdaterContract.UPDATE_TIME_ZONE_RULES_PERMISSION))
-                .thenReturn(true);
-    }
-
-    private void configureDataAppManifestOk(String dataAppPackageName) throws Exception {
-        when(mMockPackageManagerHelper.contentProviderRegistered(
-                TimeZoneRulesDataContract.AUTHORITY, dataAppPackageName))
-                .thenReturn(true);
-    }
-
-    private void configureDataAppManifestBad(String dataAppPackageName) throws Exception {
-        // Simulate the data app not exposing the content provider we require.
-        when(mMockPackageManagerHelper.contentProviderRegistered(
-                TimeZoneRulesDataContract.AUTHORITY, dataAppPackageName))
-                .thenReturn(false);
-    }
-
-    private void configureTrackingEnabled() {
-        when(mMockConfigHelper.isTrackingEnabled()).thenReturn(true);
-    }
-
-    private void configureTrackingDisabled() {
-        when(mMockConfigHelper.isTrackingEnabled()).thenReturn(false);
-    }
-
-    private void configureReliabilityConfigSettings(int retriesAllowed, int checkDelayMillis) {
-        when(mMockConfigHelper.getFailedCheckRetryCount()).thenReturn(retriesAllowed);
-        when(mMockConfigHelper.getCheckTimeAllowedMillis()).thenReturn(checkDelayMillis);
-    }
-
-    private void configureReliabilityConfigSettingsOk() {
-        configureReliabilityConfigSettings(5, 5 * 60 * 1000);
-    }
-
-    private void configureUpdateAppPackageOk(String updateAppPackageName) throws Exception {
-        when(mMockConfigHelper.getUpdateAppPackageName()).thenReturn(updateAppPackageName);
-        when(mMockPackageManagerHelper.isPrivilegedApp(updateAppPackageName)).thenReturn(true);
-    }
-
-    private void configureUpdateAppPackageNotPrivileged(String updateAppPackageName)
-            throws Exception {
-        when(mMockConfigHelper.getUpdateAppPackageName()).thenReturn(updateAppPackageName);
-        when(mMockPackageManagerHelper.isPrivilegedApp(updateAppPackageName)).thenReturn(false);
-    }
-
-    private void configureUpdateAppPackageNameMissing() {
-        when(mMockConfigHelper.getUpdateAppPackageName()).thenReturn(null);
-    }
-
-    private void configureDataAppPackageOk(String dataAppPackageName) throws Exception {
-        when(mMockConfigHelper.getDataAppPackageName()).thenReturn(dataAppPackageName);
-        when(mMockPackageManagerHelper.isPrivilegedApp(dataAppPackageName)).thenReturn(true);
-    }
-
-    private void configureDataAppPackageNotPrivileged(String dataAppPackageName)
-            throws Exception {
-        when(mMockConfigHelper.getUpdateAppPackageName()).thenReturn(dataAppPackageName);
-        when(mMockPackageManagerHelper.isPrivilegedApp(dataAppPackageName)).thenReturn(false);
-    }
-
-    private void configureDataAppPackageNameMissing() {
-        when(mMockConfigHelper.getDataAppPackageName()).thenThrow(new RuntimeException());
-    }
-
-    private void checkIntentHelperInitializedAndReliabilityTrackingEnabled() {
-        // Verify that calling start initialized the IntentHelper as well.
-        mFakeIntentHelper.assertInitialized(UPDATE_APP_PACKAGE_NAME, DATA_APP_PACKAGE_NAME);
-
-        // Assert that reliability tracking is always enabled after initialization.
-        mFakeIntentHelper.assertReliabilityTriggerScheduled();
-    }
-
-    private void checkPackageStorageStatus(
-            int expectedCheckStatus, PackageVersions expectedPackageVersions) {
-        PackageStatus packageStatus = mPackageStatusStorage.getPackageStatus();
-        assertEquals(expectedCheckStatus, packageStatus.mCheckStatus);
-        assertEquals(expectedPackageVersions, packageStatus.mVersions);
-    }
-
-    private void checkPackageStorageStatusIsInitialOrReset() {
-        assertNull(mPackageStatusStorage.getPackageStatus());
-    }
-
-    private static CheckToken createArbitraryCheckToken() {
-        return new CheckToken(1, INITIAL_APP_PACKAGE_VERSIONS);
-    }
-
-    /**
-     * A fake IntentHelper implementation for use in tests.
-     */
-    private static class FakeIntentHelper implements PackageTrackerIntentHelper {
-
-        private PackageTracker mPackageTracker;
-        private String mUpdateAppPackageName;
-        private String mDataAppPackageName;
-
-        private CheckToken mLastToken;
-
-        private boolean mReliabilityTriggerScheduled;
-
-        @Override
-        public void initialize(String updateAppPackageName, String dataAppPackageName,
-                PackageTracker packageTracker) {
-            assertNotNull(updateAppPackageName);
-            assertNotNull(dataAppPackageName);
-            assertNotNull(packageTracker);
-            mPackageTracker = packageTracker;
-            mUpdateAppPackageName = updateAppPackageName;
-            mDataAppPackageName = dataAppPackageName;
-        }
-
-        public void assertInitialized(
-                String expectedUpdateAppPackageName, String expectedDataAppPackageName) {
-            assertNotNull(mPackageTracker);
-            assertEquals(expectedUpdateAppPackageName, mUpdateAppPackageName);
-            assertEquals(expectedDataAppPackageName, mDataAppPackageName);
-        }
-
-        public void assertNotInitialized() {
-            assertNull(mPackageTracker);
-        }
-
-        @Override
-        public void sendTriggerUpdateCheck(CheckToken checkToken) {
-            if (mLastToken != null) {
-                fail("lastToken already set");
-            }
-            mLastToken = checkToken;
-        }
-
-        @Override
-        public void scheduleReliabilityTrigger(long minimumDelayMillis) {
-            mReliabilityTriggerScheduled = true;
-        }
-
-        @Override
-        public void unscheduleReliabilityTrigger() {
-            mReliabilityTriggerScheduled = false;
-        }
-
-        public void assertReliabilityTriggerScheduled() {
-            assertTrue(mReliabilityTriggerScheduled);
-        }
-
-        public void assertReliabilityTriggerNotScheduled() {
-            assertFalse(mReliabilityTriggerScheduled);
-        }
-
-        public void assertUpdateTriggered() {
-            assertNotNull(mLastToken);
-        }
-
-        public void assertUpdateNotTriggered() {
-            assertNull(mLastToken);
-        }
-
-        public CheckToken captureAndResetLastToken() {
-            CheckToken toReturn = mLastToken;
-            assertNotNull("No update triggered", toReturn);
-            mLastToken = null;
-            return toReturn;
-        }
-
-        public void simulatePackageUpdatedEvent() {
-            mPackageTracker.triggerUpdateIfNeeded(true /* packageChanged */);
-        }
-    }
-
-    private static class FakeClock extends Clock {
-
-        private long currentTime = 1000;
-
-        @Override
-        public long millis() {
-            return currentTime;
-        }
-
-        public void incrementClock(long millis) {
-            currentTime += millis;
-        }
-
-        @Override
-        public ZoneId getZone() {
-            throw new UnsupportedOperationException();
-        }
-
-        @Override
-        public Clock withZone(ZoneId zone) {
-            throw new UnsupportedOperationException();
-        }
-
-        @Override
-        public Instant instant() {
-            throw new UnsupportedOperationException();
-        }
-    }
-
-    /**
-     * Registers a mockito parameter matcher that uses {@link Intent#filterEquals(Intent)}. to
-     * check the parameter against the intent supplied.
-     */
-    private static Intent filterEquals(final Intent expected) {
-        final Matcher<Intent> m = new BaseMatcher<Intent>() {
-            @Override
-            public boolean matches(Object actual) {
-                return actual != null && expected.filterEquals((Intent) actual);
-            }
-            @Override
-            public void describeTo(Description description) {
-                description.appendText(expected.toString());
-            }
-        };
-        return argThat(m);
-    }
-}
diff --git a/services/tests/servicestests/src/com/android/server/timezone/PackageVersionsTest.java b/services/tests/servicestests/src/com/android/server/timezone/PackageVersionsTest.java
deleted file mode 100644
index 9ffc4e9..0000000
--- a/services/tests/servicestests/src/com/android/server/timezone/PackageVersionsTest.java
+++ /dev/null
@@ -1,47 +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.timezone;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-
-import androidx.test.filters.SmallTest;
-
-import org.junit.Test;
-
-@SmallTest
-public class PackageVersionsTest {
-
-    @Test
-    public void equals() {
-        PackageVersions baseline =
-                new PackageVersions(1 /* updateAppVersion */, 1 /* dataAppVersion */);
-        assertEquals(baseline, baseline);
-
-        PackageVersions deepEqual =
-                new PackageVersions(1 /* updateAppVersion */, 1 /* dataAppVersion */);
-        assertEquals(baseline, deepEqual);
-
-        PackageVersions differentUpdateAppVersion =
-                new PackageVersions(2 /* updateAppVersion */, 1 /* dataAppVersion */);
-        assertFalse(baseline.equals(differentUpdateAppVersion));
-
-        PackageVersions differentDataAppVersion =
-                new PackageVersions(1 /* updateAppVersion */, 2 /* dataAppVersion */);
-        assertFalse(baseline.equals(differentDataAppVersion));
-    }
-}
diff --git a/services/tests/servicestests/src/com/android/server/timezone/RulesManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/timezone/RulesManagerServiceTest.java
deleted file mode 100644
index 2c4c4d0..0000000
--- a/services/tests/servicestests/src/com/android/server/timezone/RulesManagerServiceTest.java
+++ /dev/null
@@ -1,1107 +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.timezone;
-
-import static com.android.server.timezone.RulesManagerService.REQUIRED_QUERY_PERMISSION;
-import static com.android.server.timezone.RulesManagerService.REQUIRED_UPDATER_PERMISSION;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.doThrow;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.reset;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyNoMoreInteractions;
-import static org.mockito.Mockito.verifyZeroInteractions;
-import static org.mockito.Mockito.when;
-
-import android.app.timezone.Callback;
-import android.app.timezone.DistroRulesVersion;
-import android.app.timezone.ICallback;
-import android.app.timezone.RulesManager;
-import android.app.timezone.RulesState;
-import android.os.ParcelFileDescriptor;
-
-import com.android.i18n.timezone.TzDataSetVersion;
-import com.android.timezone.distro.DistroVersion;
-import com.android.timezone.distro.StagedDistroOperation;
-import com.android.timezone.distro.TimeZoneDistro;
-import com.android.timezone.distro.installer.TimeZoneDistroInstaller;
-
-import libcore.io.IoUtils;
-
-import org.junit.Before;
-import org.junit.Test;
-
-import java.io.File;
-import java.io.FileDescriptor;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.util.concurrent.Executor;
-
-import javax.annotation.Nullable;
-
-/**
- * White box interaction / unit testing of the {@link RulesManagerService}.
- */
-public class RulesManagerServiceTest {
-
-    private static final int CURRENT_FORMAT_MAJOR_VERSION =
-            TzDataSetVersion.currentFormatMajorVersion();
-    private static final int CURRENT_FORMAT_MINOR_VERSION =
-            TzDataSetVersion.currentFormatMinorVersion();
-
-    private RulesManagerService mRulesManagerService;
-
-    private FakeExecutor mFakeExecutor;
-    private PermissionHelper mMockPermissionHelper;
-    private RulesManagerIntentHelper mMockIntentHelper;
-    private PackageTracker mMockPackageTracker;
-    private TimeZoneDistroInstaller mMockTimeZoneDistroInstaller;
-
-    @Before
-    public void setUp() {
-        mFakeExecutor = new FakeExecutor();
-
-        mMockPackageTracker = mock(PackageTracker.class);
-        mMockPermissionHelper = mock(PermissionHelper.class);
-        mMockIntentHelper = mock(RulesManagerIntentHelper.class);
-        mMockTimeZoneDistroInstaller = mock(TimeZoneDistroInstaller.class);
-
-        mRulesManagerService = new RulesManagerService(
-                mMockPermissionHelper,
-                mFakeExecutor,
-                mMockIntentHelper,
-                mMockPackageTracker,
-                mMockTimeZoneDistroInstaller);
-    }
-
-    @Test(expected = SecurityException.class)
-    public void getRulesState_noCallerPermission() throws Exception {
-        configureCallerDoesNotHaveQueryPermission();
-        mRulesManagerService.getRulesState();
-    }
-
-    @Test(expected = SecurityException.class)
-    public void requestInstall_noCallerPermission() throws Exception {
-        configureCallerDoesNotHaveUpdatePermission();
-        mRulesManagerService.requestInstall(null, null, null);
-    }
-
-    @Test(expected = SecurityException.class)
-    public void requestUninstall_noCallerPermission() throws Exception {
-        configureCallerDoesNotHaveUpdatePermission();
-        mRulesManagerService.requestUninstall(null, null);
-    }
-
-    @Test(expected = SecurityException.class)
-    public void requestNothing_noCallerPermission() throws Exception {
-        configureCallerDoesNotHaveUpdatePermission();
-        mRulesManagerService.requestNothing(null, true);
-    }
-
-    @Test
-    public void getRulesState_baseVersionError() throws Exception {
-        configureDeviceCannotReadBaseVersion();
-
-        assertNull(mRulesManagerService.getRulesState());
-    }
-
-    @Test
-    public void getRulesState_stagedInstall() throws Exception {
-        configureCallerHasPermission();
-
-        configureDeviceBaseVersion("2016a");
-
-        DistroVersion stagedDistroVersion = new DistroVersion(
-                CURRENT_FORMAT_MAJOR_VERSION,
-                CURRENT_FORMAT_MINOR_VERSION - 1,
-                "2016c",
-                3 /* revision */);
-        configureStagedInstall(stagedDistroVersion);
-
-        DistroVersion installedDistroVersion = new DistroVersion(
-                CURRENT_FORMAT_MAJOR_VERSION,
-                CURRENT_FORMAT_MINOR_VERSION - 1,
-                "2016b",
-                4);
-        configureInstalledDistroVersion(installedDistroVersion);
-
-        DistroRulesVersion stagedDistroRulesVersion = new DistroRulesVersion(
-                stagedDistroVersion.rulesVersion, stagedDistroVersion.revision);
-        DistroRulesVersion installedDistroRulesVersion = new DistroRulesVersion(
-                installedDistroVersion.rulesVersion, installedDistroVersion.revision);
-        RulesState expectedRuleState = new RulesState(
-                "2016a", RulesManagerService.DISTRO_FORMAT_VERSION_SUPPORTED,
-                false /* operationInProgress */,
-                RulesState.STAGED_OPERATION_INSTALL, stagedDistroRulesVersion,
-                RulesState.DISTRO_STATUS_INSTALLED, installedDistroRulesVersion);
-        assertEquals(expectedRuleState, mRulesManagerService.getRulesState());
-    }
-
-    @Test
-    public void getRulesState_nothingStaged() throws Exception {
-        configureCallerHasPermission();
-
-        configureDeviceBaseVersion("2016a");
-
-        configureNoStagedOperation();
-
-        DistroVersion installedDistroVersion = new DistroVersion(
-                CURRENT_FORMAT_MAJOR_VERSION,
-                CURRENT_FORMAT_MINOR_VERSION - 1,
-                "2016b",
-                4);
-        configureInstalledDistroVersion(installedDistroVersion);
-
-        DistroRulesVersion installedDistroRulesVersion = new DistroRulesVersion(
-                installedDistroVersion.rulesVersion, installedDistroVersion.revision);
-        RulesState expectedRuleState = new RulesState(
-                "2016a", RulesManagerService.DISTRO_FORMAT_VERSION_SUPPORTED,
-                false /* operationInProgress */,
-                RulesState.STAGED_OPERATION_NONE, null /* stagedDistroRulesVersion */,
-                RulesState.DISTRO_STATUS_INSTALLED, installedDistroRulesVersion);
-        assertEquals(expectedRuleState, mRulesManagerService.getRulesState());
-    }
-
-    @Test
-    public void getRulesState_uninstallStaged() throws Exception {
-        configureCallerHasPermission();
-
-        configureDeviceBaseVersion("2016a");
-
-        configureStagedUninstall();
-
-        DistroVersion installedDistroVersion = new DistroVersion(
-                CURRENT_FORMAT_MAJOR_VERSION,
-                CURRENT_FORMAT_MINOR_VERSION - 1,
-                "2016b",
-                4);
-        configureInstalledDistroVersion(installedDistroVersion);
-
-        DistroRulesVersion installedDistroRulesVersion = new DistroRulesVersion(
-                installedDistroVersion.rulesVersion, installedDistroVersion.revision);
-        RulesState expectedRuleState = new RulesState(
-                "2016a", RulesManagerService.DISTRO_FORMAT_VERSION_SUPPORTED,
-                false /* operationInProgress */,
-                RulesState.STAGED_OPERATION_UNINSTALL, null /* stagedDistroRulesVersion */,
-                RulesState.DISTRO_STATUS_INSTALLED, installedDistroRulesVersion);
-        assertEquals(expectedRuleState, mRulesManagerService.getRulesState());
-    }
-
-    @Test
-    public void getRulesState_installedRulesError() throws Exception {
-        configureCallerHasPermission();
-
-        String baseRulesVersion = "2016a";
-        configureDeviceBaseVersion(baseRulesVersion);
-
-        configureStagedUninstall();
-        configureDeviceCannotReadInstalledDistroVersion();
-
-        RulesState expectedRuleState = new RulesState(
-                "2016a", RulesManagerService.DISTRO_FORMAT_VERSION_SUPPORTED,
-                false /* operationInProgress */,
-                RulesState.STAGED_OPERATION_UNINSTALL, null /* stagedDistroRulesVersion */,
-                RulesState.DISTRO_STATUS_UNKNOWN, null /* installedDistroRulesVersion */);
-        assertEquals(expectedRuleState, mRulesManagerService.getRulesState());
-    }
-
-    @Test
-    public void getRulesState_stagedRulesError() throws Exception {
-        configureCallerHasPermission();
-
-        String baseRulesVersion = "2016a";
-        configureDeviceBaseVersion(baseRulesVersion);
-
-        configureDeviceCannotReadStagedDistroOperation();
-
-        DistroVersion installedDistroVersion = new DistroVersion(
-                CURRENT_FORMAT_MAJOR_VERSION,
-                CURRENT_FORMAT_MINOR_VERSION - 1,
-                "2016b",
-                4);
-        configureInstalledDistroVersion(installedDistroVersion);
-
-        DistroRulesVersion installedDistroRulesVersion = new DistroRulesVersion(
-                installedDistroVersion.rulesVersion, installedDistroVersion.revision);
-        RulesState expectedRuleState = new RulesState(
-                "2016a", RulesManagerService.DISTRO_FORMAT_VERSION_SUPPORTED,
-                false /* operationInProgress */,
-                RulesState.STAGED_OPERATION_UNKNOWN, null /* stagedDistroRulesVersion */,
-                RulesState.DISTRO_STATUS_INSTALLED, installedDistroRulesVersion);
-        assertEquals(expectedRuleState, mRulesManagerService.getRulesState());
-    }
-
-    @Test
-    public void getRulesState_noInstalledRules() throws Exception {
-        configureCallerHasPermission();
-
-        String baseRulesVersion = "2016a";
-        configureDeviceBaseVersion(baseRulesVersion);
-        configureNoStagedOperation();
-        configureInstalledDistroVersion(null);
-
-        RulesState expectedRuleState = new RulesState(
-                baseRulesVersion, RulesManagerService.DISTRO_FORMAT_VERSION_SUPPORTED,
-                false /* operationInProgress */,
-                RulesState.STAGED_OPERATION_NONE, null /* stagedDistroRulesVersion */,
-                RulesState.DISTRO_STATUS_NONE, null /* installedDistroRulesVersion */);
-        assertEquals(expectedRuleState, mRulesManagerService.getRulesState());
-    }
-
-    @Test
-    public void getRulesState_operationInProgress() throws Exception {
-        configureCallerHasPermission();
-
-        String baseRulesVersion = "2016a";
-        String installedRulesVersion = "2016b";
-        int revision = 3;
-
-        configureDeviceBaseVersion(baseRulesVersion);
-
-        DistroVersion installedDistroVersion = new DistroVersion(
-                CURRENT_FORMAT_MAJOR_VERSION,
-                CURRENT_FORMAT_MINOR_VERSION - 1,
-                installedRulesVersion,
-                revision);
-        configureInstalledDistroVersion(installedDistroVersion);
-
-        ParcelFileDescriptor parcelFileDescriptor =
-                createParcelFileDescriptor(createArbitraryBytes(1000));
-
-        // Start an async operation so there is one in progress. The mFakeExecutor won't actually
-        // execute it.
-        byte[] tokenBytes = createArbitraryTokenBytes();
-        ICallback callback = new StubbedCallback();
-
-        mRulesManagerService.requestInstall(parcelFileDescriptor, tokenBytes, callback);
-
-        // Request the rules state while the async operation is "happening".
-        RulesState actualRulesState = mRulesManagerService.getRulesState();
-        DistroRulesVersion expectedInstalledDistroRulesVersion =
-                new DistroRulesVersion(installedRulesVersion, revision);
-        RulesState expectedRuleState = new RulesState(
-                baseRulesVersion, RulesManagerService.DISTRO_FORMAT_VERSION_SUPPORTED,
-                true /* operationInProgress */,
-                RulesState.STAGED_OPERATION_UNKNOWN, null /* stagedDistroRulesVersion */,
-                RulesState.DISTRO_STATUS_INSTALLED, expectedInstalledDistroRulesVersion);
-        assertEquals(expectedRuleState, actualRulesState);
-    }
-
-    @Test
-    public void requestInstall_operationInProgress() throws Exception {
-        configureCallerHasPermission();
-
-        ParcelFileDescriptor parcelFileDescriptor1 =
-                createParcelFileDescriptor(createArbitraryBytes(1000));
-
-        byte[] tokenBytes = createArbitraryTokenBytes();
-        ICallback callback = new StubbedCallback();
-
-        // First request should succeed.
-        assertEquals(RulesManager.SUCCESS,
-                mRulesManagerService.requestInstall(parcelFileDescriptor1, tokenBytes, callback));
-
-        // Something async should be enqueued. Clear it but do not execute it so we can detect the
-        // second request does nothing.
-        mFakeExecutor.getAndResetLastCommand();
-
-        // Second request should fail.
-        ParcelFileDescriptor parcelFileDescriptor2 =
-                createParcelFileDescriptor(createArbitraryBytes(1000));
-        assertEquals(RulesManager.ERROR_OPERATION_IN_PROGRESS,
-                mRulesManagerService.requestInstall(parcelFileDescriptor2, tokenBytes, callback));
-
-        assertClosed(parcelFileDescriptor2);
-
-        // Assert nothing async was enqueued.
-        mFakeExecutor.assertNothingQueued();
-        verifyNoInstallerCallsMade();
-        verifyNoPackageTrackerCallsMade();
-        verifyNoIntentsSent();
-    }
-
-    @Test
-    public void requestInstall_badToken() throws Exception {
-        configureCallerHasPermission();
-
-        ParcelFileDescriptor parcelFileDescriptor =
-                createParcelFileDescriptor(createArbitraryBytes(1000));
-
-        byte[] badTokenBytes = new byte[2];
-        ICallback callback = new StubbedCallback();
-
-        try {
-            mRulesManagerService.requestInstall(parcelFileDescriptor, badTokenBytes, callback);
-            fail();
-        } catch (IllegalArgumentException expected) {
-        }
-
-        assertClosed(parcelFileDescriptor);
-
-        // Assert nothing async was enqueued.
-        mFakeExecutor.assertNothingQueued();
-        verifyNoInstallerCallsMade();
-        verifyNoPackageTrackerCallsMade();
-        verifyNoIntentsSent();
-    }
-
-    @Test
-    public void requestInstall_nullParcelFileDescriptor() throws Exception {
-        configureCallerHasPermission();
-
-        ParcelFileDescriptor parcelFileDescriptor = null;
-        byte[] tokenBytes = createArbitraryTokenBytes();
-        ICallback callback = new StubbedCallback();
-
-        try {
-            mRulesManagerService.requestInstall(parcelFileDescriptor, tokenBytes, callback);
-            fail();
-        } catch (NullPointerException expected) {}
-
-        // Assert nothing async was enqueued.
-        mFakeExecutor.assertNothingQueued();
-        verifyNoInstallerCallsMade();
-        verifyNoPackageTrackerCallsMade();
-        verifyNoIntentsSent();
-    }
-
-    @Test
-    public void requestInstall_nullCallback() throws Exception {
-        configureCallerHasPermission();
-
-        ParcelFileDescriptor parcelFileDescriptor =
-                createParcelFileDescriptor(createArbitraryBytes(1000));
-        byte[] tokenBytes = createArbitraryTokenBytes();
-        ICallback callback = null;
-
-        try {
-            mRulesManagerService.requestInstall(parcelFileDescriptor, tokenBytes, callback);
-            fail();
-        } catch (NullPointerException expected) {}
-
-        assertClosed(parcelFileDescriptor);
-
-        // Assert nothing async was enqueued.
-        mFakeExecutor.assertNothingQueued();
-        verifyNoInstallerCallsMade();
-        verifyNoPackageTrackerCallsMade();
-        verifyNoIntentsSent();
-    }
-
-    @Test
-    public void requestInstall_asyncSuccess() throws Exception {
-        configureCallerHasPermission();
-
-        ParcelFileDescriptor parcelFileDescriptor =
-                createParcelFileDescriptor(createArbitraryBytes(1000));
-
-        CheckToken token = createArbitraryToken();
-        byte[] tokenBytes = token.toByteArray();
-
-        TestCallback callback = new TestCallback();
-
-        // Request the install.
-        assertEquals(RulesManager.SUCCESS,
-                mRulesManagerService.requestInstall(parcelFileDescriptor, tokenBytes, callback));
-
-        // Assert nothing has happened yet.
-        callback.assertNoResultReceived();
-        verifyNoInstallerCallsMade();
-        verifyNoPackageTrackerCallsMade();
-        verifyNoIntentsSent();
-
-        // Set up the installer.
-        configureStageInstallExpectation(TimeZoneDistroInstaller.INSTALL_SUCCESS);
-
-        // Simulate the async execution.
-        mFakeExecutor.simulateAsyncExecutionOfLastCommand();
-
-        assertClosed(parcelFileDescriptor);
-
-        // Verify the expected calls were made to other components.
-        verifyStageInstallCalled();
-        verifyPackageTrackerCalled(token, true /* success */);
-        verifyStagedOperationIntentSent();
-
-        // Check the callback was called.
-        callback.assertResultReceived(Callback.SUCCESS);
-    }
-
-    @Test
-    public void requestInstall_nullTokenBytes() throws Exception {
-        configureCallerHasPermission();
-
-        ParcelFileDescriptor parcelFileDescriptor =
-                createParcelFileDescriptor(createArbitraryBytes(1000));
-
-        TestCallback callback = new TestCallback();
-
-        // Request the install.
-        assertEquals(RulesManager.SUCCESS,
-                mRulesManagerService.requestInstall(
-                        parcelFileDescriptor, null /* tokenBytes */, callback));
-
-        // Assert nothing has happened yet.
-        verifyNoInstallerCallsMade();
-        callback.assertNoResultReceived();
-        verifyNoIntentsSent();
-
-        // Set up the installer.
-        configureStageInstallExpectation(TimeZoneDistroInstaller.INSTALL_SUCCESS);
-
-        // Simulate the async execution.
-        mFakeExecutor.simulateAsyncExecutionOfLastCommand();
-
-        assertClosed(parcelFileDescriptor);
-
-        // Verify the expected calls were made to other components.
-        verifyStageInstallCalled();
-        verifyPackageTrackerCalled(null /* expectedToken */, true /* success */);
-        verifyStagedOperationIntentSent();
-
-        // Check the callback was received.
-        callback.assertResultReceived(Callback.SUCCESS);
-    }
-
-    @Test
-    public void requestInstall_asyncInstallFail() throws Exception {
-        configureCallerHasPermission();
-
-        ParcelFileDescriptor parcelFileDescriptor =
-                createParcelFileDescriptor(createArbitraryBytes(1000));
-
-        CheckToken token = createArbitraryToken();
-        byte[] tokenBytes = token.toByteArray();
-
-        TestCallback callback = new TestCallback();
-
-        // Request the install.
-        assertEquals(RulesManager.SUCCESS,
-                mRulesManagerService.requestInstall(parcelFileDescriptor, tokenBytes, callback));
-
-        // Assert nothing has happened yet.
-        verifyNoInstallerCallsMade();
-        callback.assertNoResultReceived();
-        verifyNoIntentsSent();
-
-        // Set up the installer.
-        configureStageInstallExpectation(TimeZoneDistroInstaller.INSTALL_FAIL_VALIDATION_ERROR);
-
-        // Simulate the async execution.
-        mFakeExecutor.simulateAsyncExecutionOfLastCommand();
-
-        assertClosed(parcelFileDescriptor);
-
-        // Verify the expected calls were made to other components.
-        verifyStageInstallCalled();
-
-        // Validation failure is treated like a successful check: repeating it won't improve things.
-        boolean expectedSuccess = true;
-        verifyPackageTrackerCalled(token, expectedSuccess);
-
-        // Nothing should be staged, so no intents sent.
-        verifyNoIntentsSent();
-
-        // Check the callback was received.
-        callback.assertResultReceived(Callback.ERROR_INSTALL_VALIDATION_ERROR);
-    }
-
-    @Test
-    public void requestUninstall_operationInProgress() throws Exception {
-        configureCallerHasPermission();
-
-        byte[] tokenBytes = createArbitraryTokenBytes();
-        ICallback callback = new StubbedCallback();
-
-        // First request should succeed.
-        assertEquals(RulesManager.SUCCESS,
-                mRulesManagerService.requestUninstall(tokenBytes, callback));
-
-        // Something async should be enqueued. Clear it but do not execute it so we can detect the
-        // second request does nothing.
-        mFakeExecutor.getAndResetLastCommand();
-
-        // Second request should fail.
-        assertEquals(RulesManager.ERROR_OPERATION_IN_PROGRESS,
-                mRulesManagerService.requestUninstall(tokenBytes, callback));
-
-        // Assert nothing async was enqueued.
-        mFakeExecutor.assertNothingQueued();
-        verifyNoInstallerCallsMade();
-        verifyNoPackageTrackerCallsMade();
-        verifyNoIntentsSent();
-    }
-
-    @Test
-    public void requestUninstall_badToken() throws Exception {
-        configureCallerHasPermission();
-
-        byte[] badTokenBytes = new byte[2];
-        ICallback callback = new StubbedCallback();
-
-        try {
-            mRulesManagerService.requestUninstall(badTokenBytes, callback);
-            fail();
-        } catch (IllegalArgumentException expected) {
-        }
-
-        // Assert nothing async was enqueued.
-        mFakeExecutor.assertNothingQueued();
-        verifyNoInstallerCallsMade();
-        verifyNoPackageTrackerCallsMade();
-        verifyNoIntentsSent();
-    }
-
-    @Test
-    public void requestUninstall_nullCallback() throws Exception {
-        configureCallerHasPermission();
-
-        byte[] tokenBytes = createArbitraryTokenBytes();
-        ICallback callback = null;
-
-        try {
-            mRulesManagerService.requestUninstall(tokenBytes, callback);
-            fail();
-        } catch (NullPointerException expected) {}
-
-        // Assert nothing async was enqueued.
-        mFakeExecutor.assertNothingQueued();
-        verifyNoInstallerCallsMade();
-        verifyNoPackageTrackerCallsMade();
-        verifyNoIntentsSent();
-    }
-
-    @Test
-    public void requestUninstall_asyncSuccess() throws Exception {
-        configureCallerHasPermission();
-
-        CheckToken token = createArbitraryToken();
-        byte[] tokenBytes = token.toByteArray();
-
-        TestCallback callback = new TestCallback();
-
-        // Request the uninstall.
-        assertEquals(RulesManager.SUCCESS,
-                mRulesManagerService.requestUninstall(tokenBytes, callback));
-
-        // Assert nothing has happened yet.
-        callback.assertNoResultReceived();
-        verifyNoInstallerCallsMade();
-        verifyNoPackageTrackerCallsMade();
-        verifyNoIntentsSent();
-
-        // Set up the installer.
-        configureStageUninstallExpectation(TimeZoneDistroInstaller.UNINSTALL_SUCCESS);
-
-        // Simulate the async execution.
-        mFakeExecutor.simulateAsyncExecutionOfLastCommand();
-
-        // Verify the expected calls were made to other components.
-        verifyStageUninstallCalled();
-        verifyPackageTrackerCalled(token, true /* success */);
-        verifyStagedOperationIntentSent();
-
-        // Check the callback was called.
-        callback.assertResultReceived(Callback.SUCCESS);
-    }
-
-    @Test
-    public void requestUninstall_asyncNothingInstalled() throws Exception {
-        configureCallerHasPermission();
-
-        CheckToken token = createArbitraryToken();
-        byte[] tokenBytes = token.toByteArray();
-
-        TestCallback callback = new TestCallback();
-
-        // Request the uninstall.
-        assertEquals(RulesManager.SUCCESS,
-                mRulesManagerService.requestUninstall(tokenBytes, callback));
-
-        // Assert nothing has happened yet.
-        callback.assertNoResultReceived();
-        verifyNoInstallerCallsMade();
-        verifyNoPackageTrackerCallsMade();
-        verifyNoIntentsSent();
-
-        // Set up the installer.
-        configureStageUninstallExpectation(TimeZoneDistroInstaller.UNINSTALL_NOTHING_INSTALLED);
-
-        // Simulate the async execution.
-        mFakeExecutor.simulateAsyncExecutionOfLastCommand();
-
-        // Verify the expected calls were made to other components.
-        verifyStageUninstallCalled();
-        verifyPackageTrackerCalled(token, true /* success */);
-        verifyUnstagedOperationIntentSent();
-
-        // Check the callback was called.
-        callback.assertResultReceived(Callback.SUCCESS);
-    }
-
-    @Test
-    public void requestUninstall_nullTokenBytes() throws Exception {
-        configureCallerHasPermission();
-
-        TestCallback callback = new TestCallback();
-
-        // Request the uninstall.
-        assertEquals(RulesManager.SUCCESS,
-                mRulesManagerService.requestUninstall(null /* tokenBytes */, callback));
-
-        // Assert nothing has happened yet.
-        verifyNoInstallerCallsMade();
-        callback.assertNoResultReceived();
-        verifyNoIntentsSent();
-
-        // Set up the installer.
-        configureStageUninstallExpectation(TimeZoneDistroInstaller.UNINSTALL_SUCCESS);
-
-        // Simulate the async execution.
-        mFakeExecutor.simulateAsyncExecutionOfLastCommand();
-
-        // Verify the expected calls were made to other components.
-        verifyStageUninstallCalled();
-        verifyPackageTrackerCalled(null /* expectedToken */, true /* success */);
-        verifyStagedOperationIntentSent();
-
-        // Check the callback was received.
-        callback.assertResultReceived(Callback.SUCCESS);
-    }
-
-    @Test
-    public void requestUninstall_asyncUninstallFail() throws Exception {
-        configureCallerHasPermission();
-
-        CheckToken token = createArbitraryToken();
-        byte[] tokenBytes = token.toByteArray();
-
-        TestCallback callback = new TestCallback();
-
-        // Request the uninstall.
-        assertEquals(RulesManager.SUCCESS,
-                mRulesManagerService.requestUninstall(tokenBytes, callback));
-
-        // Assert nothing has happened yet.
-        verifyNoInstallerCallsMade();
-        callback.assertNoResultReceived();
-        verifyNoIntentsSent();
-
-        // Set up the installer.
-        configureStageUninstallExpectation(TimeZoneDistroInstaller.UNINSTALL_FAIL);
-
-        // Simulate the async execution.
-        mFakeExecutor.simulateAsyncExecutionOfLastCommand();
-
-        // Verify the expected calls were made to other components.
-        verifyStageUninstallCalled();
-        verifyPackageTrackerCalled(token, false /* success */);
-        verifyNoIntentsSent();
-
-        // Check the callback was received.
-        callback.assertResultReceived(Callback.ERROR_UNKNOWN_FAILURE);
-    }
-
-    @Test
-    public void requestNothing_operationInProgressOk() throws Exception {
-        configureCallerHasPermission();
-
-        // Set up a parallel operation.
-        assertEquals(RulesManager.SUCCESS,
-                mRulesManagerService.requestUninstall(null, new StubbedCallback()));
-        // Something async should be enqueued. Clear it but do not execute it to simulate it still
-        // being in progress.
-        mFakeExecutor.getAndResetLastCommand();
-
-        CheckToken token = createArbitraryToken();
-        byte[] tokenBytes = token.toByteArray();
-
-        // Make the call.
-        mRulesManagerService.requestNothing(tokenBytes, true /* success */);
-
-        // Assert nothing async was enqueued.
-        mFakeExecutor.assertNothingQueued();
-
-        // Verify the expected calls were made to other components.
-        verifyPackageTrackerCalled(token, true /* success */);
-        verifyNoInstallerCallsMade();
-        verifyNoIntentsSent();
-    }
-
-    @Test
-    public void requestNothing_badToken() throws Exception {
-        configureCallerHasPermission();
-
-        byte[] badTokenBytes = new byte[2];
-
-        try {
-            mRulesManagerService.requestNothing(badTokenBytes, true /* success */);
-            fail();
-        } catch (IllegalArgumentException expected) {
-        }
-
-        // Assert nothing async was enqueued.
-        mFakeExecutor.assertNothingQueued();
-
-        // Assert no other calls were made.
-        verifyNoInstallerCallsMade();
-        verifyNoPackageTrackerCallsMade();
-        verifyNoIntentsSent();
-    }
-
-    @Test
-    public void requestNothing() throws Exception {
-        configureCallerHasPermission();
-
-        CheckToken token = createArbitraryToken();
-        byte[] tokenBytes = token.toByteArray();
-
-        // Make the call.
-        mRulesManagerService.requestNothing(tokenBytes, false /* success */);
-
-        // Assert everything required was done.
-        verifyNoInstallerCallsMade();
-        verifyPackageTrackerCalled(token, false /* success */);
-        verifyNoIntentsSent();
-    }
-
-    @Test
-    public void requestNothing_nullTokenBytes() throws Exception {
-        configureCallerHasPermission();
-
-        // Make the call.
-        mRulesManagerService.requestNothing(null /* tokenBytes */, true /* success */);
-
-        // Assert everything required was done.
-        verifyNoInstallerCallsMade();
-        verifyPackageTrackerCalled(null /* token */, true /* success */);
-        verifyNoIntentsSent();
-    }
-
-    @Test
-    public void dump_noPermission() throws Exception {
-        when(mMockPermissionHelper.checkDumpPermission(any(String.class), any(PrintWriter.class)))
-                .thenReturn(false);
-
-        doDumpCallAndCapture(mRulesManagerService, null);
-        verifyZeroInteractions(mMockPackageTracker, mMockTimeZoneDistroInstaller);
-    }
-
-    @Test
-    public void dump_emptyArgs() throws Exception {
-        doSuccessfulDumpCall(mRulesManagerService, new String[0]);
-
-        // Verify the package tracker was consulted.
-        verify(mMockPackageTracker).dump(any(PrintWriter.class));
-    }
-
-    @Test
-    public void dump_nullArgs() throws Exception {
-        doSuccessfulDumpCall(mRulesManagerService, null);
-        // Verify the package tracker was consulted.
-        verify(mMockPackageTracker).dump(any(PrintWriter.class));
-    }
-
-    @Test
-    public void dump_unknownArgs() throws Exception {
-        String dumpedTextUnknownArgs = doSuccessfulDumpCall(
-                mRulesManagerService, new String[] { "foo", "bar"});
-
-        // Verify the package tracker was consulted.
-        verify(mMockPackageTracker).dump(any(PrintWriter.class));
-
-        String dumpedTextZeroArgs = doSuccessfulDumpCall(mRulesManagerService, null);
-        assertEquals(dumpedTextZeroArgs, dumpedTextUnknownArgs);
-    }
-
-    @Test
-    public void dump_formatState() throws Exception {
-        // Just expect these to not throw exceptions, not return nothing, and not interact with the
-        // package tracker.
-        doSuccessfulDumpCall(mRulesManagerService, dumpFormatArgs("p"));
-        doSuccessfulDumpCall(mRulesManagerService, dumpFormatArgs("s"));
-        doSuccessfulDumpCall(mRulesManagerService, dumpFormatArgs("c"));
-        doSuccessfulDumpCall(mRulesManagerService, dumpFormatArgs("i"));
-        doSuccessfulDumpCall(mRulesManagerService, dumpFormatArgs("o"));
-        doSuccessfulDumpCall(mRulesManagerService, dumpFormatArgs("t"));
-        doSuccessfulDumpCall(mRulesManagerService, dumpFormatArgs("a"));
-        doSuccessfulDumpCall(mRulesManagerService, dumpFormatArgs("z" /* Unknown */));
-        doSuccessfulDumpCall(mRulesManagerService, dumpFormatArgs("piscotz"));
-
-        verifyZeroInteractions(mMockPackageTracker);
-    }
-
-    private static String[] dumpFormatArgs(String argsString) {
-        return new String[] { "-format_state", argsString};
-    }
-
-    private String doSuccessfulDumpCall(RulesManagerService rulesManagerService, String[] args)
-            throws Exception {
-        when(mMockPermissionHelper.checkDumpPermission(any(String.class), any(PrintWriter.class)))
-                .thenReturn(true);
-
-        // Set up the mocks to return (arbitrary) information about the current device state.
-        TzDataSetVersion baseVersion = new TzDataSetVersion(
-                CURRENT_FORMAT_MAJOR_VERSION, CURRENT_FORMAT_MINOR_VERSION, "2017a",
-                1 /* revision */);
-        when(mMockTimeZoneDistroInstaller.readBaseVersion()).thenReturn(baseVersion);
-        DistroVersion installedDistroVersion = new DistroVersion(
-                CURRENT_FORMAT_MAJOR_VERSION, CURRENT_FORMAT_MINOR_VERSION, "2017b",
-                4 /* revision */);
-        when(mMockTimeZoneDistroInstaller.getInstalledDistroVersion())
-                .thenReturn(installedDistroVersion);
-        DistroVersion stagedDistroVersion = new DistroVersion(
-                CURRENT_FORMAT_MAJOR_VERSION, CURRENT_FORMAT_MINOR_VERSION, "2017c",
-                7 /* revision */);
-        when(mMockTimeZoneDistroInstaller.getStagedDistroOperation()).thenReturn(
-                StagedDistroOperation.install(stagedDistroVersion));
-
-        // Do the dump call.
-        String dumpedOutput = doDumpCallAndCapture(rulesManagerService, args);
-
-        assertFalse(dumpedOutput.isEmpty());
-
-        return dumpedOutput;
-    }
-
-    private static String doDumpCallAndCapture(
-            RulesManagerService rulesManagerService, String[] args) throws IOException {
-        File file = File.createTempFile("dump", null);
-        try {
-            try (FileOutputStream fos = new FileOutputStream(file)) {
-                FileDescriptor fd = fos.getFD();
-                rulesManagerService.dump(fd, args);
-            }
-            return IoUtils.readFileAsString(file.getAbsolutePath());
-        } finally {
-            file.delete();
-        }
-    }
-
-    private void verifyNoPackageTrackerCallsMade() {
-        verifyNoMoreInteractions(mMockPackageTracker);
-        reset(mMockPackageTracker);
-    }
-
-    private void verifyPackageTrackerCalled(
-            CheckToken expectedCheckToken, boolean expectedSuccess) {
-        verify(mMockPackageTracker).recordCheckResult(expectedCheckToken, expectedSuccess);
-        reset(mMockPackageTracker);
-    }
-
-    private void verifyNoIntentsSent() {
-        verifyNoMoreInteractions(mMockIntentHelper);
-        reset(mMockIntentHelper);
-    }
-
-    private void verifyStagedOperationIntentSent() {
-        verify(mMockIntentHelper).sendTimeZoneOperationStaged();
-        reset(mMockIntentHelper);
-    }
-
-    private void verifyUnstagedOperationIntentSent() {
-        verify(mMockIntentHelper).sendTimeZoneOperationUnstaged();
-        reset(mMockIntentHelper);
-    }
-
-    private void configureCallerHasPermission() throws Exception {
-        doNothing()
-                .when(mMockPermissionHelper)
-                .enforceCallerHasPermission(REQUIRED_UPDATER_PERMISSION);
-    }
-
-    private void configureCallerDoesNotHaveUpdatePermission() {
-        doThrow(new SecurityException("Simulated permission failure"))
-                .when(mMockPermissionHelper)
-                .enforceCallerHasPermission(REQUIRED_UPDATER_PERMISSION);
-    }
-
-    private void configureCallerDoesNotHaveQueryPermission() {
-        doThrow(new SecurityException("Simulated permission failure"))
-                .when(mMockPermissionHelper)
-                .enforceCallerHasPermission(REQUIRED_QUERY_PERMISSION);
-    }
-
-    private void configureStageInstallExpectation(int resultCode)
-            throws Exception {
-        when(mMockTimeZoneDistroInstaller.stageInstallWithErrorCode(any(TimeZoneDistro.class)))
-                .thenReturn(resultCode);
-    }
-
-    private void configureStageUninstallExpectation(int resultCode) throws Exception {
-        doReturn(resultCode).when(mMockTimeZoneDistroInstaller).stageUninstall();
-    }
-
-    private void verifyStageInstallCalled() throws Exception {
-        verify(mMockTimeZoneDistroInstaller).stageInstallWithErrorCode(any(TimeZoneDistro.class));
-        verifyNoMoreInteractions(mMockTimeZoneDistroInstaller);
-        reset(mMockTimeZoneDistroInstaller);
-    }
-
-    private void verifyStageUninstallCalled() throws Exception {
-        verify(mMockTimeZoneDistroInstaller).stageUninstall();
-        verifyNoMoreInteractions(mMockTimeZoneDistroInstaller);
-        reset(mMockTimeZoneDistroInstaller);
-    }
-
-    private void verifyNoInstallerCallsMade() {
-        verifyNoMoreInteractions(mMockTimeZoneDistroInstaller);
-        reset(mMockTimeZoneDistroInstaller);
-    }
-
-    private static byte[] createArbitraryBytes(int length) {
-        byte[] bytes = new byte[length];
-        for (int i = 0; i < length; i++) {
-            bytes[i] = (byte) i;
-        }
-        return bytes;
-    }
-
-    private byte[] createArbitraryTokenBytes() {
-        return createArbitraryToken().toByteArray();
-    }
-
-    private CheckToken createArbitraryToken() {
-        return new CheckToken(1, new PackageVersions(1, 1));
-    }
-
-    private void configureDeviceBaseVersion(String baseRulesVersion) throws Exception {
-        TzDataSetVersion tzDataSetVersion = new TzDataSetVersion(
-                CURRENT_FORMAT_MAJOR_VERSION, CURRENT_FORMAT_MINOR_VERSION, baseRulesVersion,
-                1 /* revision */);
-        when(mMockTimeZoneDistroInstaller.readBaseVersion()).thenReturn(tzDataSetVersion);
-    }
-
-    private void configureInstalledDistroVersion(@Nullable DistroVersion installedDistroVersion)
-            throws Exception {
-        when(mMockTimeZoneDistroInstaller.getInstalledDistroVersion())
-                .thenReturn(installedDistroVersion);
-    }
-
-    private void configureStagedInstall(DistroVersion stagedDistroVersion) throws Exception {
-        when(mMockTimeZoneDistroInstaller.getStagedDistroOperation())
-                .thenReturn(StagedDistroOperation.install(stagedDistroVersion));
-    }
-
-    private void configureStagedUninstall() throws Exception {
-        when(mMockTimeZoneDistroInstaller.getStagedDistroOperation())
-                .thenReturn(StagedDistroOperation.uninstall());
-    }
-
-    private void configureNoStagedOperation() throws Exception {
-        when(mMockTimeZoneDistroInstaller.getStagedDistroOperation()).thenReturn(null);
-    }
-
-    private void configureDeviceCannotReadStagedDistroOperation() throws Exception {
-        when(mMockTimeZoneDistroInstaller.getStagedDistroOperation())
-                .thenThrow(new IOException("Simulated failure"));
-    }
-
-    private void configureDeviceCannotReadBaseVersion() throws Exception {
-        when(mMockTimeZoneDistroInstaller.readBaseVersion())
-                .thenThrow(new IOException("Simulated failure"));
-    }
-
-    private void configureDeviceCannotReadInstalledDistroVersion() throws Exception {
-        when(mMockTimeZoneDistroInstaller.getInstalledDistroVersion())
-                .thenThrow(new IOException("Simulated failure"));
-    }
-
-    private static void assertClosed(ParcelFileDescriptor parcelFileDescriptor) {
-        assertFalse(parcelFileDescriptor.getFileDescriptor().valid());
-    }
-
-    private static class FakeExecutor implements Executor {
-
-        private Runnable mLastCommand;
-
-        @Override
-        public void execute(Runnable command) {
-            assertNull(mLastCommand);
-            assertNotNull(command);
-            mLastCommand = command;
-        }
-
-        public Runnable getAndResetLastCommand() {
-            assertNotNull(mLastCommand);
-            Runnable toReturn = mLastCommand;
-            mLastCommand = null;
-            return toReturn;
-        }
-
-        public void simulateAsyncExecutionOfLastCommand() {
-            Runnable toRun = getAndResetLastCommand();
-            toRun.run();
-        }
-
-        public void assertNothingQueued() {
-            assertNull(mLastCommand);
-        }
-    }
-
-    private static class TestCallback extends ICallback.Stub {
-
-        private boolean mOnFinishedCalled;
-        private int mLastError;
-
-        @Override
-        public void onFinished(int error) {
-            assertFalse(mOnFinishedCalled);
-            mOnFinishedCalled = true;
-            mLastError = error;
-        }
-
-        public void assertResultReceived(int expectedResult) {
-            assertTrue(mOnFinishedCalled);
-            assertEquals(expectedResult, mLastError);
-        }
-
-        public void assertNoResultReceived() {
-            assertFalse(mOnFinishedCalled);
-        }
-    }
-
-    private static class StubbedCallback extends ICallback.Stub {
-        @Override
-        public void onFinished(int error) {
-            fail("Unexpected call");
-        }
-    }
-
-    private static ParcelFileDescriptor createParcelFileDescriptor(byte[] bytes)
-            throws IOException {
-        File file = File.createTempFile("pfd", null);
-        try (FileOutputStream fos = new FileOutputStream(file)) {
-            fos.write(bytes);
-        }
-        ParcelFileDescriptor pfd =
-                ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY);
-        // This should now be safe to delete. The ParcelFileDescriptor has an open fd.
-        file.delete();
-        return pfd;
-    }
-}
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
index 32cee44..b770b3e 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -3065,11 +3065,11 @@
 
         // Simulate app re-start input or turning screen off/on then unlocked by un-secure
         // keyguard to back to the app, expect IME insets is not frozen
-        mDisplayContent.updateImeInputAndControlTarget(app);
-        assertFalse(app.mActivityRecord.mImeInsetsFrozenUntilStartInput);
         imeSource.setFrame(new Rect(100, 400, 500, 500));
         app.getInsetsState().addSource(imeSource);
         app.getInsetsState().setSourceVisible(ITYPE_IME, true);
+        mDisplayContent.updateImeInputAndControlTarget(app);
+        assertFalse(app.mActivityRecord.mImeInsetsFrozenUntilStartInput);
 
         // Verify when IME is visible and the app can receive the right IME insets from policy.
         makeWindowVisibleAndDrawn(app, mImeWindow);
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
index 9c0c213c..f3c1ec5 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
@@ -1075,21 +1075,6 @@
         assertEquals(dc.getImeContainer().getParentSurfaceControl(), dc.computeImeParent());
     }
 
-    @UseTestDisplay(addWindows = W_ACTIVITY)
-    @Test
-    public void testComputeImeParent_inputTargetNotUpdate() throws Exception {
-        WindowState app1 = createWindow(null, TYPE_BASE_APPLICATION, "app1");
-        WindowState app2 = createWindow(null, TYPE_BASE_APPLICATION, "app2");
-        doReturn(true).when(mDisplayContent).shouldImeAttachedToApp();
-        mDisplayContent.setImeLayeringTarget(app1);
-        mDisplayContent.setImeInputTarget(app1);
-        assertEquals(app1.mActivityRecord.getSurfaceControl(), mDisplayContent.computeImeParent());
-        mDisplayContent.setImeLayeringTarget(app2);
-        // Expect null means no change IME parent when the IME layering target not yet
-        // request IME to be the input target.
-        assertNull(mDisplayContent.computeImeParent());
-    }
-
     @Test
     public void testInputMethodInputTarget_isClearedWhenWindowStateIsRemoved() throws Exception {
         final DisplayContent dc = createNewDisplay();
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java
index 168c250..159d482 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java
@@ -196,6 +196,28 @@
     }
 
     @Test
+    public void testUsesOptionsDisplayAreaFeatureIdIfSet() {
+        final TestDisplayContent freeformDisplay = createNewDisplayContent(
+                WINDOWING_MODE_FREEFORM);
+        final TestDisplayContent fullscreenDisplay = createNewDisplayContent(
+                WINDOWING_MODE_FULLSCREEN);
+
+        mCurrent.mPreferredTaskDisplayArea = freeformDisplay.getDefaultTaskDisplayArea();
+        ActivityRecord source = createSourceActivity(freeformDisplay);
+
+        ActivityOptions options = ActivityOptions.makeBasic();
+        options.setLaunchDisplayId(fullscreenDisplay.mDisplayId);
+        options.setLaunchTaskDisplayAreaFeatureId(
+                fullscreenDisplay.getDefaultTaskDisplayArea().mFeatureId);
+
+        assertEquals(RESULT_CONTINUE,
+                new CalculateRequestBuilder().setSource(source).setOptions(options).calculate());
+
+        assertEquals(fullscreenDisplay.getDefaultTaskDisplayArea(),
+                mResult.mPreferredTaskDisplayArea);
+    }
+
+    @Test
     public void testUsesSourcesDisplayAreaIdPriorToTaskIfSet() {
         final TestDisplayContent freeformDisplay = createNewDisplayContent(
                 WINDOWING_MODE_FREEFORM);
@@ -453,7 +475,7 @@
     }
 
     @Test
-    public void testNotOverrideDisplayAreaWhenActivityOptionsHasDisplayArea() {
+    public void testNotOverrideDisplayAreaWhenActivityOptionsHasDisplayAreaToken() {
         final TaskDisplayArea secondaryDisplayArea = createTaskDisplayArea(mDefaultDisplay,
                 mWm, "SecondaryDisplayArea", FEATURE_RUNTIME_TASK_CONTAINER_FIRST);
         final Task launchRoot = createTask(secondaryDisplayArea, WINDOWING_MODE_FULLSCREEN,
@@ -475,6 +497,52 @@
     }
 
     @Test
+    public void testNotOverrideDisplayAreaWhenActivityOptionsHasDisplayAreaFeatureId() {
+        final TaskDisplayArea secondaryDisplayArea = createTaskDisplayArea(mDefaultDisplay,
+                mWm, "SecondaryDisplayArea", FEATURE_RUNTIME_TASK_CONTAINER_FIRST);
+        final Task launchRoot = createTask(secondaryDisplayArea, WINDOWING_MODE_FULLSCREEN,
+                ACTIVITY_TYPE_STANDARD);
+        launchRoot.mCreatedByOrganizer = true;
+
+        secondaryDisplayArea.setLaunchRootTask(launchRoot, new int[] { WINDOWING_MODE_FULLSCREEN },
+                new int[] { ACTIVITY_TYPE_STANDARD });
+
+        ActivityOptions options = ActivityOptions.makeBasic();
+        options.setLaunchTaskDisplayAreaFeatureId(
+                mDefaultDisplay.getDefaultTaskDisplayArea().mFeatureId);
+
+        assertEquals(RESULT_CONTINUE,
+                new CalculateRequestBuilder().setOptions(options).calculate());
+
+        assertEquals(
+                mDefaultDisplay.getDefaultTaskDisplayArea(), mResult.mPreferredTaskDisplayArea);
+    }
+
+    @Test
+    public void testUsesOptionsDisplayAreaFeatureIdDisplayIdNotSet() {
+        final TestDisplayContent secondaryDisplay = createNewDisplayContent(
+                WINDOWING_MODE_FULLSCREEN);
+        final TaskDisplayArea tdaOnSecondaryDisplay = createTaskDisplayArea(secondaryDisplay,
+                mWm, "TestTaskDisplayArea", FEATURE_RUNTIME_TASK_CONTAINER_FIRST);
+
+        final TaskDisplayArea tdaOnDefaultDisplay = createTaskDisplayArea(mDefaultDisplay,
+                mWm, "TestTaskDisplayArea", FEATURE_RUNTIME_TASK_CONTAINER_FIRST);
+
+        mCurrent.mPreferredTaskDisplayArea = tdaOnSecondaryDisplay;
+        ActivityRecord source = createSourceActivity(tdaOnSecondaryDisplay,
+                WINDOWING_MODE_FULLSCREEN);
+
+        ActivityOptions options = ActivityOptions.makeBasic();
+        options.setLaunchTaskDisplayAreaFeatureId(tdaOnSecondaryDisplay.mFeatureId);
+
+        assertEquals(RESULT_CONTINUE,
+                new CalculateRequestBuilder().setSource(source).setOptions(options).calculate());
+        // Display id wasn't specified in ActivityOptions - the activity should be placed on the
+        // default display, into the TaskDisplayArea with the same feature id.
+        assertEquals(tdaOnDefaultDisplay, mResult.mPreferredTaskDisplayArea);
+    }
+
+    @Test
     public void testRecalculateFreeformInitialBoundsWithOverrideDisplayArea() {
         final TestDisplayContent freeformDisplay = createNewDisplayContent(
                 WINDOWING_MODE_FREEFORM);
@@ -1822,6 +1890,13 @@
         return new ActivityBuilder(mAtm).setTask(rootTask).build();
     }
 
+    private ActivityRecord createSourceActivity(TaskDisplayArea taskDisplayArea,
+            int windowingMode) {
+        final Task rootTask = taskDisplayArea.createRootTask(windowingMode, ACTIVITY_TYPE_STANDARD,
+                true);
+        return new ActivityBuilder(mAtm).setTask(rootTask).build();
+    }
+
     private void addFreeformTaskTo(TestDisplayContent display, Rect bounds) {
         final Task rootTask = display.getDefaultTaskDisplayArea()
                 .createRootTask(display.getWindowingMode(), ACTIVITY_TYPE_STANDARD, true);
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 03b8188..7d50135 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
@@ -931,47 +931,6 @@
 
     @UseTestDisplay(addWindows = { W_ACTIVITY })
     @Test
-    public void testAdjustImeInsetsVisibilityWhenSwitchingApps_toAppInMultiWindowMode() {
-        final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
-        final WindowState app2 = createWindow(null, WINDOWING_MODE_MULTI_WINDOW,
-                ACTIVITY_TYPE_STANDARD, TYPE_APPLICATION, mDisplayContent, "app2");
-        final WindowState imeWindow = createWindow(null, TYPE_APPLICATION, "imeWindow");
-        spyOn(imeWindow);
-        doReturn(true).when(imeWindow).isVisible();
-        mDisplayContent.mInputMethodWindow = imeWindow;
-
-        final InsetsStateController controller = mDisplayContent.getInsetsStateController();
-        controller.getImeSourceProvider().setWindow(imeWindow, null, null);
-
-        // Simulate app2 in multi-window mode is going to background to switch to the fullscreen
-        // app which requests IME with updating all windows Insets State when IME is above app.
-        app2.mActivityRecord.mImeInsetsFrozenUntilStartInput = true;
-        mDisplayContent.setImeLayeringTarget(app);
-        mDisplayContent.setImeInputTarget(app);
-        assertTrue(mDisplayContent.shouldImeAttachedToApp());
-        controller.getImeSourceProvider().scheduleShowImePostLayout(app);
-        controller.getImeSourceProvider().getSource().setVisible(true);
-        controller.updateAboveInsetsState(imeWindow, false);
-
-        // Expect app windows behind IME can receive IME insets visible,
-        // but not for app2 in background.
-        assertTrue(app.getInsetsState().getSource(ITYPE_IME).isVisible());
-        assertFalse(app2.getInsetsState().getSource(ITYPE_IME).isVisible());
-
-        // Simulate app plays closing transition to app2.
-        // And app2 is now IME layering target but not yet to be the IME input target.
-        mDisplayContent.setImeLayeringTarget(app2);
-        app.mActivityRecord.commitVisibility(false, false);
-        assertTrue(app.mActivityRecord.mLastImeShown);
-        assertTrue(app.mActivityRecord.mImeInsetsFrozenUntilStartInput);
-
-        // Verify the IME insets is still visible on app, but not for app2 during task switching.
-        assertTrue(app.getInsetsState().getSource(ITYPE_IME).isVisible());
-        assertFalse(app2.getInsetsState().getSource(ITYPE_IME).isVisible());
-    }
-
-    @UseTestDisplay(addWindows = {W_ACTIVITY})
-    @Test
     public void testUpdateImeControlTargetWhenLeavingMultiWindow() {
         WindowState app = createWindow(null, TYPE_BASE_APPLICATION,
                 mAppWindow.mToken, "app");
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index af1d56a..610190e 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -175,7 +175,11 @@
     // Delay for debouncing USB disconnects.
     // We often get rapid connect/disconnect events when enabling USB functions,
     // which need debouncing.
-    private static final int UPDATE_DELAY = 1000;
+    private static final int DEVICE_STATE_UPDATE_DELAY_EXT = 3000;
+    private static final int DEVICE_STATE_UPDATE_DELAY = 1000;
+
+    // Delay for debouncing USB disconnects on Type-C ports in host mode
+    private static final int HOST_STATE_UPDATE_DELAY = 1000;
 
     // Timeout for entering USB request mode.
     // Request is cancelled if host does not configure device within 10 seconds.
@@ -637,7 +641,9 @@
             msg.arg1 = connected;
             msg.arg2 = configured;
             // debounce disconnects to avoid problems bringing up USB tethering
-            sendMessageDelayed(msg, (connected == 0) ? UPDATE_DELAY : 0);
+            sendMessageDelayed(msg,
+                    (connected == 0) ? (mScreenLocked ? DEVICE_STATE_UPDATE_DELAY
+                                                      : DEVICE_STATE_UPDATE_DELAY_EXT) : 0);
         }
 
         public void updateHostState(UsbPort port, UsbPortStatus status) {
@@ -652,7 +658,7 @@
             removeMessages(MSG_UPDATE_PORT_STATE);
             Message msg = obtainMessage(MSG_UPDATE_PORT_STATE, args);
             // debounce rapid transitions of connect/disconnect on type-c ports
-            sendMessageDelayed(msg, UPDATE_DELAY);
+            sendMessageDelayed(msg, HOST_STATE_UPDATE_DELAY);
         }
 
         private void setAdbEnabled(boolean enable) {
diff --git a/telephony/common/android/telephony/LocationAccessPolicy.java b/telephony/common/android/telephony/LocationAccessPolicy.java
index 85d59a2..9dfb0cc 100644
--- a/telephony/common/android/telephony/LocationAccessPolicy.java
+++ b/telephony/common/android/telephony/LocationAccessPolicy.java
@@ -361,7 +361,10 @@
         return isCurrentProfile(context, uid) || checkInteractAcrossUsersFull(context, pid, uid);
     }
 
-    private static boolean isLocationModeEnabled(@NonNull Context context, @UserIdInt int userId) {
+    /**
+     * @return Whether location is enabled for the given user.
+     */
+    public static boolean isLocationModeEnabled(@NonNull Context context, @UserIdInt int userId) {
         LocationManager locationManager = context.getSystemService(LocationManager.class);
         if (locationManager == null) {
             Log.w(TAG, "Couldn't get location manager, denying location access");
@@ -370,6 +373,14 @@
         return locationManager.isLocationEnabledForUser(UserHandle.of(userId));
     }
 
+    /**
+     * @return An array of packages that are always allowed to access location.
+     */
+    public static @NonNull String[] getLocationBypassPackages(@NonNull Context context) {
+        return context.getResources().getStringArray(
+                com.android.internal.R.array.config_serviceStateLocationAllowedPackages);
+    }
+
     private static boolean checkInteractAcrossUsersFull(
             @NonNull Context context, int pid, int uid) {
         return checkManifestPermission(context, pid, uid,
diff --git a/telephony/java/android/telephony/AccessNetworkUtils.java b/telephony/java/android/telephony/AccessNetworkUtils.java
index b5d97ab..c2a9864 100644
--- a/telephony/java/android/telephony/AccessNetworkUtils.java
+++ b/telephony/java/android/telephony/AccessNetworkUtils.java
@@ -4,8 +4,8 @@
 import static android.telephony.ServiceState.DUPLEX_MODE_TDD;
 import static android.telephony.ServiceState.DUPLEX_MODE_UNKNOWN;
 
-import android.telephony.AccessNetworkConstants.EutranBandArfcnFrequency;
 import android.telephony.AccessNetworkConstants.EutranBand;
+import android.telephony.AccessNetworkConstants.EutranBandArfcnFrequency;
 import android.telephony.AccessNetworkConstants.GeranBand;
 import android.telephony.AccessNetworkConstants.GeranBandArfcnFrequency;
 import android.telephony.AccessNetworkConstants.NgranArfcnFrequency;
@@ -13,7 +13,6 @@
 import android.telephony.AccessNetworkConstants.UtranBand;
 import android.telephony.AccessNetworkConstants.UtranBandArfcnFrequency;
 import android.telephony.ServiceState.DuplexMode;
-import android.util.Log;
 
 import java.util.Arrays;
 import java.util.HashSet;
@@ -232,6 +231,108 @@
     }
 
     /**
+     * Gets the NR Operating band for a given downlink NRARFCN.
+     *
+     * <p>See 3GPP TS 38.104 Table 5.2-1 NR operating bands in FR1 and
+     * Table 5.2-2 NR operating bands in FR2
+     *
+     * @param nrarfcn The downlink NRARFCN
+     * @return Operating band number, or {@link #INVALID_BAND} if no corresponding band exists
+     */
+    public static int getOperatingBandForNrarfcn(int nrarfcn) {
+        if (nrarfcn >= 422000 && nrarfcn <= 434000) {
+            return NgranBands.BAND_1;
+        } else if (nrarfcn >= 386000 && nrarfcn <= 398000) {
+            return NgranBands.BAND_2;
+        } else if (nrarfcn >= 361000 && nrarfcn <= 376000) {
+            return NgranBands.BAND_3;
+        } else if (nrarfcn >= 173800 && nrarfcn <= 178800) {
+            return NgranBands.BAND_5;
+        } else if (nrarfcn >= 524000 && nrarfcn <= 538000) {
+            return NgranBands.BAND_7;
+        } else if (nrarfcn >= 185000 && nrarfcn <= 192000) {
+            return NgranBands.BAND_8;
+        } else if (nrarfcn >= 145800 && nrarfcn <= 149200) {
+            return NgranBands.BAND_12;
+        } else if (nrarfcn >= 151600 && nrarfcn <= 153600) {
+            return NgranBands.BAND_14;
+        } else if (nrarfcn >= 172000 && nrarfcn <= 175000) {
+            return NgranBands.BAND_18;
+        } else if (nrarfcn >= 158200 && nrarfcn <= 164200) {
+            return NgranBands.BAND_20;
+        } else if (nrarfcn >= 386000 && nrarfcn <= 399000) {
+            return NgranBands.BAND_25;
+        } else if (nrarfcn >= 171800 && nrarfcn <= 178800) {
+            return NgranBands.BAND_26;
+        } else if (nrarfcn >= 151600 && nrarfcn <= 160600) {
+            return NgranBands.BAND_28;
+        } else if (nrarfcn >= 143400 && nrarfcn <= 145600) {
+            return NgranBands.BAND_29;
+        } else if (nrarfcn >= 470000 && nrarfcn <= 472000) {
+            return NgranBands.BAND_30;
+        } else if (nrarfcn >= 402000 && nrarfcn <= 405000) {
+            return NgranBands.BAND_34;
+        } else if (nrarfcn >= 514000 && nrarfcn <= 524000) {
+            return NgranBands.BAND_38;
+        } else if (nrarfcn >= 376000 && nrarfcn <= 384000) {
+            return NgranBands.BAND_39;
+        } else if (nrarfcn >= 460000 && nrarfcn <= 480000) {
+            return NgranBands.BAND_40;
+        } else if (nrarfcn >= 499200 && nrarfcn <= 537999) {
+            return NgranBands.BAND_41;
+        } else if (nrarfcn >= 743334 && nrarfcn <= 795000) {
+            return NgranBands.BAND_46;
+        } else if (nrarfcn >= 636667 && nrarfcn <= 646666) {
+            return NgranBands.BAND_48;
+        } else if (nrarfcn >= 286400 && nrarfcn <= 303400) {
+            return NgranBands.BAND_50;
+        } else if (nrarfcn >= 285400 && nrarfcn <= 286400) {
+            return NgranBands.BAND_51;
+        } else if (nrarfcn >= 496700 && nrarfcn <= 499000) {
+            return NgranBands.BAND_53;
+        } else if (nrarfcn >= 422000 && nrarfcn <= 440000) {
+            return NgranBands.BAND_65; // BAND_66 has the same channels
+        } else if (nrarfcn >= 399000 && nrarfcn <= 404000) {
+            return NgranBands.BAND_70;
+        } else if (nrarfcn >= 123400 && nrarfcn <= 130400) {
+            return NgranBands.BAND_71;
+        } else if (nrarfcn >= 295000 && nrarfcn <= 303600) {
+            return NgranBands.BAND_74;
+        } else if (nrarfcn >= 286400 && nrarfcn <= 303400) {
+            return NgranBands.BAND_75;
+        } else if (nrarfcn >= 285400 && nrarfcn <= 286400) {
+            return NgranBands.BAND_76;
+        } else if (nrarfcn >= 620000 && nrarfcn <= 680000) {
+            return NgranBands.BAND_77;
+        } else if (nrarfcn >= 620000 && nrarfcn <= 653333) {
+            return NgranBands.BAND_78;
+        } else if (nrarfcn >= 693334 && nrarfcn <= 733333) {
+            return NgranBands.BAND_79;
+        } else if (nrarfcn >= 499200 && nrarfcn <= 538000) {
+            return NgranBands.BAND_90;
+        } else if (nrarfcn >= 285400 && nrarfcn <= 286400) {
+            return NgranBands.BAND_91;
+        } else if (nrarfcn >= 286400 && nrarfcn <= 303400) {
+            return NgranBands.BAND_92;
+        } else if (nrarfcn >= 285400 && nrarfcn <= 286400) {
+            return NgranBands.BAND_93;
+        } else if (nrarfcn >= 286400 && nrarfcn <= 303400) {
+            return NgranBands.BAND_94;
+        } else if (nrarfcn >= 795000 && nrarfcn <= 875000) {
+            return NgranBands.BAND_96;
+        } else if (nrarfcn >= 2054166 && nrarfcn <= 2104165) {
+            return NgranBands.BAND_257;
+        } else if (nrarfcn >= 2016667 && nrarfcn <= 2070832) {
+            return NgranBands.BAND_258;
+        } else if (nrarfcn >= 2229166 && nrarfcn <= 2279165) {
+            return NgranBands.BAND_260;
+        } else if (nrarfcn >= 2070833 && nrarfcn <= 2084999) {
+            return NgranBands.BAND_261;
+        }
+        return INVALID_BAND;
+    }
+
+    /**
      * Gets the GERAN Operating band for a given ARFCN.
      *
      * <p>See 3GPP TS 45.005 clause 2 for calculation.
diff --git a/tests/RollbackTest/SampleRollbackApp/Android.bp b/tests/RollbackTest/SampleRollbackApp/Android.bp
new file mode 100644
index 0000000..a18488d
--- /dev/null
+++ b/tests/RollbackTest/SampleRollbackApp/Android.bp
@@ -0,0 +1,32 @@
+// Copyright (C) 2022 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
+android_app {
+    name: "SampleRollbackApp",
+    srcs: [
+        "src/**/*.java",
+    ],
+    resource_dirs: ["res"],
+    certificate: "platform",
+    sdk_version: "system_current",
+}
diff --git a/tests/RollbackTest/SampleRollbackApp/AndroidManifest.xml b/tests/RollbackTest/SampleRollbackApp/AndroidManifest.xml
new file mode 100644
index 0000000..5a135c9
--- /dev/null
+++ b/tests/RollbackTest/SampleRollbackApp/AndroidManifest.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2022 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="com.android.sample.rollbackapp" >
+    <uses-permission android:name="android.permission.TEST_MANAGE_ROLLBACKS" />
+    <application
+        android:label="@string/title_activity_main">
+        <activity
+            android:name="com.android.sample.rollbackapp.MainActivity"
+            android:exported="true">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+    </application>
+</manifest>
\ No newline at end of file
diff --git a/tests/RollbackTest/SampleRollbackApp/res/layout/activity_main.xml b/tests/RollbackTest/SampleRollbackApp/res/layout/activity_main.xml
new file mode 100644
index 0000000..3fb987b
--- /dev/null
+++ b/tests/RollbackTest/SampleRollbackApp/res/layout/activity_main.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2022 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+              android:orientation="vertical"
+              android:layout_width="match_parent"
+              android:layout_height="match_parent">
+
+    <Button
+        android:id="@+id/trigger_rollback_button"
+        android:layout_height="wrap_content"
+        android:layout_width="wrap_content"
+        style="?android:attr/buttonBarButtonStyle"
+        android:text="Rollback Selected" />
+
+    <ListView
+        android:id="@+id/listView"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        android:divider="?android:attr/dividerHorizontal"
+        android:dividerHeight="1dp" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/tests/RollbackTest/SampleRollbackApp/res/layout/listitem_rollbackinfo.xml b/tests/RollbackTest/SampleRollbackApp/res/layout/listitem_rollbackinfo.xml
new file mode 100644
index 0000000..f650dd5
--- /dev/null
+++ b/tests/RollbackTest/SampleRollbackApp/res/layout/listitem_rollbackinfo.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2022 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+>
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="vertical"
+        android:paddingTop="10dp"
+        android:paddingLeft="10dp"
+        android:paddingRight="10dp">
+        <TextView android:id="@+id/rollback_id"
+                  android:layout_width="match_parent"
+                  android:layout_height="wrap_content"
+                  android:textSize="20dp"/>
+        <TextView android:id="@+id/rollback_packages"
+                  android:layout_width="match_parent"
+                  android:layout_height="wrap_content"
+                  android:textSize="16dp"/>
+        <CheckBox android:id="@+id/checkbox"
+                  android:layout_width="wrap_content"
+                  android:layout_height="wrap_content"
+                  android:text="Roll Back"/>
+    </LinearLayout>
+</RelativeLayout>
\ No newline at end of file
diff --git a/tests/RollbackTest/SampleRollbackApp/res/values/strings.xml b/tests/RollbackTest/SampleRollbackApp/res/values/strings.xml
new file mode 100644
index 0000000..a85b680
--- /dev/null
+++ b/tests/RollbackTest/SampleRollbackApp/res/values/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2022 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<resources>
+    <string name="title_activity_main" description="Launcher title">Rollback Sample App</string>
+</resources>
\ No newline at end of file
diff --git a/tests/RollbackTest/SampleRollbackApp/src/com/android/sample/rollbackapp/MainActivity.java b/tests/RollbackTest/SampleRollbackApp/src/com/android/sample/rollbackapp/MainActivity.java
new file mode 100644
index 0000000..916551a
--- /dev/null
+++ b/tests/RollbackTest/SampleRollbackApp/src/com/android/sample/rollbackapp/MainActivity.java
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.sample.rollbackapp;
+
+import static android.app.PendingIntent.FLAG_MUTABLE;
+
+import android.app.Activity;
+import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.rollback.PackageRollbackInfo;
+import android.content.rollback.RollbackInfo;
+import android.content.rollback.RollbackManager;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.Button;
+import android.widget.CheckBox;
+import android.widget.ListView;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public class MainActivity extends Activity {
+
+    List<Integer> mIdsToRollback = new ArrayList<>();
+    Button mTriggerRollbackButton;
+    RollbackManager mRollbackManager;
+    static final String ROLLBACK_ID_EXTRA = "rollbackId";
+    static final String ACTION_NAME = MainActivity.class.getName();
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_main);
+        ListView rollbackListView = findViewById(R.id.listView);
+        mRollbackManager = getApplicationContext().getSystemService(RollbackManager.class);
+        initTriggerRollbackButton();
+
+        // Populate list of available rollbacks.
+        List<RollbackInfo> availableRollbacks = mRollbackManager.getAvailableRollbacks();
+        CustomAdapter adapter = new CustomAdapter(availableRollbacks);
+        rollbackListView.setAdapter(adapter);
+
+        // Register receiver for rollback status events.
+        getApplicationContext().registerReceiver(
+                new BroadcastReceiver() {
+                    @Override
+                    public void onReceive(Context context,
+                            Intent intent) {
+                        int rollbackId = intent.getIntExtra(ROLLBACK_ID_EXTRA, -1);
+                        int rollbackStatusCode = intent.getIntExtra(RollbackManager.EXTRA_STATUS,
+                                RollbackManager.STATUS_FAILURE);
+                        String rollbackStatus = "FAILED";
+                        if (rollbackStatusCode == RollbackManager.STATUS_SUCCESS) {
+                            rollbackStatus = "SUCCESS";
+                        }
+                        makeToast("Status for rollback ID " + rollbackId + " is " + rollbackStatus);
+                    }}, new IntentFilter(ACTION_NAME), Context.RECEIVER_NOT_EXPORTED);
+    }
+
+    private void initTriggerRollbackButton() {
+        mTriggerRollbackButton = findViewById(R.id.trigger_rollback_button);
+        mTriggerRollbackButton.setClickable(false);
+        mTriggerRollbackButton.setOnClickListener(v -> {
+            // Commits all selected rollbacks. Rollback status events will be sent to our receiver.
+            for (int i = 0; i < mIdsToRollback.size(); i++) {
+                Intent intent = new Intent(ACTION_NAME);
+                intent.putExtra(ROLLBACK_ID_EXTRA, mIdsToRollback.get(i));
+                PendingIntent pendingIntent = PendingIntent.getBroadcast(
+                        getApplicationContext(), 0, intent, FLAG_MUTABLE);
+                mRollbackManager.commitRollback(mIdsToRollback.get(i),
+                        Collections.emptyList(),
+                        pendingIntent.getIntentSender());
+            }
+        });
+    }
+
+
+
+    private void makeToast(String message) {
+        runOnUiThread(() -> Toast.makeText(MainActivity.this, message, Toast.LENGTH_LONG).show());
+    }
+
+    public class CustomAdapter extends BaseAdapter {
+        List<RollbackInfo> mRollbackInfos;
+        LayoutInflater mInflater = LayoutInflater.from(getApplicationContext());
+
+        CustomAdapter(List<RollbackInfo> rollbackInfos) {
+            mRollbackInfos = rollbackInfos;
+        }
+
+        @Override
+        public int getCount() {
+            return mRollbackInfos.size();
+        }
+
+        @Override
+        public Object getItem(int position) {
+            return mRollbackInfos.get(position);
+        }
+
+        @Override
+        public long getItemId(int position) {
+            return mRollbackInfos.get(position).getRollbackId();
+        }
+
+        @Override
+        public View getView(int position, View view, ViewGroup parent) {
+            if (view == null) {
+                view = mInflater.inflate(R.layout.listitem_rollbackinfo, null);
+            }
+            RollbackInfo rollbackInfo = mRollbackInfos.get(position);
+            TextView rollbackIdView = view.findViewById(R.id.rollback_id);
+            rollbackIdView.setText("Rollback ID " + rollbackInfo.getRollbackId());
+            TextView rollbackPackagesTextView = view.findViewById(R.id.rollback_packages);
+            StringBuilder sb = new StringBuilder();
+            for (int i = 0; i < rollbackInfo.getPackages().size(); i++) {
+                PackageRollbackInfo pkgInfo = rollbackInfo.getPackages().get(i);
+                sb.append(pkgInfo.getPackageName() + ": "
+                        + pkgInfo.getVersionRolledBackFrom().getLongVersionCode() + " -> "
+                        + pkgInfo.getVersionRolledBackTo().getLongVersionCode() + ",");
+            }
+            sb.deleteCharAt(sb.length() - 1);
+            rollbackPackagesTextView.setText(sb.toString());
+            CheckBox checkbox = view.findViewById(R.id.checkbox);
+            checkbox.setOnCheckedChangeListener((buttonView, isChecked) -> {
+                if (isChecked) {
+                    mIdsToRollback.add(rollbackInfo.getRollbackId());
+                } else {
+                    mIdsToRollback.remove(Integer.valueOf(rollbackInfo.getRollbackId()));
+                }
+                mTriggerRollbackButton.setClickable(mIdsToRollback.size() > 0);
+            });
+            return view;
+        }
+    }
+}
diff --git a/tools/localedata/OWNERS b/tools/localedata/OWNERS
new file mode 100644
index 0000000..2501679
--- /dev/null
+++ b/tools/localedata/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 24949
+include platform/external/icu:/OWNERS
diff --git a/tools/validatekeymaps/Android.bp b/tools/validatekeymaps/Android.bp
index ff24d16..25373f9 100644
--- a/tools/validatekeymaps/Android.bp
+++ b/tools/validatekeymaps/Android.bp
@@ -21,6 +21,7 @@
     cflags: [
         "-Wall",
         "-Werror",
+        "-Wextra",
     ],
 
     static_libs: [
@@ -31,6 +32,9 @@
         "liblog",
         "libui-types",
     ],
+    shared_libs: [
+        "libvintf",
+    ],
     target: {
         host_linux: {
             static_libs: [
diff --git a/tools/validatekeymaps/Main.cpp b/tools/validatekeymaps/Main.cpp
index 991b280..cbfdfe4 100644
--- a/tools/validatekeymaps/Main.cpp
+++ b/tools/validatekeymaps/Main.cpp
@@ -97,6 +97,11 @@
         case FileType::KEY_LAYOUT: {
             base::Result<std::shared_ptr<KeyLayoutMap>> ret = KeyLayoutMap::load(filename);
             if (!ret.ok()) {
+                if (ret.error().message() == "Missing kernel config") {
+                    // It means the layout is valid, but won't be loaded on this device because
+                    // this layout requires a certain kernel config.
+                    return true;
+                }
                 error("Error %s parsing key layout file.\n\n", ret.error().message().c_str());
                 return false;
             }