Merge "Stop loading animation for addtional cursor type."
diff --git a/Android.bp b/Android.bp
index ea14b9d..2a820cb 100644
--- a/Android.bp
+++ b/Android.bp
@@ -212,6 +212,7 @@
     name: "framework-non-updatable-sources",
     srcs: [
         // Java/AIDL sources under frameworks/base
+        ":framework-appsearch-sources",
         ":framework-blobstore-sources",
         ":framework-core-sources",
         ":framework-drm-sources",
@@ -870,11 +871,13 @@
     srcs: [
         "core/java/android/os/HidlSupport.java",
         "core/java/android/annotation/IntDef.java",
+        "core/java/android/annotation/IntRange.java",
         "core/java/android/annotation/NonNull.java",
         "core/java/android/annotation/Nullable.java",
         "core/java/android/annotation/SystemApi.java",
         "core/java/android/annotation/TestApi.java",
         "core/java/android/annotation/UnsupportedAppUsage.java",
+        "core/java/android/os/HidlMemory.java",
         "core/java/android/os/HwBinder.java",
         "core/java/android/os/HwBlob.java",
         "core/java/android/os/HwParcel.java",
@@ -1405,8 +1408,10 @@
     srcs: [
         "core/java/android/os/HidlSupport.java",
         "core/java/android/annotation/IntDef.java",
+        "core/java/android/annotation/IntRange.java",
         "core/java/android/annotation/NonNull.java",
         "core/java/android/annotation/SystemApi.java",
+        "core/java/android/os/HidlMemory.java",
         "core/java/android/os/HwBinder.java",
         "core/java/android/os/HwBlob.java",
         "core/java/android/os/HwParcel.java",
diff --git a/apex/appsearch/framework/Android.bp b/apex/appsearch/framework/Android.bp
new file mode 100644
index 0000000..0a65f73
--- /dev/null
+++ b/apex/appsearch/framework/Android.bp
@@ -0,0 +1,39 @@
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+filegroup {
+  name: "framework-appsearch-sources",
+  srcs: [
+    "java/**/*.java",
+    "java/**/*.aidl",
+  ],
+  path: "java",
+}
+
+java_library {
+  name: "framework-appsearch",
+  installable: false,
+  sdk_version: "core_platform",
+  srcs: [
+    ":framework-appsearch-sources",
+  ],
+  aidl: {
+    export_include_dirs: [
+      "java",
+    ],
+  },
+  libs: [
+    "framework-minus-apex",
+  ],
+}
diff --git a/apex/appsearch/framework/java/android/app/appsearch/AppSearchManager.java b/apex/appsearch/framework/java/android/app/appsearch/AppSearchManager.java
new file mode 100644
index 0000000..a8ee35c
--- /dev/null
+++ b/apex/appsearch/framework/java/android/app/appsearch/AppSearchManager.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.app.appsearch;
+
+import android.annotation.SystemService;
+import android.content.Context;
+
+/**
+ * TODO(b/142567528): add comments when implement this class
+ * @hide
+ */
+@SystemService(Context.APP_SEARCH_SERVICE)
+public class AppSearchManager {
+    private final IAppSearchManager mService;
+    /**
+     * TODO(b/142567528): add comments when implement this class
+     * @hide
+     */
+    public AppSearchManager(IAppSearchManager service) {
+        mService = service;
+    }
+}
diff --git a/apex/appsearch/framework/java/android/app/appsearch/AppSearchManagerFrameworkInitializer.java b/apex/appsearch/framework/java/android/app/appsearch/AppSearchManagerFrameworkInitializer.java
new file mode 100644
index 0000000..fcebe3d
--- /dev/null
+++ b/apex/appsearch/framework/java/android/app/appsearch/AppSearchManagerFrameworkInitializer.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.app.appsearch;
+
+import android.app.SystemServiceRegistry;
+import android.content.Context;
+
+/**
+ * This is where the AppSearchManagerService wrapper is registered.
+ *
+ * TODO(b/142567528): add comments when implement this class
+ * @hide
+ */
+public class AppSearchManagerFrameworkInitializer {
+
+    /**
+     * TODO(b/142567528): add comments when implement this class
+     */
+    public static void initialize() {
+        SystemServiceRegistry.registerStaticService(
+                Context.APP_SEARCH_SERVICE, AppSearchManager.class,
+                (service) -> new AppSearchManager(IAppSearchManager.Stub.asInterface(service)));
+    }
+}
diff --git a/apex/appsearch/framework/java/android/app/appsearch/IAppSearchManager.aidl b/apex/appsearch/framework/java/android/app/appsearch/IAppSearchManager.aidl
new file mode 100644
index 0000000..f0f4f51
--- /dev/null
+++ b/apex/appsearch/framework/java/android/app/appsearch/IAppSearchManager.aidl
@@ -0,0 +1,19 @@
+/**
+ * Copyright 2019, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.app.appsearch;
+/** {@hide} */
+interface IAppSearchManager {
+}
diff --git a/apex/appsearch/service/Android.bp b/apex/appsearch/service/Android.bp
new file mode 100644
index 0000000..2821fbe
--- /dev/null
+++ b/apex/appsearch/service/Android.bp
@@ -0,0 +1,24 @@
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+java_library {
+  name: "appsearch-service",
+  installable: true,
+  srcs: [
+    "java/**/*.java",
+  ],
+  libs: [
+    "framework",
+    "services.core",
+  ],
+}
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java b/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java
new file mode 100644
index 0000000..4d44d9d
--- /dev/null
+++ b/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.appsearch;
+
+import android.app.appsearch.IAppSearchManager;
+import android.content.Context;
+
+import com.android.server.SystemService;
+
+/**
+ * TODO(b/142567528): add comments when implement this class
+ */
+public class AppSearchManagerService extends SystemService {
+
+    public AppSearchManagerService(Context context) {
+        super(context);
+    }
+
+    @Override
+    public void onStart() {
+        publishBinderService(Context.APP_SEARCH_SERVICE, new Stub());
+    }
+
+    private class Stub extends IAppSearchManager.Stub {
+    }
+}
diff --git a/api/current.txt b/api/current.txt
index a45583a..63046b8 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -9927,6 +9927,7 @@
     field public static final String ALARM_SERVICE = "alarm";
     field public static final String APPWIDGET_SERVICE = "appwidget";
     field public static final String APP_OPS_SERVICE = "appops";
+    field public static final String APP_SEARCH_SERVICE = "app_search";
     field public static final String AUDIO_SERVICE = "audio";
     field public static final String BATTERY_SERVICE = "batterymanager";
     field public static final int BIND_ABOVE_CLIENT = 8; // 0x8
@@ -30060,7 +30061,8 @@
     method public void addOrUpdatePasspointConfiguration(android.net.wifi.hotspot2.PasspointConfiguration);
     method @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public void addScanResultsListener(@NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.WifiManager.ScanResultsListener);
     method @RequiresPermission(allOf={android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.ACCESS_WIFI_STATE}) public void addSuggestionConnectionStatusListener(@NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.WifiManager.SuggestionConnectionStatusListener);
-    method public static int calculateSignalLevel(int, int);
+    method @Deprecated public static int calculateSignalLevel(int, int);
+    method public int calculateSignalLevel(int);
     method @Deprecated public void cancelWps(android.net.wifi.WifiManager.WpsCallback);
     method public static int compareSignalLevel(int, int);
     method public android.net.wifi.WifiManager.MulticastLock createMulticastLock(String);
@@ -30073,6 +30075,7 @@
     method public android.net.wifi.WifiInfo getConnectionInfo();
     method public android.net.DhcpInfo getDhcpInfo();
     method public int getMaxNumberOfNetworkSuggestionsPerApp();
+    method public int getMaxSignalLevel();
     method @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public java.util.List<android.net.wifi.WifiNetworkSuggestion> getNetworkSuggestions();
     method @Deprecated @RequiresPermission(anyOf={"android.permission.NETWORK_SETTINGS", "android.permission.NETWORK_SETUP_WIZARD"}) public java.util.List<android.net.wifi.hotspot2.PasspointConfiguration> getPasspointConfigurations();
     method public java.util.List<android.net.wifi.ScanResult> getScanResults();
@@ -45590,6 +45593,8 @@
     field public static final int PHONE_TYPE_NONE = 0; // 0x0
     field public static final int PHONE_TYPE_SIP = 3; // 0x3
     field public static final int SET_OPPORTUNISTIC_SUB_INACTIVE_SUBSCRIPTION = 2; // 0x2
+    field public static final int SET_OPPORTUNISTIC_SUB_NO_OPPORTUNISTIC_SUB_AVAILABLE = 3; // 0x3
+    field public static final int SET_OPPORTUNISTIC_SUB_REMOTE_SERVICE_EXCEPTION = 4; // 0x4
     field public static final int SET_OPPORTUNISTIC_SUB_SUCCESS = 0; // 0x0
     field public static final int SET_OPPORTUNISTIC_SUB_VALIDATION_FAILED = 1; // 0x1
     field public static final int SIM_STATE_ABSENT = 1; // 0x1
@@ -45606,8 +45611,14 @@
     field public static final int UNKNOWN_CARRIER_ID = -1; // 0xffffffff
     field public static final int UNSUPPORTED_CARD_ID = -1; // 0xffffffff
     field public static final int UPDATE_AVAILABLE_NETWORKS_ABORTED = 2; // 0x2
+    field public static final int UPDATE_AVAILABLE_NETWORKS_DISABLE_MODEM_FAIL = 5; // 0x5
+    field public static final int UPDATE_AVAILABLE_NETWORKS_ENABLE_MODEM_FAIL = 6; // 0x6
     field public static final int UPDATE_AVAILABLE_NETWORKS_INVALID_ARGUMENTS = 3; // 0x3
+    field public static final int UPDATE_AVAILABLE_NETWORKS_MULTIPLE_NETWORKS_NOT_SUPPORTED = 7; // 0x7
     field public static final int UPDATE_AVAILABLE_NETWORKS_NO_CARRIER_PRIVILEGE = 4; // 0x4
+    field public static final int UPDATE_AVAILABLE_NETWORKS_NO_OPPORTUNISTIC_SUB_AVAILABLE = 8; // 0x8
+    field public static final int UPDATE_AVAILABLE_NETWORKS_REMOTE_SERVICE_EXCEPTION = 9; // 0x9
+    field public static final int UPDATE_AVAILABLE_NETWORKS_SERVICE_IS_DISABLED = 10; // 0xa
     field public static final int UPDATE_AVAILABLE_NETWORKS_SUCCESS = 0; // 0x0
     field public static final int UPDATE_AVAILABLE_NETWORKS_UNKNOWN_FAILURE = 1; // 0x1
     field public static final int USSD_ERROR_SERVICE_UNAVAIL = -2; // 0xfffffffe
@@ -57044,7 +57055,7 @@
     method public int describeContents();
     method public int getLayoutId();
     method public String getPackage();
-    method public boolean onLoadClass(Class);
+    method @Deprecated public boolean onLoadClass(Class);
     method public void reapply(android.content.Context, android.view.View);
     method public void removeAllViews(int);
     method public void setAccessibilityTraversalAfter(int, int);
diff --git a/api/system-current.txt b/api/system-current.txt
index e40fd24..f3cdac3 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -5489,6 +5489,17 @@
     method @NonNull public static java.io.File getVendorDirectory();
   }
 
+  public class HidlMemory implements java.io.Closeable {
+    ctor public HidlMemory(@NonNull String, @IntRange(from=0) long, @Nullable android.os.NativeHandle);
+    method public void close() throws java.io.IOException;
+    method @NonNull public android.os.HidlMemory dup() throws java.io.IOException;
+    method protected void finalize();
+    method @Nullable public android.os.NativeHandle getHandle();
+    method @NonNull public String getName();
+    method public long getSize();
+    method @NonNull public android.os.NativeHandle releaseHandle();
+  }
+
   public class HidlSupport {
     method public static boolean deepEquals(Object, Object);
     method public static int deepHashCode(Object);
@@ -5519,6 +5530,7 @@
     method public final void copyToInt8Array(long, byte[], int);
     method public final boolean getBool(long);
     method public final double getDouble(long);
+    method public final long getFieldHandle(long);
     method public final float getFloat(long);
     method public final short getInt16(long);
     method public final int getInt32(long);
@@ -5533,6 +5545,7 @@
     method public final void putDoubleArray(long, double[]);
     method public final void putFloat(long, float);
     method public final void putFloatArray(long, float[]);
+    method public final void putHidlMemory(long, @NonNull android.os.HidlMemory);
     method public final void putInt16(long, short);
     method public final void putInt16Array(long, short[]);
     method public final void putInt32(long, int);
@@ -5561,9 +5574,11 @@
     method public final double readDouble();
     method public final java.util.ArrayList<java.lang.Double> readDoubleVector();
     method public final android.os.HwBlob readEmbeddedBuffer(long, long, long, boolean);
+    method @NonNull @Nullable public final android.os.HidlMemory readEmbeddedHidlMemory(long, long, long);
     method @Nullable public final android.os.NativeHandle readEmbeddedNativeHandle(long, long);
     method public final float readFloat();
     method public final java.util.ArrayList<java.lang.Float> readFloatVector();
+    method @NonNull public final android.os.HidlMemory readHidlMemory();
     method public final short readInt16();
     method public final java.util.ArrayList<java.lang.Short> readInt16Vector();
     method public final int readInt32();
@@ -5588,6 +5603,7 @@
     method public final void writeDoubleVector(java.util.ArrayList<java.lang.Double>);
     method public final void writeFloat(float);
     method public final void writeFloatVector(java.util.ArrayList<java.lang.Float>);
+    method public final void writeHidlMemory(@NonNull android.os.HidlMemory);
     method public final void writeInt16(short);
     method public final void writeInt16Vector(java.util.ArrayList<java.lang.Short>);
     method public final void writeInt32(int);
@@ -5899,7 +5915,15 @@
   }
 
   public class WorkSource implements android.os.Parcelable {
+    ctor public WorkSource(int);
+    ctor public WorkSource(int, @NonNull String);
     method public android.os.WorkSource.WorkChain createWorkChain();
+    method @Nullable public String getPackageName(int);
+    method public int getUid(int);
+    method @Nullable public java.util.List<android.os.WorkSource.WorkChain> getWorkChains();
+    method public boolean isEmpty();
+    method public int size();
+    method @NonNull public android.os.WorkSource withoutNames();
   }
 
   public static final class WorkSource.WorkChain implements android.os.Parcelable {
@@ -8655,6 +8679,10 @@
     method @Deprecated public static android.telephony.SubscriptionPlan.Builder createRecurringWeekly(java.time.ZonedDateTime);
   }
 
+  public class TelephonyFrameworkInitializer {
+    method public static void registerServiceWrappers();
+  }
+
   public final class TelephonyHistogram implements android.os.Parcelable {
     ctor public TelephonyHistogram(int, int, int);
     ctor public TelephonyHistogram(android.telephony.TelephonyHistogram);
diff --git a/api/test-current.txt b/api/test-current.txt
index 897e825..a8bd9be 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -1808,6 +1808,17 @@
     method public static boolean contains(java.io.File, java.io.File);
   }
 
+  public class HidlMemory implements java.io.Closeable {
+    ctor public HidlMemory(@NonNull String, @IntRange(from=0) long, @Nullable android.os.NativeHandle);
+    method public void close() throws java.io.IOException;
+    method @NonNull public android.os.HidlMemory dup() throws java.io.IOException;
+    method protected void finalize();
+    method @Nullable public android.os.NativeHandle getHandle();
+    method @NonNull public String getName();
+    method public long getSize();
+    method @NonNull public android.os.NativeHandle releaseHandle();
+  }
+
   public abstract class HwBinder implements android.os.IHwBinder {
     ctor public HwBinder();
     method public static final void configureRpcThreadpool(long, boolean);
@@ -1831,6 +1842,7 @@
     method public final void copyToInt8Array(long, byte[], int);
     method public final boolean getBool(long);
     method public final double getDouble(long);
+    method public final long getFieldHandle(long);
     method public final float getFloat(long);
     method public final short getInt16(long);
     method public final int getInt32(long);
@@ -1845,6 +1857,7 @@
     method public final void putDoubleArray(long, double[]);
     method public final void putFloat(long, float);
     method public final void putFloatArray(long, float[]);
+    method public final void putHidlMemory(long, @NonNull android.os.HidlMemory);
     method public final void putInt16(long, short);
     method public final void putInt16Array(long, short[]);
     method public final void putInt32(long, int);
@@ -1873,9 +1886,11 @@
     method public final double readDouble();
     method public final java.util.ArrayList<java.lang.Double> readDoubleVector();
     method public final android.os.HwBlob readEmbeddedBuffer(long, long, long, boolean);
+    method @NonNull @Nullable public final android.os.HidlMemory readEmbeddedHidlMemory(long, long, long);
     method @Nullable public final android.os.NativeHandle readEmbeddedNativeHandle(long, long);
     method public final float readFloat();
     method public final java.util.ArrayList<java.lang.Float> readFloatVector();
+    method @NonNull public final android.os.HidlMemory readHidlMemory();
     method public final short readInt16();
     method public final java.util.ArrayList<java.lang.Short> readInt16Vector();
     method public final int readInt32();
@@ -1900,6 +1915,7 @@
     method public final void writeDoubleVector(java.util.ArrayList<java.lang.Double>);
     method public final void writeFloat(float);
     method public final void writeFloatVector(java.util.ArrayList<java.lang.Float>);
+    method public final void writeHidlMemory(@NonNull android.os.HidlMemory);
     method public final void writeInt16(short);
     method public final void writeInt16Vector(java.util.ArrayList<java.lang.Short>);
     method public final void writeInt32(int);
@@ -2185,10 +2201,12 @@
     method public boolean add(int);
     method public boolean add(int, String);
     method @Deprecated public android.os.WorkSource addReturningNewbs(android.os.WorkSource);
-    method public int get(int);
-    method public String getName(int);
+    method @Nullable public String getPackageName(int);
+    method public int getUid(int);
+    method public boolean isEmpty();
     method @Deprecated public android.os.WorkSource[] setReturningDiffs(android.os.WorkSource);
     method public int size();
+    method @NonNull public android.os.WorkSource withoutNames();
   }
 
 }
diff --git a/cmds/statsd/src/external/StatsPullerManager.cpp b/cmds/statsd/src/external/StatsPullerManager.cpp
index ce27ce6..b5bad05 100644
--- a/cmds/statsd/src/external/StatsPullerManager.cpp
+++ b/cmds/statsd/src/external/StatsPullerManager.cpp
@@ -499,8 +499,9 @@
     StatsdStats::getInstance().notePullerCallbackRegistrationChanged(atomTag, /*registered=*/true);
     kAllPullAtomInfo[{.atomTag = atomTag}] = {.additiveFields = additiveFields,
                                               .coolDownNs = coolDownNs,
+                                              .puller = new StatsCallbackPuller(atomTag, callback),
                                               .pullTimeoutNs = timeoutNs,
-                                              .puller = new StatsCallbackPuller(atomTag, callback)};
+    };
 }
 
 void StatsPullerManager::UnregisterPullerCallback(int32_t atomTag) {
diff --git a/config/preloaded-classes b/config/preloaded-classes
index ab98e5b..0394a7a 100644
--- a/config/preloaded-classes
+++ b/config/preloaded-classes
@@ -514,6 +514,7 @@
 android.app.admin.SystemUpdateInfo
 android.app.admin.SystemUpdatePolicy$1
 android.app.admin.SystemUpdatePolicy
+android.app.appsearch.AppSearchManagerFrameworkInitializer
 android.app.assist.AssistContent$1
 android.app.assist.AssistContent
 android.app.assist.AssistStructure$1
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index fce7449..3ac88eb 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -10410,6 +10410,16 @@
             p.recycle();
             return brv;
         }
+
+        /**
+         * Override and return true, since {@link RemoteViews#onLoadClass(Class)} is not overridden.
+         *
+         * @see RemoteViews#shouldUseStaticFilter()
+         */
+        @Override
+        protected boolean shouldUseStaticFilter() {
+            return true;
+        }
     }
 
     /**
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index d0ba879..5effa1b 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -22,6 +22,7 @@
 import android.app.ContextImpl.ServiceInitializationState;
 import android.app.admin.DevicePolicyManager;
 import android.app.admin.IDevicePolicyManager;
+import android.app.appsearch.AppSearchManagerFrameworkInitializer;
 import android.app.blob.BlobStoreManagerFrameworkInitializer;
 import android.app.contentsuggestions.ContentSuggestionsManager;
 import android.app.contentsuggestions.IContentSuggestionsManager;
@@ -166,12 +167,8 @@
 import android.service.persistentdata.PersistentDataBlockManager;
 import android.service.vr.IVrManager;
 import android.telecom.TelecomManager;
-import android.telephony.CarrierConfigManager;
-import android.telephony.SubscriptionManager;
-import android.telephony.TelephonyManager;
+import android.telephony.TelephonyFrameworkInitializer;
 import android.telephony.TelephonyRegistryManager;
-import android.telephony.euicc.EuiccCardManager;
-import android.telephony.euicc.EuiccManager;
 import android.util.ArrayMap;
 import android.util.Log;
 import android.view.ContextThemeWrapper;
@@ -604,13 +601,6 @@
                         return new SystemUpdateManager(service);
                     }});
 
-        registerService(Context.TELEPHONY_SERVICE, TelephonyManager.class,
-                new CachedServiceFetcher<TelephonyManager>() {
-            @Override
-            public TelephonyManager createService(ContextImpl ctx) {
-                return new TelephonyManager(ctx.getOuterContext());
-            }});
-
         registerService(Context.TELEPHONY_REGISTRY_SERVICE, TelephonyRegistryManager.class,
             new CachedServiceFetcher<TelephonyRegistryManager>() {
                 @Override
@@ -618,20 +608,6 @@
                     return new TelephonyRegistryManager(ctx);
                 }});
 
-        registerService(Context.TELEPHONY_SUBSCRIPTION_SERVICE, SubscriptionManager.class,
-                new CachedServiceFetcher<SubscriptionManager>() {
-            @Override
-            public SubscriptionManager createService(ContextImpl ctx) throws ServiceNotFoundException {
-                return new SubscriptionManager(ctx.getOuterContext());
-            }});
-
-        registerService(Context.CARRIER_CONFIG_SERVICE, CarrierConfigManager.class,
-                new CachedServiceFetcher<CarrierConfigManager>() {
-            @Override
-            public CarrierConfigManager createService(ContextImpl ctx) {
-                return new CarrierConfigManager(ctx.getOuterContext());
-            }});
-
         registerService(Context.TELECOM_SERVICE, TelecomManager.class,
                 new CachedServiceFetcher<TelecomManager>() {
             @Override
@@ -639,20 +615,6 @@
                 return new TelecomManager(ctx.getOuterContext());
             }});
 
-        registerService(Context.EUICC_SERVICE, EuiccManager.class,
-                new CachedServiceFetcher<EuiccManager>() {
-            @Override
-            public EuiccManager createService(ContextImpl ctx) {
-                return new EuiccManager(ctx.getOuterContext());
-            }});
-
-        registerService(Context.EUICC_CARD_SERVICE, EuiccCardManager.class,
-                new CachedServiceFetcher<EuiccCardManager>() {
-                    @Override
-                    public EuiccCardManager createService(ContextImpl ctx) {
-                        return new EuiccCardManager(ctx.getOuterContext());
-                    }});
-
         registerService(Context.UI_MODE_SERVICE, UiModeManager.class,
                 new CachedServiceFetcher<UiModeManager>() {
             @Override
@@ -1301,6 +1263,8 @@
 
             JobSchedulerFrameworkInitializer.registerServiceWrappers();
             BlobStoreManagerFrameworkInitializer.initialize();
+            TelephonyFrameworkInitializer.registerServiceWrappers();
+            AppSearchManagerFrameworkInitializer.initialize();
         } finally {
             // If any of the above code throws, we're in a pretty bad shape and the process
             // will likely crash, but we'll reset it just in case there's an exception handler...
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 7703e08..8507316 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -4898,6 +4898,15 @@
     public static final String BATTERY_STATS_SERVICE = "batterystats";
 
     /**
+     * Use with {@link #getSystemService(String)} to retrieve an
+     * AppSearchManager for indexing and querying app data managed
+     * by the system.
+     *
+     * @see #getSystemService(String)
+     */
+    public static final String APP_SEARCH_SERVICE = "app_search";
+
+    /**
      * Determine whether the given permission is allowed for a particular
      * process and user ID running in the system.
      *
diff --git a/core/java/android/content/om/OverlayableInfo.java b/core/java/android/content/om/OverlayableInfo.java
new file mode 100644
index 0000000..5923907
--- /dev/null
+++ b/core/java/android/content/om/OverlayableInfo.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content.om;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
+import com.android.internal.util.DataClass;
+
+import java.util.Objects;
+
+/**
+ * Immutable info on an overlayable defined inside a target package.
+ *
+ * @hide
+ */
+@DataClass(genSetters = false, genEqualsHashCode = true, genHiddenConstructor = true)
+public final class OverlayableInfo {
+
+    /**
+     * The "name" attribute of the overlayable tag. Used to identify the set of resources overlaid.
+     */
+    @NonNull
+    public final String name;
+
+    /**
+     * The "actor" attribute of the overlayable tag. Used to signal which apps are allowed to
+     * modify overlay state for this overlayable.
+     */
+    @Nullable
+    public final String actor;
+
+    // CHECKSTYLE:OFF Generated code
+    //
+
+
+
+    // Code below generated by codegen v1.0.3.
+    //
+    // DO NOT MODIFY!
+    // CHECKSTYLE:OFF Generated code
+    //
+    // To regenerate run:
+    // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/content/om/OverlayableInfo.java
+
+
+    /**
+     * Creates a new OverlayableInfo.
+     *
+     * @param name
+     *   The "name" attribute of the overlayable tag. Used to identify the set of resources overlaid.
+     * @param actor
+     *   The "actor" attribute of the overlayable tag. Used to signal which apps are allowed to
+     *   modify overlay state for this overlayable.
+     * @hide
+     */
+    @DataClass.Generated.Member
+    public OverlayableInfo(
+            @NonNull String name,
+            @Nullable String actor) {
+        this.name = name;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, name);
+        this.actor = actor;
+
+        // onConstructed(); // You can define this method to get a callback
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public boolean equals(Object o) {
+        // You can override field equality logic by defining either of the methods like:
+        // boolean fieldNameEquals(OverlayableInfo other) { ... }
+        // boolean fieldNameEquals(FieldType otherValue) { ... }
+
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        @SuppressWarnings("unchecked")
+        OverlayableInfo that = (OverlayableInfo) o;
+        //noinspection PointlessBooleanExpression
+        return true
+                && Objects.equals(name, that.name)
+                && Objects.equals(actor, that.actor);
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public int hashCode() {
+        // You can override field hashCode logic by defining methods like:
+        // int fieldNameHashCode() { ... }
+
+        int _hash = 1;
+        _hash = 31 * _hash + Objects.hashCode(name);
+        _hash = 31 * _hash + Objects.hashCode(actor);
+        return _hash;
+    }
+
+    @DataClass.Generated(
+            time = 1570059850579L,
+            codegenVersion = "1.0.3",
+            sourceFile = "frameworks/base/core/java/android/content/om/OverlayableInfo.java",
+            inputSignatures = "public final @android.annotation.NonNull java.lang.String name\npublic final @android.annotation.Nullable java.lang.String actor\nclass OverlayableInfo extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genSetters=false, genEqualsHashCode=true, genHiddenConstructor=true)")
+    @Deprecated
+    private void __metadata() {}
+
+}
diff --git a/core/java/android/content/res/ApkAssets.java b/core/java/android/content/res/ApkAssets.java
index de1d514..ad37555 100644
--- a/core/java/android/content/res/ApkAssets.java
+++ b/core/java/android/content/res/ApkAssets.java
@@ -18,6 +18,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.UnsupportedAppUsage;
+import android.content.om.OverlayableInfo;
 import android.content.res.loader.ResourcesProvider;
 import android.text.TextUtils;
 
@@ -254,6 +255,17 @@
         }
     }
 
+    /** @hide */
+    @Nullable
+    public OverlayableInfo getOverlayableInfo(String overlayableName) throws IOException {
+        return nativeGetOverlayableInfo(mNativePtr, overlayableName);
+    }
+
+    /** @hide */
+    public boolean definesOverlayable() throws IOException {
+        return nativeDefinesOverlayable(mNativePtr);
+    }
+
     /**
      * Returns false if the underlying APK was changed since this ApkAssets was loaded.
      */
@@ -305,4 +317,7 @@
     private static native long nativeGetStringBlock(long ptr);
     private static native boolean nativeIsUpToDate(long ptr);
     private static native long nativeOpenXml(long ptr, @NonNull String fileName) throws IOException;
+    private static native @Nullable OverlayableInfo nativeGetOverlayableInfo(long ptr,
+            String overlayableName) throws IOException;
+    private static native boolean nativeDefinesOverlayable(long ptr) throws IOException;
 }
diff --git a/core/java/android/os/HidlMemory.java b/core/java/android/os/HidlMemory.java
new file mode 100644
index 0000000..aeb6589
--- /dev/null
+++ b/core/java/android/os/HidlMemory.java
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os;
+
+import android.annotation.IntRange;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.annotation.TestApi;
+
+import java.io.Closeable;
+import java.io.IOException;
+
+/**
+ * An abstract representation of a memory block, as representing by the HIDL system.
+ *
+ * The block is defined by a {name, size, handle} tuple, where the name is used to determine how to
+ * interpret the handle. The underlying handle is assumed to be owned by this instance and will be
+ * closed as soon as {@link #close()} is called on this instance, or this instance has been
+ * finalized (the latter supports using it in a shared manner without having to worry about who owns
+ * this instance, the former is more efficient resource-wise and is recommended for most use-cases).
+ * Note, however, that ownership of the handle does not necessarily imply ownership of the
+ * underlying file descriptors - the underlying handle may or may not own them. If you want the
+ * underlying handle to outlive this instance, call {@link #releaseHandle()} to obtain the handle
+ * and detach the ownership relationship.
+ *
+ * @hide
+ */
+@SystemApi
+@TestApi
+public class HidlMemory implements Closeable {
+    private final @NonNull String mName;
+    private final long mSize;
+    private @Nullable NativeHandle mHandle;
+    private long mNativeContext;  // For use of native code.
+
+    /**
+     * Constructor.
+     *
+     * @param name      The name of the IMapper service used to resolve the handle (e.g. "ashmem").
+     * @param size      The (non-negative) size in bytes of the memory block.
+     * @param handle    The handle. May be null. This instance will own the handle and will close it
+     *                  as soon as {@link #close()} is called or the object is destroyed. This, this
+     *                  handle instance should generally not be shared with other clients.
+     */
+    public HidlMemory(@NonNull String name, @IntRange(from = 0) long size,
+            @Nullable NativeHandle handle) {
+        mName = name;
+        mSize = size;
+        mHandle = handle;
+    }
+
+    /**
+     * Create a copy of this instance, where the underlying handle (and its file descriptors) have
+     * been duplicated.
+     */
+    @NonNull
+    public HidlMemory dup() throws IOException {
+        return new HidlMemory(mName, mSize, mHandle != null ? mHandle.dup() : null);
+    }
+
+    /**
+     * Close the underlying native handle. No-op if handle is null or has been released using {@link
+     * #releaseHandle()}.
+     */
+    @Override
+    public void close() throws IOException {
+        if (mHandle != null) {
+            mHandle.close();
+        }
+    }
+
+    /**
+     * Disowns the underlying handle and returns it. This object becomes invalid.
+     *
+     * @return The underlying handle.
+     */
+    @NonNull
+    public NativeHandle releaseHandle() {
+        NativeHandle handle = mHandle;
+        mHandle = null;
+        return handle;
+    }
+
+    /**
+     * Gets the name, which represents how the handle is to be interpreted.
+     *
+     * @return The name.
+     */
+    @NonNull
+    public String getName() {
+        return mName;
+    }
+
+    /**
+     * Gets the size of the block, in bytes.
+     *
+     * @return The size.
+     */
+    public long getSize() {
+        return mSize;
+    }
+
+    /**
+     * Gets a native handle. The actual interpretation depends on the name and is implementation
+     * defined.
+     *
+     * @return The native handle.
+     */
+    @Nullable
+    public NativeHandle getHandle() {
+        return mHandle;
+    }
+
+    @Override
+    protected void finalize() {
+        try {
+            close();
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        } finally {
+            nativeFinalize();
+        }
+    }
+
+    private native void nativeFinalize();
+}
diff --git a/core/java/android/os/HidlMemoryUtil.java b/core/java/android/os/HidlMemoryUtil.java
new file mode 100644
index 0000000..b08822d
--- /dev/null
+++ b/core/java/android/os/HidlMemoryUtil.java
@@ -0,0 +1,215 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.os;
+
+import static android.system.OsConstants.MAP_SHARED;
+import static android.system.OsConstants.PROT_READ;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SuppressLint;
+import android.annotation.SystemApi;
+import android.annotation.TestApi;
+import android.system.ErrnoException;
+import android.system.Os;
+import android.util.Log;
+
+import com.android.internal.util.Preconditions;
+
+import java.nio.ByteBuffer;
+import java.nio.DirectByteBuffer;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Provides utilities for dealing with HidlMemory.
+ *
+ * @hide
+ */
+public final class HidlMemoryUtil {
+    static private final String TAG = "HidlMemoryUtil";
+
+    private HidlMemoryUtil() {
+    }
+
+    /**
+     * Copies a byte-array into a new Ashmem region and return it as HidlMemory.
+     * The returned instance owns the underlying file descriptors, and the client should generally
+     * call close on it when no longer in use (or otherwise, when the object gets destroyed it will
+     * be closed).
+     *
+     * @param input The input byte array.
+     * @return A HidlMemory instance, containing a copy of the input.
+     */
+    public static @NonNull
+    HidlMemory byteArrayToHidlMemory(@NonNull byte[] input) {
+        return byteArrayToHidlMemory(input, null);
+    }
+
+    /**
+     * Copies a byte-array into a new Ashmem region and return it as HidlMemory.
+     * The returned instance owns the underlying file descriptors, and the client should generally
+     * call close on it when no longer in use (or otherwise, when the object gets destroyed it will
+     * be closed).
+     *
+     * @param input The input byte array.
+     * @param name  An optional name for the ashmem region.
+     * @return A HidlMemory instance, containing a copy of the input.
+     */
+    public static @NonNull
+    HidlMemory byteArrayToHidlMemory(@NonNull byte[] input, @Nullable String name) {
+        Preconditions.checkNotNull(input);
+
+        if (input.length == 0) {
+            return new HidlMemory("ashmem", 0, null);
+        }
+
+        try {
+            SharedMemory shmem = SharedMemory.create(name != null ? name : "", input.length);
+            ByteBuffer buffer = shmem.mapReadWrite();
+            buffer.put(input);
+            shmem.unmap(buffer);
+            NativeHandle handle = new NativeHandle(shmem.getFileDescriptor(), true);
+            return new HidlMemory("ashmem", input.length, handle);
+        } catch (ErrnoException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * Copies a byte list into a new Ashmem region and return it as HidlMemory.
+     * The returned instance owns the underlying file descriptors, and the client should generally
+     * call close on it when no longer in use (or otherwise, when the object gets destroyed it will
+     * be closed).
+     *
+     * @param input The input byte list.
+     * @return A HidlMemory instance, containing a copy of the input.
+     */
+    public static @NonNull
+    HidlMemory byteListToHidlMemory(@NonNull List<Byte> input) {
+        return byteListToHidlMemory(input, null);
+    }
+
+    /**
+     * Copies a byte list into a new Ashmem region and return it as HidlMemory.
+     * The returned instance owns the underlying file descriptors, and the client should generally
+     * call close on it when no longer in use (or otherwise, when the object gets destroyed it will
+     * be closed).
+     *
+     * @param input The input byte list.
+     * @param name  An optional name for the ashmem region.
+     * @return A HidlMemory instance, containing a copy of the input.
+     */
+    public static @NonNull
+    HidlMemory byteListToHidlMemory(@NonNull List<Byte> input, @Nullable String name) {
+        Preconditions.checkNotNull(input);
+
+        if (input.isEmpty()) {
+            return new HidlMemory("ashmem", 0, null);
+        }
+
+        try {
+            SharedMemory shmem = SharedMemory.create(name != null ? name : "", input.size());
+            ByteBuffer buffer = shmem.mapReadWrite();
+            for (Byte b : input) {
+                buffer.put(b);
+            }
+            shmem.unmap(buffer);
+            NativeHandle handle = new NativeHandle(shmem.getFileDescriptor(), true);
+            return new HidlMemory("ashmem", input.size(), handle);
+        } catch (ErrnoException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * Copies all data from a HidlMemory instance into a byte array.
+     *
+     * @param mem The HidlMemory instance. Must be of name "ashmem" and of size that doesn't exceed
+     *            {@link Integer#MAX_VALUE}.
+     * @return A byte array, containing a copy of the input.
+     */
+    public static @NonNull
+    byte[] hidlMemoryToByteArray(@NonNull HidlMemory mem) {
+        Preconditions.checkNotNull(mem);
+        Preconditions.checkArgumentInRange(mem.getSize(), 0L, (long) Integer.MAX_VALUE,
+                "Memory size");
+        Preconditions.checkArgument(mem.getSize() == 0 || mem.getName().equals("ashmem"),
+                "Unsupported memory type: %s", mem.getName());
+
+        if (mem.getSize() == 0) {
+            return new byte[0];
+        }
+
+        ByteBuffer buffer = getBuffer(mem);
+        byte[] result = new byte[buffer.remaining()];
+        buffer.get(result);
+        return result;
+    }
+
+    /**
+     * Copies all data from a HidlMemory instance into a byte list.
+     *
+     * @param mem The HidlMemory instance. Must be of name "ashmem" and of size that doesn't exceed
+     *            {@link Integer#MAX_VALUE}.
+     * @return A byte list, containing a copy of the input.
+     */
+    @SuppressLint("ConcreteCollection")
+    public static @NonNull
+    ArrayList<Byte> hidlMemoryToByteList(@NonNull HidlMemory mem) {
+        Preconditions.checkNotNull(mem);
+        Preconditions.checkArgumentInRange(mem.getSize(), 0L, (long) Integer.MAX_VALUE,
+                "Memory size");
+        Preconditions.checkArgument(mem.getSize() == 0 || mem.getName().equals("ashmem"),
+                "Unsupported memory type: %s", mem.getName());
+
+        if (mem.getSize() == 0) {
+            return new ArrayList<>();
+        }
+
+        ByteBuffer buffer = getBuffer(mem);
+
+        ArrayList<Byte> result = new ArrayList<>(buffer.remaining());
+        while (buffer.hasRemaining()) {
+            result.add(buffer.get());
+        }
+        return result;
+    }
+
+    private static ByteBuffer getBuffer(@NonNull HidlMemory mem) {
+        try {
+            final int size = (int) mem.getSize();
+
+            if (size == 0) {
+                return ByteBuffer.wrap(new byte[0]);
+            }
+
+            NativeHandle handle = mem.getHandle();
+
+            final long address = Os.mmap(0, size, PROT_READ, MAP_SHARED, handle.getFileDescriptor(),
+                    0);
+            return new DirectByteBuffer(size, address, handle.getFileDescriptor(), () -> {
+                try {
+                    Os.munmap(address, size);
+                } catch (ErrnoException e) {
+                    Log.wtf(TAG, e);
+                }
+            }, true);
+        } catch (ErrnoException e) {
+            throw new RuntimeException(e);
+        }
+    }
+}
diff --git a/core/java/android/os/HwBlob.java b/core/java/android/os/HwBlob.java
index 2c453bf..154227b2 100644
--- a/core/java/android/os/HwBlob.java
+++ b/core/java/android/os/HwBlob.java
@@ -92,6 +92,14 @@
      * @throws IndexOutOfBoundsException when offset is out of this HwBlob
      */
     public native final String getString(long offset);
+    /**
+     * For embedded fields that follow a two-step approach for reading, first obtain their field
+     * handle using this method, and pass that field handle to the respective
+     * HwParcel.readEmbedded*() method.
+     * @param offset The field offset.
+     * @return The field handle.
+     */
+    public native final long getFieldHandle(long offset);
 
     /**
      * Copy the blobs data starting from the given byte offset into the range, copying
@@ -312,6 +320,20 @@
     public native final void putBlob(long offset, HwBlob blob);
 
     /**
+     * Writes a HidlMemory instance (without duplicating the underlying file descriptors) at an
+     * offset.
+     *
+     * @param offset location to write value
+     * @param mem    a {@link HidlMemory} instance to write
+     * @throws IndexOutOfBoundsException when [offset, offset + sizeof(jobject)] is out of range
+     */
+    public final void putHidlMemory(long offset, @NonNull HidlMemory mem) {
+        putNativeHandle(offset + 0  /* offset of 'handle' field. */, mem.getHandle());
+        putInt64(offset + 16  /* offset of 'size' field. */, mem.getSize());
+        putString(offset + 24  /* offset of 'name' field. */, mem.getName());
+    }
+
+    /**
      * @return current handle of HwBlob for reference in a parcelled binder transaction
      */
     public native final long handle();
diff --git a/core/java/android/os/HwParcel.java b/core/java/android/os/HwParcel.java
index 5e8929c..9786f16 100644
--- a/core/java/android/os/HwParcel.java
+++ b/core/java/android/os/HwParcel.java
@@ -324,6 +324,15 @@
     public native final void writeStrongBinder(IHwBinder binder);
 
     /**
+     * Write a HidlMemory object (without duplicating the underlying file descriptors) to the end
+     * of the parcel.
+     *
+     * @param memory value to write
+     */
+    @FastNative
+    public native final void writeHidlMemory(@NonNull HidlMemory memory);
+
+    /**
      * Checks to make sure that the interface name matches the name written by the parcel
      * sender by writeInterfaceToken
      *
@@ -582,6 +591,38 @@
     public native final IHwBinder readStrongBinder();
 
     /**
+     * Reads a HidlMemory value (without duplicating the underlying file
+     * descriptors) from the parcel. These file descriptors will only
+     * be open for the duration that the binder window is open. If they
+     * are needed further, you must call {@link HidlMemory#dup()}, which makes you also
+     * responsible for calling {@link HidlMemory#close()}.
+     *
+     * @return HidlMemory object read from parcel.
+     * @throws IllegalArgumentException if the parcel has no more data or is otherwise corrupt.
+     */
+    @FastNative
+    @NonNull
+    public native final HidlMemory readHidlMemory();
+
+    /**
+     * Reads an embedded HidlMemory (without duplicating the underlying
+     * file descriptors) from the parcel. These file descriptors will only
+     * be open for the duration that the binder window is open. If they
+     * are needed further, you must call {@link HidlMemory#dup()}. You
+     * do not need to call close on the HidlMemory returned from this.
+     *
+     * @param fieldHandle  handle of the field, obtained from the {@link HwBlob}.
+     * @param parentHandle parentHandle from which to read the embedded object
+     * @param offset       offset into parent
+     * @return a {@link HidlMemory} instance parsed from the parcel
+     * @throws IllegalArgumentException if the parcel has no more data
+     */
+    @FastNative
+    @NonNull
+    public native final @Nullable
+    HidlMemory readEmbeddedHidlMemory(long fieldHandle, long parentHandle, long offset);
+
+    /**
      * Read opaque segment of data as a blob.
      * @return blob of size expectedSize
      * @throws IllegalArgumentException if the parcel has no more data
diff --git a/core/java/android/os/StatsLogEventWrapper.java b/core/java/android/os/StatsLogEventWrapper.java
index 89c9bb2..320fc13 100644
--- a/core/java/android/os/StatsLogEventWrapper.java
+++ b/core/java/android/os/StatsLogEventWrapper.java
@@ -139,7 +139,7 @@
         out.writeLong(mElapsedTimeNs);
         out.writeLong(mWallClockTimeNs);
         if (mWorkSource != null) {
-            ArrayList<android.os.WorkSource.WorkChain> workChains = mWorkSource.getWorkChains();
+            List<WorkSource.WorkChain> workChains = mWorkSource.getWorkChains();
             // number of chains
             out.writeInt(workChains.size());
             for (int i = 0; i < workChains.size(); i++) {
diff --git a/core/java/android/os/WorkSource.java b/core/java/android/os/WorkSource.java
index 825fc64..b5635a4 100644
--- a/core/java/android/os/WorkSource.java
+++ b/core/java/android/os/WorkSource.java
@@ -13,13 +13,15 @@
 import android.util.proto.ProtoOutputStream;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.Preconditions;
 
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.List;
 
 /**
  * Describes the source of some work that may be done by someone else.
- * Currently the public representation of what a work source is is not
+ * Currently the public representation of what a work source is not
  * defined; this is an opaque container.
  */
 public class WorkSource implements Parcelable {
@@ -48,7 +50,7 @@
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
     static WorkSource sNewbWork;
     /**
-     * For returning gone work form a modification operation.
+     * For returning gone work from a modification operation.
      */
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
     static WorkSource sGoneWork;
@@ -91,9 +93,14 @@
         }
     }
 
-    /** @hide */
-    @UnsupportedAppUsage
+
+    /**
+     * Creates a work source with the given uid.
+     * @param uid the uid performing the work
+     * @hide
+     */
     @TestApi
+    @SystemApi
     public WorkSource(int uid) {
         mNum = 1;
         mUids = new int[] { uid, 0 };
@@ -101,14 +108,18 @@
         mChains = null;
     }
 
-    /** @hide */
-    public WorkSource(int uid, String name) {
-        if (name == null) {
-            throw new NullPointerException("Name can't be null");
-        }
+    /**
+     * Creates a work source with the given uid and package name.
+     * @param uid the uid performing the work
+     * @param packageName the package performing the work
+     * @hide
+     */
+    @SystemApi
+    public WorkSource(int uid, @NonNull String packageName) {
+        Preconditions.checkNotNull(packageName, "packageName can't be null");
         mNum = 1;
         mUids = new int[] { uid, 0 };
-        mNames = new String[] { name, null };
+        mNames = new String[] { packageName, null };
         mChains = null;
     }
 
@@ -138,17 +149,34 @@
                 Global.CHAINED_BATTERY_ATTRIBUTION_ENABLED, 0) == 1;
     }
 
-    /** @hide */
-    @UnsupportedAppUsage
+    /**
+     * Returns the size of this work source.
+     * @hide
+     */
     @TestApi
+    @SystemApi
     public int size() {
         return mNum;
     }
 
-    /** @hide */
+    /**
+     * @deprecated use {{@link #getUid(int)}} instead.
+     * @hide
+     */
     @UnsupportedAppUsage
-    @TestApi
+    @Deprecated
     public int get(int index) {
+        return getUid(index);
+    }
+
+    /**
+     * Get the uid at the given index.
+     * If {@code index} < 0 or {@code index} >= {@link #size() N}, then the behavior is undefined.
+     * @hide
+     */
+    @TestApi
+    @SystemApi
+    public int getUid(int index) {
         return mUids[index];
     }
 
@@ -167,10 +195,25 @@
         return mNum > 0 ? mUids[0] : mChains.get(0).getAttributionUid();
     }
 
-    /** @hide */
+    /**
+     * @deprecated use {{@link #getPackageName(int)}} instead.
+     * @hide
+     */
     @UnsupportedAppUsage
-    @TestApi
+    @Deprecated
     public String getName(int index) {
+        return getPackageName(index);
+    }
+
+    /**
+     * Get the package name at the given index.
+     * If {@code index} < 0 or {@code index} >= {@link #size() N}, then the behavior is undefined.
+     * @hide
+     */
+    @TestApi
+    @SystemApi
+    @Nullable
+    public String getPackageName(int index) {
         return mNames != null ? mNames[index] : null;
     }
 
@@ -179,9 +222,8 @@
      * intact.
      *
      * <p>Useful when combining with another WorkSource that doesn't have names.
-     * @hide
      */
-    public void clearNames() {
+    private void clearNames() {
         if (mNames != null) {
             mNames = null;
             // Clear out any duplicate uids now that we don't have names to disambiguate them.
@@ -407,6 +449,22 @@
     }
 
     /**
+     * Returns a copy of this work source without any package names.
+     * If any {@link WorkChain WorkChains} are present, they are left intact.
+     *
+     * @return a {@link WorkSource} without any package names.
+     * @hide
+     */
+    @SystemApi
+    @TestApi
+    @NonNull
+    public WorkSource withoutNames() {
+        final WorkSource copy = new WorkSource(this);
+        copy.clearNames();
+        return copy;
+    }
+
+    /**
      * Legacy API: DO NOT USE. Only in use from unit tests.
      *
      * @hide
@@ -524,6 +582,8 @@
      *
      * @hide for internal use only.
      */
+    @SystemApi
+    @TestApi
     public boolean isEmpty() {
         return mNum == 0 && (mChains == null || mChains.isEmpty());
     }
@@ -532,7 +592,9 @@
      * @return the list of {@code WorkChains} associated with this {@code WorkSource}.
      * @hide
      */
-    public ArrayList<WorkChain> getWorkChains() {
+    @SystemApi
+    @Nullable
+    public List<WorkChain> getWorkChains() {
         return mChains;
     }
 
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index 3251127..6458737 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -199,6 +199,8 @@
     private static native void nativeWriteTransactionToParcel(long nativeObject, Parcel out);
     private static native void nativeSetShadowRadius(long transactionObj, long nativeObject,
             float shadowRadius);
+    private static native void nativeSetGlobalShadowSettings(@Size(4) float[] ambientColor,
+            @Size(4) float[] spotColor, float lightPosY, float lightPosZ, float lightRadius);
 
     private final CloseGuard mCloseGuard = CloseGuard.get();
     private String mName;
@@ -1979,6 +1981,42 @@
         return sc;
     }
 
+    private static void validateColorArg(@Size(4) float[] color) {
+        final String msg = "Color must be specified as a float array with"
+                + " four values to represent r, g, b, a in range [0..1]";
+        if (color.length != 4) {
+            throw new IllegalArgumentException(msg);
+        }
+        for (float c:color) {
+            if ((c < 0.f) || (c > 1.f)) {
+                throw new IllegalArgumentException(msg);
+            }
+        }
+    }
+
+    /**
+     * Sets the global configuration for all the shadows drawn by SurfaceFlinger. Shadow follows
+     * material design guidelines.
+     *
+     * @param ambientColor Color applied to the ambient shadow. The alpha is premultiplied. A
+     *                     float array with four values to represent r, g, b, a in range [0..1]
+     * @param spotColor Color applied to the spot shadow. The alpha is premultiplied. The position
+     *                  of the spot shadow depends on the light position. A float array with
+     *                  four values to represent r, g, b, a in range [0..1]
+     * @param lightPosY Y axis position of the light used to cast the spot shadow in pixels.
+     * @param lightPosZ Z axis position of the light used to cast the spot shadow in pixels. The X
+     *                  axis position is set to the display width / 2.
+     * @param lightRadius Radius of the light casting the shadow in pixels.
+     *[
+     * @hide
+     */
+    public static void setGlobalShadowSettings(@Size(4) float[] ambientColor,
+            @Size(4) float[] spotColor, float lightPosY, float lightPosZ, float lightRadius) {
+        validateColorArg(ambientColor);
+        validateColorArg(spotColor);
+        nativeSetGlobalShadowSettings(ambientColor, spotColor, lightPosY, lightPosZ, lightRadius);
+    }
+
      /**
      * An atomic set of changes to a set of SurfaceControl.
      */
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 89b111d..afa661e 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -4966,6 +4966,8 @@
         protected static final int FINISH_HANDLED = 1;
         protected static final int FINISH_NOT_HANDLED = 2;
 
+        private String mTracePrefix;
+
         /**
          * Creates an input stage.
          * @param next The next stage to which events should be forwarded.
@@ -4983,7 +4985,14 @@
             } else if (shouldDropInputEvent(q)) {
                 finish(q, false);
             } else {
-                apply(q, onProcess(q));
+                traceEvent(q, Trace.TRACE_TAG_VIEW);
+                final int result;
+                try {
+                    result = onProcess(q);
+                } finally {
+                    Trace.traceEnd(Trace.TRACE_TAG_VIEW);
+                }
+                apply(q, result);
             }
         }
 
@@ -5093,6 +5102,17 @@
                 return false;
             }
         }
+
+        private void traceEvent(QueuedInputEvent q, long traceTag) {
+            if (!Trace.isTagEnabled(traceTag)) {
+                return;
+            }
+
+            if (mTracePrefix == null) {
+                mTracePrefix = getClass().getSimpleName();
+            }
+            Trace.traceBegin(traceTag, mTracePrefix + " seq#=" + q.mEvent.getSequenceNumber());
+        }
     }
 
     /**
@@ -7709,26 +7729,46 @@
     private void deliverInputEvent(QueuedInputEvent q) {
         Trace.asyncTraceBegin(Trace.TRACE_TAG_VIEW, "deliverInputEvent",
                 q.mEvent.getSequenceNumber());
-        if (mInputEventConsistencyVerifier != null) {
-            mInputEventConsistencyVerifier.onInputEvent(q.mEvent, 0);
-        }
 
-        InputStage stage;
-        if (q.shouldSendToSynthesizer()) {
-            stage = mSyntheticInputStage;
-        } else {
-            stage = q.shouldSkipIme() ? mFirstPostImeInputStage : mFirstInputStage;
+        if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
+            Trace.traceBegin(Trace.TRACE_TAG_VIEW, "deliverInputEvent src=0x"
+                    + Integer.toHexString(q.mEvent.getSource()) + " eventTimeNano="
+                    + q.mEvent.getEventTimeNano() + " seq#=" + q.mEvent.getSequenceNumber());
         }
+        try {
+            if (mInputEventConsistencyVerifier != null) {
+                Trace.traceBegin(Trace.TRACE_TAG_VIEW, "verifyEventConsistency");
+                try {
+                    mInputEventConsistencyVerifier.onInputEvent(q.mEvent, 0);
+                } finally {
+                    Trace.traceEnd(Trace.TRACE_TAG_VIEW);
+                }
+            }
 
-        if (q.mEvent instanceof KeyEvent) {
-            mUnhandledKeyManager.preDispatch((KeyEvent) q.mEvent);
-        }
+            InputStage stage;
+            if (q.shouldSendToSynthesizer()) {
+                stage = mSyntheticInputStage;
+            } else {
+                stage = q.shouldSkipIme() ? mFirstPostImeInputStage : mFirstInputStage;
+            }
 
-        if (stage != null) {
-            handleWindowFocusChanged();
-            stage.deliver(q);
-        } else {
-            finishInputEvent(q);
+            if (q.mEvent instanceof KeyEvent) {
+                Trace.traceBegin(Trace.TRACE_TAG_VIEW, "preDispatchToUnhandledKeyManager");
+                try {
+                    mUnhandledKeyManager.preDispatch((KeyEvent) q.mEvent);
+                } finally {
+                    Trace.traceEnd(Trace.TRACE_TAG_VIEW);
+                }
+            }
+
+            if (stage != null) {
+                handleWindowFocusChanged();
+                stage.deliver(q);
+            } else {
+                finishInputEvent(q);
+            }
+        } finally {
+            Trace.traceEnd(Trace.TRACE_TAG_VIEW);
         }
     }
 
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 86cec5e..c571737 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -202,6 +202,14 @@
     public static final int FLAG_USE_LIGHT_BACKGROUND_LAYOUT = 4;
 
     /**
+     * Used to restrict the views which can be inflated
+     *
+     * @see android.view.LayoutInflater.Filter#onLoadClass(java.lang.Class)
+     */
+    private static final LayoutInflater.Filter INFLATER_FILTER =
+            (clazz) -> clazz.isAnnotationPresent(RemoteViews.RemoteView.class);
+
+    /**
      * Application that hosts the remote views.
      *
      * @hide
@@ -3413,13 +3421,24 @@
         // Clone inflater so we load resources from correct context and
         // we don't add a filter to the static version returned by getSystemService.
         inflater = inflater.cloneInContext(inflationContext);
-        inflater.setFilter(this);
+        inflater.setFilter(shouldUseStaticFilter() ? INFLATER_FILTER : this);
         View v = inflater.inflate(rv.getLayoutId(), parent, false);
         v.setTagInternal(R.id.widget_frame, rv.getLayoutId());
         return v;
     }
 
     /**
+     * A static filter is much lighter than RemoteViews itself. It's optimized here only for
+     * RemoteVies class. Subclasses should always override this and return true if not overriding
+     * {@link this#onLoadClass(Class)}.
+     *
+     * @hide
+     */
+    protected boolean shouldUseStaticFilter() {
+        return this.getClass().equals(RemoteViews.class);
+    }
+
+    /**
      * Implement this interface to receive a callback when
      * {@link #applyAsync} or {@link #reapplyAsync} is finished.
      * @hide
@@ -3686,11 +3705,15 @@
         return (mActions == null) ? 0 : mActions.size();
     }
 
-    /* (non-Javadoc)
+    /**
      * Used to restrict the views which can be inflated
      *
      * @see android.view.LayoutInflater.Filter#onLoadClass(java.lang.Class)
+     * @deprecated Used by system to enforce safe inflation of {@link RemoteViews}. Apps should not
+     * override this method. Changing of this method will NOT affect the process where RemoteViews
+     * is rendered.
      */
+    @Deprecated
     public boolean onLoadClass(Class clazz) {
         return clazz.isAnnotationPresent(RemoteView.class);
     }
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index f5bfe5c..75a5804 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -4086,7 +4086,7 @@
 
         if (workSource != null) {
             for (int i = 0; i < workSource.size(); ++i) {
-                uid = mapUid(workSource.get(i));
+                uid = mapUid(workSource.getUid(i));
                 if (mActiveEvents.updateState(historyItem, name, uid, 0)) {
                     addHistoryEventLocked(elapsedRealtime, uptime, historyItem, name, uid);
                 }
@@ -4114,8 +4114,8 @@
             String tag) {
         if (workSource != null) {
             for (int i = 0; i < workSource.size(); ++i) {
-                uid = workSource.get(i);
-                final String workSourceName = workSource.getName(i);
+                uid = workSource.getUid(i);
+                final String workSourceName = workSource.getPackageName(i);
 
                 if (isOnBattery()) {
                     BatteryStatsImpl.Uid.Pkg pkg = getPackageStatsLocked(uid,
@@ -4124,7 +4124,7 @@
                 }
             }
 
-            ArrayList<WorkChain> workChains = workSource.getWorkChains();
+            List<WorkChain> workChains = workSource.getWorkChains();
             if (workChains != null) {
                 for (int i = 0; i < workChains.size(); ++i) {
                     final WorkChain wc = workChains.get(i);
@@ -4350,7 +4350,7 @@
         final long uptime = mClocks.uptimeMillis();
         final int N = ws.size();
         for (int i=0; i<N; i++) {
-            noteStartWakeLocked(ws.get(i), pid, null, name, historyName, type,
+            noteStartWakeLocked(ws.getUid(i), pid, null, name, historyName, type,
                     unimportantForLogging, elapsedRealtime, uptime);
         }
 
@@ -4379,7 +4379,7 @@
         // First the starts :
         final int NN = newWs.size();
         for (int i=0; i<NN; i++) {
-            noteStartWakeLocked(newWs.get(i), newPid, null, newName, newHistoryName, newType,
+            noteStartWakeLocked(newWs.getUid(i), newPid, null, newName, newHistoryName, newType,
                     newUnimportantForLogging, elapsedRealtime, uptime);
         }
         if (wcs != null) {
@@ -4397,7 +4397,7 @@
         // Then the stops :
         final int NO = ws.size();
         for (int i=0; i<NO; i++) {
-            noteStopWakeLocked(ws.get(i), pid, null, name, historyName, type, elapsedRealtime,
+            noteStopWakeLocked(ws.getUid(i), pid, null, name, historyName, type, elapsedRealtime,
                     uptime);
         }
         if (wcs != null) {
@@ -4418,7 +4418,7 @@
         final long uptime = mClocks.uptimeMillis();
         final int N = ws.size();
         for (int i=0; i<N; i++) {
-            noteStopWakeLocked(ws.get(i), pid, null, name, historyName, type, elapsedRealtime,
+            noteStopWakeLocked(ws.getUid(i), pid, null, name, historyName, type, elapsedRealtime,
                     uptime);
         }
 
@@ -4441,11 +4441,11 @@
             WorkSource workSource) {
         final int N = workSource.size();
         for (int i = 0; i < N; ++i) {
-            final int uid = mapUid(workSource.get(i));
+            final int uid = mapUid(workSource.getUid(i));
             noteLongPartialWakeLockStartInternal(name, historyName, uid);
         }
 
-        final ArrayList<WorkChain> workChains = workSource.getWorkChains();
+        final List<WorkChain> workChains = workSource.getWorkChains();
         if (workChains != null) {
             for (int i = 0; i < workChains.size(); ++i) {
                 final WorkChain workChain = workChains.get(i);
@@ -4478,11 +4478,11 @@
             WorkSource workSource) {
         final int N = workSource.size();
         for (int i = 0; i < N; ++i) {
-            final int uid = mapUid(workSource.get(i));
+            final int uid = mapUid(workSource.getUid(i));
             noteLongPartialWakeLockFinishInternal(name, historyName, uid);
         }
 
-        final ArrayList<WorkChain> workChains = workSource.getWorkChains();
+        final List<WorkChain> workChains = workSource.getWorkChains();
         if (workChains != null) {
             for (int i = 0; i < workChains.size(); ++i) {
                 final WorkChain workChain = workChains.get(i);
@@ -4615,11 +4615,11 @@
 
     public void noteGpsChangedLocked(WorkSource oldWs, WorkSource newWs) {
         for (int i = 0; i < newWs.size(); ++i) {
-            noteStartGpsLocked(newWs.get(i), null);
+            noteStartGpsLocked(newWs.getUid(i), null);
         }
 
         for (int i = 0; i < oldWs.size(); ++i) {
-            noteStopGpsLocked((oldWs.get(i)), null);
+            noteStopGpsLocked((oldWs.getUid(i)), null);
         }
 
         List<WorkChain>[] wcs = WorkSource.diffChains(oldWs, newWs);
@@ -5564,7 +5564,7 @@
     public void noteBluetoothScanStartedFromSourceLocked(WorkSource ws, boolean isUnoptimized) {
         final int N = ws.size();
         for (int i = 0; i < N; i++) {
-            noteBluetoothScanStartedLocked(null, ws.get(i), isUnoptimized);
+            noteBluetoothScanStartedLocked(null, ws.getUid(i), isUnoptimized);
         }
 
         final List<WorkChain> workChains = ws.getWorkChains();
@@ -5602,7 +5602,7 @@
     public void noteBluetoothScanStoppedFromSourceLocked(WorkSource ws, boolean isUnoptimized) {
         final int N = ws.size();
         for (int i = 0; i < N; i++) {
-            noteBluetoothScanStoppedLocked(null, ws.get(i), isUnoptimized);
+            noteBluetoothScanStoppedLocked(null, ws.getUid(i), isUnoptimized);
         }
 
         final List<WorkChain> workChains = ws.getWorkChains();
@@ -5633,7 +5633,7 @@
     public void noteBluetoothScanResultsFromSourceLocked(WorkSource ws, int numNewResults) {
         final int N = ws.size();
         for (int i = 0; i < N; i++) {
-            int uid = mapUid(ws.get(i));
+            int uid = mapUid(ws.getUid(i));
             getUidStatsLocked(uid).noteBluetoothScanResultsLocked(numNewResults);
         }
 
@@ -5692,7 +5692,7 @@
             mGlobalWifiRunningTimer.startRunningLocked(elapsedRealtime);
             int N = ws.size();
             for (int i=0; i<N; i++) {
-                int uid = mapUid(ws.get(i));
+                int uid = mapUid(ws.getUid(i));
                 getUidStatsLocked(uid).noteWifiRunningLocked(elapsedRealtime);
             }
 
@@ -5715,7 +5715,7 @@
             final long elapsedRealtime = mClocks.elapsedRealtime();
             int N = oldWs.size();
             for (int i=0; i<N; i++) {
-                int uid = mapUid(oldWs.get(i));
+                int uid = mapUid(oldWs.getUid(i));
                 getUidStatsLocked(uid).noteWifiStoppedLocked(elapsedRealtime);
             }
 
@@ -5729,7 +5729,7 @@
 
             N = newWs.size();
             for (int i=0; i<N; i++) {
-                int uid = mapUid(newWs.get(i));
+                int uid = mapUid(newWs.getUid(i));
                 getUidStatsLocked(uid).noteWifiRunningLocked(elapsedRealtime);
             }
 
@@ -5757,7 +5757,7 @@
             mGlobalWifiRunningTimer.stopRunningLocked(elapsedRealtime);
             int N = ws.size();
             for (int i=0; i<N; i++) {
-                int uid = mapUid(ws.get(i));
+                int uid = mapUid(ws.getUid(i));
                 getUidStatsLocked(uid).noteWifiStoppedLocked(elapsedRealtime);
             }
 
@@ -5963,7 +5963,7 @@
     public void noteFullWifiLockAcquiredFromSourceLocked(WorkSource ws) {
         int N = ws.size();
         for (int i=0; i<N; i++) {
-            final int uid = mapUid(ws.get(i));
+            final int uid = mapUid(ws.getUid(i));
             noteFullWifiLockAcquiredLocked(uid);
         }
 
@@ -5980,7 +5980,7 @@
     public void noteFullWifiLockReleasedFromSourceLocked(WorkSource ws) {
         int N = ws.size();
         for (int i=0; i<N; i++) {
-            final int uid = mapUid(ws.get(i));
+            final int uid = mapUid(ws.getUid(i));
             noteFullWifiLockReleasedLocked(uid);
         }
 
@@ -5997,7 +5997,7 @@
     public void noteWifiScanStartedFromSourceLocked(WorkSource ws) {
         int N = ws.size();
         for (int i=0; i<N; i++) {
-            final int uid = mapUid(ws.get(i));
+            final int uid = mapUid(ws.getUid(i));
             noteWifiScanStartedLocked(uid);
         }
 
@@ -6014,7 +6014,7 @@
     public void noteWifiScanStoppedFromSourceLocked(WorkSource ws) {
         int N = ws.size();
         for (int i=0; i<N; i++) {
-            final int uid = mapUid(ws.get(i));
+            final int uid = mapUid(ws.getUid(i));
             noteWifiScanStoppedLocked(uid);
         }
 
@@ -6031,7 +6031,7 @@
     public void noteWifiBatchedScanStartedFromSourceLocked(WorkSource ws, int csph) {
         int N = ws.size();
         for (int i=0; i<N; i++) {
-            noteWifiBatchedScanStartedLocked(ws.get(i), csph);
+            noteWifiBatchedScanStartedLocked(ws.getUid(i), csph);
         }
 
         final List<WorkChain> workChains = ws.getWorkChains();
@@ -6045,7 +6045,7 @@
     public void noteWifiBatchedScanStoppedFromSourceLocked(WorkSource ws) {
         int N = ws.size();
         for (int i=0; i<N; i++) {
-            noteWifiBatchedScanStoppedLocked(ws.get(i));
+            noteWifiBatchedScanStoppedLocked(ws.getUid(i));
         }
 
         final List<WorkChain> workChains = ws.getWorkChains();
diff --git a/core/java/com/android/server/SystemConfig.java b/core/java/com/android/server/SystemConfig.java
index ed7f5de..49a73ee 100644
--- a/core/java/com/android/server/SystemConfig.java
+++ b/core/java/com/android/server/SystemConfig.java
@@ -18,6 +18,7 @@
 
 import static com.android.internal.util.ArrayUtils.appendInt;
 
+import android.annotation.NonNull;
 import android.app.ActivityManager;
 import android.content.ComponentName;
 import android.content.pm.FeatureInfo;
@@ -221,6 +222,12 @@
     private ArrayMap<String, Set<String>> mPackageToUserTypeWhitelist = new ArrayMap<>();
     private ArrayMap<String, Set<String>> mPackageToUserTypeBlacklist = new ArrayMap<>();
 
+    /**
+     * Map of system pre-defined, uniquely named actors; keys are namespace,
+     * value maps actor name to package name.
+     */
+    private ArrayMap<String, ArrayMap<String, String>> mNamedActors = null;
+
     public static SystemConfig getInstance() {
         if (!isSystemProcess()) {
             Slog.wtf(TAG, "SystemConfig is being accessed by a process other than "
@@ -398,12 +405,17 @@
         return r;
     }
 
+    @NonNull
+    public Map<String, ? extends Map<String, String>> getNamedActors() {
+        return mNamedActors != null ? mNamedActors : Collections.emptyMap();
+    }
+
     /**
      * Only use for testing. Do NOT use in production code.
      * @param readPermissions false to create an empty SystemConfig; true to read the permissions.
      */
     @VisibleForTesting
-    protected SystemConfig(boolean readPermissions) {
+    public SystemConfig(boolean readPermissions) {
         if (readPermissions) {
             Slog.w(TAG, "Constructing a test SystemConfig");
             readAllPermissions();
@@ -1028,6 +1040,44 @@
                         readInstallInUserType(parser,
                                 mPackageToUserTypeWhitelist, mPackageToUserTypeBlacklist);
                     } break;
+                    case "named-actor": {
+                        String namespace = TextUtils.safeIntern(
+                                parser.getAttributeValue(null, "namespace"));
+                        String actorName = parser.getAttributeValue(null, "name");
+                        String pkgName = TextUtils.safeIntern(
+                                parser.getAttributeValue(null, "package"));
+                        if (TextUtils.isEmpty(namespace)) {
+                            Slog.wtf(TAG, "<" + name + "> without namespace in " + permFile
+                                    + " at " + parser.getPositionDescription());
+                        } else if (TextUtils.isEmpty(actorName)) {
+                            Slog.wtf(TAG, "<" + name + "> without actor name in " + permFile
+                                    + " at " + parser.getPositionDescription());
+                        } else if (TextUtils.isEmpty(pkgName)) {
+                            Slog.wtf(TAG, "<" + name + "> without package name in " + permFile
+                                    + " at " + parser.getPositionDescription());
+                        } else if ("android".equalsIgnoreCase(namespace)) {
+                            throw new IllegalStateException("Defining " + actorName + " as "
+                                    + pkgName + " for the android namespace is not allowed");
+                        } else {
+                            if (mNamedActors == null) {
+                                mNamedActors = new ArrayMap<>();
+                            }
+
+                            ArrayMap<String, String> nameToPkgMap = mNamedActors.get(namespace);
+                            if (nameToPkgMap == null) {
+                                nameToPkgMap = new ArrayMap<>();
+                                mNamedActors.put(namespace, nameToPkgMap);
+                            } else if (nameToPkgMap.containsKey(actorName)) {
+                                String existing = nameToPkgMap.get(actorName);
+                                throw new IllegalStateException("Duplicate actor definition for "
+                                        + namespace + "/" + actorName
+                                        + "; defined as both " + existing + " and " + pkgName);
+                            }
+
+                            nameToPkgMap.put(actorName, pkgName);
+                        }
+                        XmlUtils.skipCurrentTag(parser);
+                    } break;
                     default: {
                         Slog.w(TAG, "Tag " + name + " is unknown in "
                                 + permFile + " at " + parser.getPositionDescription());
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index ea10949..51f8fcc 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -125,6 +125,7 @@
                 "android_text_Hyphenator.cpp",
                 "android_os_Debug.cpp",
                 "android_os_GraphicsEnvironment.cpp",
+                "android_os_HidlMemory.cpp",
                 "android_os_HidlSupport.cpp",
                 "android_os_HwBinder.cpp",
                 "android_os_HwBlob.cpp",
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 32d62fe..378e125 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -147,6 +147,7 @@
 extern int register_android_os_Trace(JNIEnv* env);
 extern int register_android_os_FileObserver(JNIEnv *env);
 extern int register_android_os_UEventObserver(JNIEnv* env);
+extern int register_android_os_HidlMemory(JNIEnv* env);
 extern int register_android_os_MemoryFile(JNIEnv* env);
 extern int register_android_os_SharedMemory(JNIEnv* env);
 extern int register_android_net_LocalSocketImpl(JNIEnv* env);
@@ -1432,6 +1433,7 @@
     REG_JNI(register_android_os_SystemProperties),
     REG_JNI(register_android_os_Binder),
     REG_JNI(register_android_os_Parcel),
+    REG_JNI(register_android_os_HidlMemory),
     REG_JNI(register_android_os_HidlSupport),
     REG_JNI(register_android_os_HwBinder),
     REG_JNI(register_android_os_HwBlob),
diff --git a/core/jni/android_content_res_ApkAssets.cpp b/core/jni/android_content_res_ApkAssets.cpp
index 6370253..f3a626e 100644
--- a/core/jni/android_content_res_ApkAssets.cpp
+++ b/core/jni/android_content_res_ApkAssets.cpp
@@ -194,6 +194,59 @@
   return reinterpret_cast<jlong>(xml_tree.release());
 }
 
+static jobject NativeGetOverlayableInfo(JNIEnv* env, jclass /*clazz*/, jlong ptr,
+                                         jstring overlayable_name) {
+  const ApkAssets* apk_assets = reinterpret_cast<const ApkAssets*>(ptr);
+
+  const auto& packages = apk_assets->GetLoadedArsc()->GetPackages();
+  if (packages.empty()) {
+    jniThrowException(env, "java/io/IOException", "Error reading overlayable from APK");
+    return 0;
+  }
+
+  // TODO(b/119899133): Convert this to a search for the info rather than assuming it's at index 0
+  const auto& overlayable_map = packages[0]->GetOverlayableMap();
+  if (overlayable_map.empty()) {
+    return nullptr;
+  }
+
+  auto overlayable_name_native = std::string(env->GetStringUTFChars(overlayable_name, NULL));
+  auto actor = overlayable_map.find(overlayable_name_native);
+  if (actor == overlayable_map.end()) {
+    return nullptr;
+  }
+
+  jstring actor_string = env->NewStringUTF(actor->first.c_str());
+  if (env->ExceptionCheck() || actor_string == nullptr) {
+    jniThrowException(env, "java/io/IOException", "Error reading overlayable from APK");
+    return 0;
+  }
+
+  jclass overlayable_class = env->FindClass("android/content/om/OverlayableInfo");
+  jmethodID overlayable_constructor = env->GetMethodID(overlayable_class, "<init>",
+                                                       "(Ljava/lang/String;Ljava/lang/String;I)V");
+  return env->NewObject(
+      overlayable_class,
+      overlayable_constructor,
+      overlayable_name,
+      actor_string
+  );
+}
+
+static jboolean NativeDefinesOverlayable(JNIEnv* env, jclass /*clazz*/, jlong ptr) {
+  const ApkAssets* apk_assets = reinterpret_cast<const ApkAssets*>(ptr);
+
+  const auto& packages = apk_assets->GetLoadedArsc()->GetPackages();
+  if (packages.empty()) {
+    // Must throw to prevent bypass by returning false
+    jniThrowException(env, "java/io/IOException", "Error reading overlayable from APK");
+    return 0;
+  }
+
+  const auto& overlayable_infos = packages[0]->GetOverlayableMap();
+  return overlayable_infos.empty() ? JNI_FALSE : JNI_TRUE;
+}
+
 // JNI registration.
 static const JNINativeMethod gApkAssetsMethods[] = {
     {"nativeLoad", "(Ljava/lang/String;ZZZZ)J", (void*)NativeLoad},
@@ -208,6 +261,9 @@
     {"nativeGetStringBlock", "(J)J", (void*)NativeGetStringBlock},
     {"nativeIsUpToDate", "(J)Z", (void*)NativeIsUpToDate},
     {"nativeOpenXml", "(JLjava/lang/String;)J", (void*)NativeOpenXml},
+    {"nativeGetOverlayableInfo", "(JLjava/lang/String;)Landroid/content/om/OverlayableInfo;",
+     (void*)NativeGetOverlayableInfo},
+    {"nativeDefinesOverlayable", "(J)Z", (void*)NativeDefinesOverlayable},
 };
 
 int register_android_content_res_ApkAssets(JNIEnv* env) {
diff --git a/core/jni/android_os_HidlMemory.cpp b/core/jni/android_os_HidlMemory.cpp
new file mode 100644
index 0000000..69e4818
--- /dev/null
+++ b/core/jni/android_os_HidlMemory.cpp
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "android_os_HidlMemory.h"
+#include "core_jni_helpers.h"
+#include "android_os_NativeHandle.h"
+
+#define PACKAGE_PATH    "android/os"
+#define CLASS_NAME      "HidlMemory"
+#define CLASS_PATH      PACKAGE_PATH "/" CLASS_NAME
+
+namespace android {
+
+namespace {
+
+static struct {
+    jclass clazz;
+    jfieldID nativeContext;  // long
+    jmethodID constructor;   // HidlMemory(String, long, NativeHandle)
+    jmethodID getName;       // String HidlMemory.getName()
+    jmethodID getSize;       // int HidlMemory.getSize()
+    jmethodID getHandle;     // NativeHandle HidlMemory.getHandle()
+} gFields;
+
+std::string stringFromJava(JNIEnv* env, jstring jstr) {
+    ScopedUtfChars s(env, jstr);
+    return s.c_str();
+}
+
+jstring stringToJava(JNIEnv* env, const std::string& cstr) {
+    return env->NewStringUTF(cstr.c_str());
+}
+
+static void nativeFinalize(JNIEnv* env, jobject jobj) {
+    jlong jNativeContext = env->GetLongField(jobj, gFields.nativeContext);
+    JHidlMemory* native = reinterpret_cast<JHidlMemory*>(jNativeContext);
+    delete native;
+}
+
+static JNINativeMethod gMethods[] = {
+        {"nativeFinalize", "()V", (void*) nativeFinalize},
+};
+
+}  // namespace
+
+JHidlMemory::~JHidlMemory() {
+    if (mObj) {
+        // Must manually delete the underlying handle - hidl_memory doesn't own
+        // it.
+        native_handle_delete(const_cast<native_handle_t*>(mObj->handle()));
+    }
+}
+
+/* static */ const hardware::hidl_memory* JHidlMemory::fromJava(JNIEnv* env,
+                                                                jobject jobj) {
+    // Try to get the result from cache.
+    env->MonitorEnter(jobj);
+    JHidlMemory* obj = getNativeContext(env, jobj);
+    if (!obj->mObj) {
+        // Create and cache.
+        obj->mObj = javaToNative(env, jobj);
+    }
+    env->MonitorExit(jobj);
+    return obj->mObj.get();
+}
+
+/* static */ jobject JHidlMemory::toJava(JNIEnv* env,
+                                         const hardware::hidl_memory& cobj) {
+    if (cobj.size() > std::numeric_limits<jlong>::max()) {
+        return nullptr;
+    }
+    jstring jname = stringToJava(env, cobj.name());
+    jlong jsize = static_cast<jlong>(cobj.size());
+    jobject jhandle =
+            JNativeHandle::MakeJavaNativeHandleObj(env, cobj.handle());
+
+    // We're sharing the handle of cobj, so the Java instance doesn't own it.
+    return env->NewObject(gFields.clazz,
+                          gFields.constructor,
+                          jname,
+                          jsize,
+                          jhandle,
+                          false);
+}
+
+/* static */ std::unique_ptr<hardware::hidl_memory> JHidlMemory::javaToNative(
+        JNIEnv* env,
+        jobject jobj) {
+    jstring jname =
+            static_cast<jstring>(env->CallObjectMethod(jobj, gFields.getName));
+    jlong jsize = env->CallLongMethod(jobj, gFields.getSize);
+    jobject jhandle = env->CallObjectMethod(jobj, gFields.getHandle);
+
+    if (jsize > std::numeric_limits<size_t>::max()) {
+        return nullptr;
+    }
+
+    std::string cname = stringFromJava(env, jname);
+    size_t csize = jsize;
+    // We created the handle here, we're responsible to call
+    // native_handle_delete() on it. However, we don't assume ownership of the
+    // underlying fd, so we shouldn't call native_handle_close() on it.
+    native_handle_t* chandle = JNativeHandle::MakeCppNativeHandle(env, jhandle,
+                                                                  nullptr);
+    // hidl_memory doesn't take ownership of the handle here, so won't delete
+    // or close it.
+    return std::make_unique<hardware::hidl_memory>(cname, chandle, csize);
+}
+
+/* static */ JHidlMemory* JHidlMemory::getNativeContext(JNIEnv* env,
+                                                        jobject jobj) {
+    env->MonitorEnter(jobj);
+    jlong jNativeContext = env->GetLongField(jobj, gFields.nativeContext);
+    JHidlMemory* native = reinterpret_cast<JHidlMemory*>(jNativeContext);
+    if (!native) {
+        native = new JHidlMemory();
+        env->SetLongField(jobj,
+                          gFields.nativeContext,
+                          reinterpret_cast<jlong>(native));
+    }
+    env->MonitorExit(jobj);
+    return native;
+}
+
+int register_android_os_HidlMemory(JNIEnv* env) {
+    jclass clazz = FindClassOrDie(env, CLASS_PATH);
+    gFields.clazz = MakeGlobalRefOrDie(env, clazz);
+
+    gFields.nativeContext = GetFieldIDOrDie(env, clazz, "mNativeContext", "J");
+
+    gFields.constructor = GetMethodIDOrDie(env,
+                                           clazz,
+                                           "<init>",
+                                           "(Ljava/lang/String;JL" PACKAGE_PATH "/NativeHandle;)V");
+    gFields.getName =
+            GetMethodIDOrDie(env, clazz, "getName", "()Ljava/lang/String;");
+    gFields.getSize = GetMethodIDOrDie(env, clazz, "getSize", "()J");
+    gFields.getHandle = GetMethodIDOrDie(env,
+                                         clazz,
+                                         "getHandle",
+                                         "()L" PACKAGE_PATH "/NativeHandle;");
+
+    RegisterMethodsOrDie(env, CLASS_PATH, gMethods, NELEM(gMethods));
+
+    return 0;
+}
+
+}  // namespace android
+
diff --git a/core/jni/android_os_HidlMemory.h b/core/jni/android_os_HidlMemory.h
new file mode 100644
index 0000000..993a132
--- /dev/null
+++ b/core/jni/android_os_HidlMemory.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_OS_HIDL_MEMORY_H
+#define ANDROID_OS_HIDL_MEMORY_H
+
+#include <jni.h>
+#include <hidl/HidlSupport.h>
+
+namespace android {
+
+// A utility class for handling the android.os.HidlMemory class from JNI code.
+class JHidlMemory final {
+ public:
+    // Convert an android.os.HidlMemory object to its C++ counterpart,
+    // hardware::hidl_memory.
+    // No duplication of file descriptors is performed.
+    // The returned reference is owned by the underlying Java object.
+    // Returns nullptr if conversion cannot be done.
+    static const hardware::hidl_memory* fromJava(JNIEnv* env,
+                                                 jobject jobj);
+
+    // Convert a hardware::hidl_memory object to its Java counterpart,
+    // android.os.HidlMemory.
+    // No duplication of file descriptors is performed.
+    // Returns nullptr if conversion cannot be done.
+    static jobject toJava(JNIEnv* env,
+                          const hardware::hidl_memory& cobj);
+
+    ~JHidlMemory();
+
+ private:
+    // We store an instance of type JHidlMemory attached to every Java object
+    // of type HidlMemory, for holding any native context we need. This instance
+    // will get deleted when finalize() is called on the Java object.
+    // This method either extracts the native object from the Java object, or
+    // attached a new one if it doesn't yet exist.
+    static JHidlMemory* getNativeContext(JNIEnv* env, jobject obj);
+
+    // Convert an android.os.HidlMemory object to its C++ counterpart,
+    // hardware::hidl_memory.
+    // No duplication of file descriptors is performed.
+    // IMPORTANT: caller is responsible to native_handle_delete() the handle of the
+    // returned object. This is due to an underlying limitation of the hidl_handle
+    // type, where ownership of the handle implies ownership of the fd and we don't
+    // want the latter.
+    // Returns nullptr if conversion cannot be done.
+    static std::unique_ptr<hardware::hidl_memory> javaToNative(JNIEnv* env,
+                                                               jobject jobj);
+
+    std::unique_ptr<hardware::hidl_memory> mObj;
+};
+
+int register_android_os_HidlMemory(JNIEnv* env);
+
+}  // namespace android
+
+#endif //ANDROID_OS_HIDL_MEMORY_H
diff --git a/core/jni/android_os_HwBlob.cpp b/core/jni/android_os_HwBlob.cpp
index e5b72ca..0fb2911 100644
--- a/core/jni/android_os_HwBlob.cpp
+++ b/core/jni/android_os_HwBlob.cpp
@@ -340,6 +340,14 @@
     return env->NewStringUTF(s->c_str());
 }
 
+static jlong JHwBlob_native_getFieldHandle(JNIEnv* env,
+                                           jobject thiz,
+                                           jlong offset) {
+    sp<JHwBlob> blob = JHwBlob::GetNativeContext(env, thiz);
+
+    return reinterpret_cast<jlong>(blob->data()) + offset;
+}
+
 #define DEFINE_BLOB_ARRAY_COPIER(Suffix,Type,NewType)                          \
 static void JHwBlob_native_copyTo ## Suffix ## Array(                          \
         JNIEnv *env,                                                           \
@@ -593,6 +601,7 @@
     { "getFloat", "(J)F", (void *)JHwBlob_native_getFloat },
     { "getDouble", "(J)D", (void *)JHwBlob_native_getDouble },
     { "getString", "(J)Ljava/lang/String;", (void *)JHwBlob_native_getString },
+    { "getFieldHandle", "(J)J", (void*) JHwBlob_native_getFieldHandle},
 
     { "copyToBoolArray", "(J[ZI)V", (void *)JHwBlob_native_copyToBoolArray },
     { "copyToInt8Array", "(J[BI)V", (void *)JHwBlob_native_copyToInt8Array },
diff --git a/core/jni/android_os_HwParcel.cpp b/core/jni/android_os_HwParcel.cpp
index f437a78..151dbfc 100644
--- a/core/jni/android_os_HwParcel.cpp
+++ b/core/jni/android_os_HwParcel.cpp
@@ -20,6 +20,7 @@
 
 #include "android_os_HwParcel.h"
 
+#include "android_os_HidlMemory.h"
 #include "android_os_HwBinder.h"
 #include "android_os_HwBlob.h"
 #include "android_os_NativeHandle.h"
@@ -27,6 +28,8 @@
 
 #include <nativehelper/JNIHelp.h>
 #include <android_runtime/AndroidRuntime.h>
+#include <hidl/HidlBinderSupport.h>
+#include <hidl/HidlSupport.h>
 #include <hidl/HidlTransportSupport.h>
 #include <hidl/Status.h>
 #include <nativehelper/ScopedLocalRef.h>
@@ -650,6 +653,36 @@
     signalExceptionForError(env, err);
 }
 
+static void JHwParcel_native_writeHidlMemory(
+    JNIEnv *env, jobject thiz, jobject jmem) {
+
+    if (jmem == nullptr) {
+        jniThrowException(env, "java/lang/NullPointerException", nullptr);
+        return;
+    }
+
+    status_t err = OK;
+
+    // Convert the Java object to its C++ counterpart.
+    const hardware::hidl_memory* cmem = JHidlMemory::fromJava(env, jmem);
+    if (cmem == nullptr) {
+        err = BAD_VALUE;
+    }
+
+    if (err == OK) {
+        // Write it to the parcel.
+        hardware::Parcel* parcel =
+            JHwParcel::GetNativeContext(env, thiz)->getParcel();
+
+        size_t parentHandle;
+        err = parcel->writeBuffer(cmem, sizeof(*cmem), &parentHandle);
+        if (err == OK) {
+            err = hardware::writeEmbeddedToParcel(*cmem, parcel, parentHandle, 0);
+        }
+    }
+    signalExceptionForError(env, err);
+}
+
 static jstring MakeStringObjFromHidlString(JNIEnv *env, const hidl_string &s) {
     String16 utf16String(s.c_str(), s.size());
 
@@ -877,6 +910,74 @@
     return objArray;
 }
 
+static status_t readEmbeddedHidlMemory(JNIEnv* env,
+                                       hardware::Parcel* parcel,
+                                       const hardware::hidl_memory& mem,
+                                       size_t parentHandle,
+                                       size_t parentOffset,
+                                       jobject* result) {
+    status_t err = hardware::readEmbeddedFromParcel(mem,
+                                                    *parcel,
+                                                    parentHandle,
+                                                    parentOffset);
+    if (err == OK) {
+        // Convert to Java.
+        *result = JHidlMemory::toJava(env, mem);
+        if (*result == nullptr) {
+            err = BAD_VALUE;
+        }
+    }
+    return err;
+}
+
+static jobject JHwParcel_native_readHidlMemory(
+        JNIEnv* env, jobject thiz) {
+    hardware::Parcel* parcel =
+            JHwParcel::GetNativeContext(env, thiz)->getParcel();
+
+    jobject result = nullptr;
+
+    const hardware::hidl_memory* mem;
+    size_t parentHandle;
+
+    status_t err = parcel->readBuffer(sizeof(*mem),
+                                      &parentHandle,
+                                      reinterpret_cast<const void**>(&mem));
+    if (err == OK) {
+        err = readEmbeddedHidlMemory(env,
+                                     parcel,
+                                     *mem,
+                                     parentHandle,
+                                     0,
+                                     &result);
+    }
+
+    signalExceptionForError(env, err);
+    return result;
+}
+
+static jobject JHwParcel_native_readEmbeddedHidlMemory(
+        JNIEnv* env,
+        jobject thiz,
+        jlong fieldHandle,
+        jlong parentHandle,
+        jlong offset) {
+    hardware::Parcel* parcel =
+            JHwParcel::GetNativeContext(env, thiz)->getParcel();
+
+    jobject result = nullptr;
+    const hardware::hidl_memory* mem =
+            reinterpret_cast<const hardware::hidl_memory*>(fieldHandle);
+    status_t err = readEmbeddedHidlMemory(env,
+                                          parcel,
+                                          *mem,
+                                          parentHandle,
+                                          offset,
+                                          &result);
+    signalExceptionForError(env, err);
+    return result;
+}
+
 static jobject JHwParcel_native_readStrongBinder(JNIEnv *env, jobject thiz) {
     hardware::Parcel *parcel =
         JHwParcel::GetNativeContext(env, thiz)->getParcel();
@@ -1075,6 +1176,14 @@
     { "release", "()V",
         (void *)JHwParcel_native_release },
 
+    {"writeHidlMemory", "(L" PACKAGE_PATH "/HidlMemory;)V",
+     (void*) JHwParcel_native_writeHidlMemory},
+
+    {"readHidlMemory", "()L" PACKAGE_PATH "/HidlMemory;",
+     (void*) JHwParcel_native_readHidlMemory},
+
+    {"readEmbeddedHidlMemory", "(JJJ)L" PACKAGE_PATH "/HidlMemory;",
+     (void*) JHwParcel_native_readEmbeddedHidlMemory},
 };
 
 namespace android {
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index f8a2744..9f20388 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -491,6 +491,7 @@
     float* floatColors = env->GetFloatArrayElements(fColor, 0);
     half3 color(floatColors[0], floatColors[1], floatColors[2]);
     transaction->setColor(ctrl, color);
+    env->ReleaseFloatArrayElements(fColor, floatColors, 0);
 }
 
 static void nativeSetMatrix(JNIEnv* env, jclass clazz, jlong transactionObj,
@@ -508,8 +509,12 @@
     SurfaceControl* const surfaceControl = reinterpret_cast<SurfaceControl*>(nativeObject);
     float* floatMatrix = env->GetFloatArrayElements(fMatrix, 0);
     mat3 matrix(static_cast<float const*>(floatMatrix));
+    env->ReleaseFloatArrayElements(fMatrix, floatMatrix, 0);
+
     float* floatTranslation = env->GetFloatArrayElements(fTranslation, 0);
     vec3 translation(floatTranslation[0], floatTranslation[1], floatTranslation[2]);
+    env->ReleaseFloatArrayElements(fTranslation, floatTranslation, 0);
+
     transaction->setColorTransform(surfaceControl, matrix, translation);
 }
 
@@ -1262,6 +1267,22 @@
     return reinterpret_cast<jlong>(surface.get());
 }
 
+static void nativeSetGlobalShadowSettings(JNIEnv* env, jclass clazz, jfloatArray jAmbientColor,
+        jfloatArray jSpotColor, jfloat lightPosY, jfloat lightPosZ, jfloat lightRadius) {
+    sp<SurfaceComposerClient> client = SurfaceComposerClient::getDefault();
+
+    float* floatAmbientColor = env->GetFloatArrayElements(jAmbientColor, 0);
+    half4 ambientColor = half4(floatAmbientColor[0], floatAmbientColor[1], floatAmbientColor[2],
+            floatAmbientColor[3]);
+    env->ReleaseFloatArrayElements(jAmbientColor, floatAmbientColor, 0);
+
+    float* floatSpotColor = env->GetFloatArrayElements(jSpotColor, 0);
+    half4 spotColor = half4(floatSpotColor[0], floatSpotColor[1], floatSpotColor[2],
+            floatSpotColor[3]);
+    env->ReleaseFloatArrayElements(jSpotColor, floatSpotColor, 0);
+
+    client->setGlobalShadowSettings(ambientColor, spotColor, lightPosY, lightPosZ, lightRadius);
+}
 // ----------------------------------------------------------------------------
 
 static const JNINativeMethod sSurfaceControlMethods[] = {
@@ -1416,6 +1437,8 @@
             (void*)nativeWriteTransactionToParcel },
     {"nativeMirrorSurface", "(J)J",
             (void*)nativeMirrorSurface },
+    {"nativeSetGlobalShadowSettings", "([F[FFFF)V",
+            (void*)nativeSetGlobalShadowSettings },
 };
 
 int register_android_view_SurfaceControl(JNIEnv* env)
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 62001aa..c63d2aa 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -5045,6 +5045,10 @@
                  android:permission="android.permission.BIND_JOB_SERVICE" >
         </service>
 
+        <service android:name="com.android.server.usage.UsageStatsIdleService"
+                 android:permission="android.permission.BIND_JOB_SERVICE" >
+        </service>
+
         <service android:name="com.android.server.net.watchlist.ReportWatchlistJobService"
                  android:permission="android.permission.BIND_JOB_SERVICE" >
         </service>
diff --git a/core/tests/coretests/src/android/os/WorkSourceTest.java b/core/tests/coretests/src/android/os/WorkSourceTest.java
index e94d60c..4206fd2 100644
--- a/core/tests/coretests/src/android/os/WorkSourceTest.java
+++ b/core/tests/coretests/src/android/os/WorkSourceTest.java
@@ -228,13 +228,13 @@
         WorkSource ws = new WorkSource();
         ws.set(10);
         assertEquals(1, ws.size());
-        assertEquals(10, ws.get(0));
+        assertEquals(10, ws.getUid(0));
 
         WorkSource ws2 = new WorkSource();
         ws2.set(20, "foo");
         assertEquals(1, ws2.size());
-        assertEquals(20, ws2.get(0));
-        assertEquals("foo", ws2.getName(0));
+        assertEquals(20, ws2.getUid(0));
+        assertEquals("foo", ws2.getPackageName(0));
     }
 
     public void testDiffChains_noChanges() {
@@ -410,8 +410,8 @@
         assertTrue(ws2.remove(ws1));
 
         assertEquals(0, ws1.size());
-        assertEquals(50, ws1.get(0));
-        assertEquals("foo", ws1.getName(0));
+        assertEquals(50, ws1.getUid(0));
+        assertEquals("foo", ws1.getPackageName(0));
     }
 
     public void testTransferWorkChains() {
diff --git a/libs/androidfw/include/androidfw/LoadedArsc.h b/libs/androidfw/include/androidfw/LoadedArsc.h
index 6cbda07..b5d3a1f 100644
--- a/libs/androidfw/include/androidfw/LoadedArsc.h
+++ b/libs/androidfw/include/androidfw/LoadedArsc.h
@@ -273,6 +273,8 @@
   ByteBucketArray<uint32_t> resource_ids_;
   std::vector<DynamicPackageEntry> dynamic_package_map_;
   std::vector<const std::pair<OverlayableInfo, std::unordered_set<uint32_t>>> overlayable_infos_;
+
+  // A map of overlayable name to actor
   std::unordered_map<std::string, std::string> overlayable_map_;
 };
 
diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java
index a3a8777..d64e4ef 100644
--- a/media/java/android/media/AudioSystem.java
+++ b/media/java/android/media/AudioSystem.java
@@ -30,7 +30,9 @@
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
+import java.util.HashSet;
 import java.util.Map;
+import java.util.Set;
 
 /* IF YOU CHANGE ANY OF THE CONSTANTS IN THIS FILE, DO NOT FORGET
  * TO UPDATE THE CORRESPONDING NATIVE GLUE AND AudioManager.java.
@@ -543,51 +545,75 @@
 
     public static final int DEVICE_OUT_DEFAULT = DEVICE_BIT_DEFAULT;
 
-    public static final int DEVICE_OUT_ALL = (DEVICE_OUT_EARPIECE |
-                                              DEVICE_OUT_SPEAKER |
-                                              DEVICE_OUT_WIRED_HEADSET |
-                                              DEVICE_OUT_WIRED_HEADPHONE |
-                                              DEVICE_OUT_BLUETOOTH_SCO |
-                                              DEVICE_OUT_BLUETOOTH_SCO_HEADSET |
-                                              DEVICE_OUT_BLUETOOTH_SCO_CARKIT |
-                                              DEVICE_OUT_BLUETOOTH_A2DP |
-                                              DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES |
-                                              DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER |
-                                              DEVICE_OUT_HDMI |
-                                              DEVICE_OUT_ANLG_DOCK_HEADSET |
-                                              DEVICE_OUT_DGTL_DOCK_HEADSET |
-                                              DEVICE_OUT_USB_ACCESSORY |
-                                              DEVICE_OUT_USB_DEVICE |
-                                              DEVICE_OUT_REMOTE_SUBMIX |
-                                              DEVICE_OUT_TELEPHONY_TX |
-                                              DEVICE_OUT_LINE |
-                                              DEVICE_OUT_HDMI_ARC |
-                                              DEVICE_OUT_SPDIF |
-                                              DEVICE_OUT_FM |
-                                              DEVICE_OUT_AUX_LINE |
-                                              DEVICE_OUT_SPEAKER_SAFE |
-                                              DEVICE_OUT_IP |
-                                              DEVICE_OUT_BUS |
-                                              DEVICE_OUT_PROXY |
-                                              DEVICE_OUT_USB_HEADSET |
-                                              DEVICE_OUT_HEARING_AID |
-                                              DEVICE_OUT_DEFAULT);
-    public static final int DEVICE_OUT_ALL_A2DP = (DEVICE_OUT_BLUETOOTH_A2DP |
-                                                   DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES |
-                                                   DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER);
-    public static final int DEVICE_OUT_ALL_SCO = (DEVICE_OUT_BLUETOOTH_SCO |
-                                                  DEVICE_OUT_BLUETOOTH_SCO_HEADSET |
-                                                  DEVICE_OUT_BLUETOOTH_SCO_CARKIT);
+    // Deprecated in R because multiple device types are no longer accessed as a bit mask.
+    // Removing this will get lint warning about changing hidden apis.
     @UnsupportedAppUsage
     public static final int DEVICE_OUT_ALL_USB = (DEVICE_OUT_USB_ACCESSORY |
                                                   DEVICE_OUT_USB_DEVICE |
                                                   DEVICE_OUT_USB_HEADSET);
-    public static final int DEVICE_OUT_ALL_HDMI_SYSTEM_AUDIO = (DEVICE_OUT_AUX_LINE |
-                                                                DEVICE_OUT_HDMI_ARC |
-                                                                DEVICE_OUT_SPDIF);
-    public static final int DEVICE_ALL_HDMI_SYSTEM_AUDIO_AND_SPEAKER =
-            (DEVICE_OUT_ALL_HDMI_SYSTEM_AUDIO |
-             DEVICE_OUT_SPEAKER);
+
+    public static final Set<Integer> DEVICE_OUT_ALL_SET;
+    public static final Set<Integer> DEVICE_OUT_ALL_A2DP_SET;
+    public static final Set<Integer> DEVICE_OUT_ALL_SCO_SET;
+    public static final Set<Integer> DEVICE_OUT_ALL_USB_SET;
+    public static final Set<Integer> DEVICE_OUT_ALL_HDMI_SYSTEM_AUDIO_SET;
+    public static final Set<Integer> DEVICE_ALL_HDMI_SYSTEM_AUDIO_AND_SPEAKER_SET;
+    static {
+        DEVICE_OUT_ALL_SET = new HashSet<>();
+        DEVICE_OUT_ALL_SET.add(DEVICE_OUT_EARPIECE);
+        DEVICE_OUT_ALL_SET.add(DEVICE_OUT_SPEAKER);
+        DEVICE_OUT_ALL_SET.add(DEVICE_OUT_WIRED_HEADSET);
+        DEVICE_OUT_ALL_SET.add(DEVICE_OUT_WIRED_HEADPHONE);
+        DEVICE_OUT_ALL_SET.add(DEVICE_OUT_BLUETOOTH_SCO);
+        DEVICE_OUT_ALL_SET.add(DEVICE_OUT_BLUETOOTH_SCO_HEADSET);
+        DEVICE_OUT_ALL_SET.add(DEVICE_OUT_BLUETOOTH_SCO_CARKIT);
+        DEVICE_OUT_ALL_SET.add(DEVICE_OUT_BLUETOOTH_A2DP);
+        DEVICE_OUT_ALL_SET.add(DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES);
+        DEVICE_OUT_ALL_SET.add(DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER);
+        DEVICE_OUT_ALL_SET.add(DEVICE_OUT_HDMI);
+        DEVICE_OUT_ALL_SET.add(DEVICE_OUT_ANLG_DOCK_HEADSET);
+        DEVICE_OUT_ALL_SET.add(DEVICE_OUT_DGTL_DOCK_HEADSET);
+        DEVICE_OUT_ALL_SET.add(DEVICE_OUT_USB_ACCESSORY);
+        DEVICE_OUT_ALL_SET.add(DEVICE_OUT_USB_DEVICE);
+        DEVICE_OUT_ALL_SET.add(DEVICE_OUT_REMOTE_SUBMIX);
+        DEVICE_OUT_ALL_SET.add(DEVICE_OUT_TELEPHONY_TX);
+        DEVICE_OUT_ALL_SET.add(DEVICE_OUT_LINE);
+        DEVICE_OUT_ALL_SET.add(DEVICE_OUT_HDMI_ARC);
+        DEVICE_OUT_ALL_SET.add(DEVICE_OUT_SPDIF);
+        DEVICE_OUT_ALL_SET.add(DEVICE_OUT_FM);
+        DEVICE_OUT_ALL_SET.add(DEVICE_OUT_AUX_LINE);
+        DEVICE_OUT_ALL_SET.add(DEVICE_OUT_SPEAKER_SAFE);
+        DEVICE_OUT_ALL_SET.add(DEVICE_OUT_IP);
+        DEVICE_OUT_ALL_SET.add(DEVICE_OUT_BUS);
+        DEVICE_OUT_ALL_SET.add(DEVICE_OUT_PROXY);
+        DEVICE_OUT_ALL_SET.add(DEVICE_OUT_USB_HEADSET);
+        DEVICE_OUT_ALL_SET.add(DEVICE_OUT_HEARING_AID);
+        DEVICE_OUT_ALL_SET.add(DEVICE_OUT_DEFAULT);
+
+        DEVICE_OUT_ALL_A2DP_SET = new HashSet<>();
+        DEVICE_OUT_ALL_A2DP_SET.add(DEVICE_OUT_BLUETOOTH_A2DP);
+        DEVICE_OUT_ALL_A2DP_SET.add(DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES);
+        DEVICE_OUT_ALL_A2DP_SET.add(DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER);
+
+        DEVICE_OUT_ALL_SCO_SET = new HashSet<>();
+        DEVICE_OUT_ALL_SCO_SET.add(DEVICE_OUT_BLUETOOTH_SCO);
+        DEVICE_OUT_ALL_SCO_SET.add(DEVICE_OUT_BLUETOOTH_SCO_HEADSET);
+        DEVICE_OUT_ALL_SCO_SET.add(DEVICE_OUT_BLUETOOTH_SCO_CARKIT);
+
+        DEVICE_OUT_ALL_USB_SET = new HashSet<>();
+        DEVICE_OUT_ALL_USB_SET.add(DEVICE_OUT_USB_ACCESSORY);
+        DEVICE_OUT_ALL_USB_SET.add(DEVICE_OUT_USB_DEVICE);
+        DEVICE_OUT_ALL_USB_SET.add(DEVICE_OUT_USB_HEADSET);
+
+        DEVICE_OUT_ALL_HDMI_SYSTEM_AUDIO_SET = new HashSet<>();
+        DEVICE_OUT_ALL_HDMI_SYSTEM_AUDIO_SET.add(DEVICE_OUT_AUX_LINE);
+        DEVICE_OUT_ALL_HDMI_SYSTEM_AUDIO_SET.add(DEVICE_OUT_HDMI_ARC);
+        DEVICE_OUT_ALL_HDMI_SYSTEM_AUDIO_SET.add(DEVICE_OUT_SPDIF);
+
+        DEVICE_ALL_HDMI_SYSTEM_AUDIO_AND_SPEAKER_SET = new HashSet<>();
+        DEVICE_ALL_HDMI_SYSTEM_AUDIO_AND_SPEAKER_SET.addAll(DEVICE_OUT_ALL_HDMI_SYSTEM_AUDIO_SET);
+        DEVICE_ALL_HDMI_SYSTEM_AUDIO_AND_SPEAKER_SET.add(DEVICE_OUT_SPEAKER);
+    }
 
     // input devices
     @UnsupportedAppUsage
@@ -635,37 +661,47 @@
     @UnsupportedAppUsage
     public static final int DEVICE_IN_DEFAULT = DEVICE_BIT_IN | DEVICE_BIT_DEFAULT;
 
-    public static final int DEVICE_IN_ALL = (DEVICE_IN_COMMUNICATION |
-                                             DEVICE_IN_AMBIENT |
-                                             DEVICE_IN_BUILTIN_MIC |
-                                             DEVICE_IN_BLUETOOTH_SCO_HEADSET |
-                                             DEVICE_IN_WIRED_HEADSET |
-                                             DEVICE_IN_HDMI |
-                                             DEVICE_IN_TELEPHONY_RX |
-                                             DEVICE_IN_BACK_MIC |
-                                             DEVICE_IN_REMOTE_SUBMIX |
-                                             DEVICE_IN_ANLG_DOCK_HEADSET |
-                                             DEVICE_IN_DGTL_DOCK_HEADSET |
-                                             DEVICE_IN_USB_ACCESSORY |
-                                             DEVICE_IN_USB_DEVICE |
-                                             DEVICE_IN_FM_TUNER |
-                                             DEVICE_IN_TV_TUNER |
-                                             DEVICE_IN_LINE |
-                                             DEVICE_IN_SPDIF |
-                                             DEVICE_IN_BLUETOOTH_A2DP |
-                                             DEVICE_IN_LOOPBACK |
-                                             DEVICE_IN_IP |
-                                             DEVICE_IN_BUS |
-                                             DEVICE_IN_PROXY |
-                                             DEVICE_IN_USB_HEADSET |
-                                             DEVICE_IN_BLUETOOTH_BLE |
-                                             DEVICE_IN_HDMI_ARC |
-                                             DEVICE_IN_ECHO_REFERENCE |
-                                             DEVICE_IN_DEFAULT);
-    public static final int DEVICE_IN_ALL_SCO = DEVICE_IN_BLUETOOTH_SCO_HEADSET;
-    public static final int DEVICE_IN_ALL_USB = (DEVICE_IN_USB_ACCESSORY |
-                                                 DEVICE_IN_USB_DEVICE |
-                                                 DEVICE_IN_USB_HEADSET);
+    public static final Set<Integer> DEVICE_IN_ALL_SET;
+    public static final Set<Integer> DEVICE_IN_ALL_SCO_SET;
+    public static final Set<Integer> DEVICE_IN_ALL_USB_SET;
+    static {
+        DEVICE_IN_ALL_SET = new HashSet<>();
+        DEVICE_IN_ALL_SET.add(DEVICE_IN_COMMUNICATION);
+        DEVICE_IN_ALL_SET.add(DEVICE_IN_AMBIENT);
+        DEVICE_IN_ALL_SET.add(DEVICE_IN_BUILTIN_MIC);
+        DEVICE_IN_ALL_SET.add(DEVICE_IN_BLUETOOTH_SCO_HEADSET);
+        DEVICE_IN_ALL_SET.add(DEVICE_IN_WIRED_HEADSET);
+        DEVICE_IN_ALL_SET.add(DEVICE_IN_HDMI);
+        DEVICE_IN_ALL_SET.add(DEVICE_IN_TELEPHONY_RX);
+        DEVICE_IN_ALL_SET.add(DEVICE_IN_BACK_MIC);
+        DEVICE_IN_ALL_SET.add(DEVICE_IN_REMOTE_SUBMIX);
+        DEVICE_IN_ALL_SET.add(DEVICE_IN_ANLG_DOCK_HEADSET);
+        DEVICE_IN_ALL_SET.add(DEVICE_IN_DGTL_DOCK_HEADSET);
+        DEVICE_IN_ALL_SET.add(DEVICE_IN_USB_ACCESSORY);
+        DEVICE_IN_ALL_SET.add(DEVICE_IN_USB_DEVICE);
+        DEVICE_IN_ALL_SET.add(DEVICE_IN_FM_TUNER);
+        DEVICE_IN_ALL_SET.add(DEVICE_IN_TV_TUNER);
+        DEVICE_IN_ALL_SET.add(DEVICE_IN_LINE);
+        DEVICE_IN_ALL_SET.add(DEVICE_IN_SPDIF);
+        DEVICE_IN_ALL_SET.add(DEVICE_IN_BLUETOOTH_A2DP);
+        DEVICE_IN_ALL_SET.add(DEVICE_IN_LOOPBACK);
+        DEVICE_IN_ALL_SET.add(DEVICE_IN_IP);
+        DEVICE_IN_ALL_SET.add(DEVICE_IN_BUS);
+        DEVICE_IN_ALL_SET.add(DEVICE_IN_PROXY);
+        DEVICE_IN_ALL_SET.add(DEVICE_IN_USB_HEADSET);
+        DEVICE_IN_ALL_SET.add(DEVICE_IN_BLUETOOTH_BLE);
+        DEVICE_IN_ALL_SET.add(DEVICE_IN_HDMI_ARC);
+        DEVICE_IN_ALL_SET.add(DEVICE_IN_ECHO_REFERENCE);
+        DEVICE_IN_ALL_SET.add(DEVICE_IN_DEFAULT);
+
+        DEVICE_IN_ALL_SCO_SET = new HashSet<>();
+        DEVICE_IN_ALL_SCO_SET.add(DEVICE_IN_BLUETOOTH_SCO_HEADSET);
+
+        DEVICE_IN_ALL_USB_SET = new HashSet<>();
+        DEVICE_IN_ALL_USB_SET.add(DEVICE_IN_USB_ACCESSORY);
+        DEVICE_IN_ALL_USB_SET.add(DEVICE_IN_USB_DEVICE);
+        DEVICE_IN_ALL_USB_SET.add(DEVICE_IN_USB_HEADSET);
+    }
 
     // device states, must match AudioSystem::device_connection_state
     @UnsupportedAppUsage
@@ -1229,6 +1265,40 @@
         return getPlatformType(context) == PLATFORM_TELEVISION || forceSingleVolume;
     }
 
+    /**
+     * Return a set of audio device types from a bit mask audio device type, which may
+     * represent multiple audio device types.
+     * FIXME: Remove this when getting ride of bit mask usage of audio device types.
+     */
+    public static Set<Integer> generateAudioDeviceTypesSet(int types) {
+        Set<Integer> deviceTypes = new HashSet<>();
+        Set<Integer> allDeviceTypes =
+                (types & DEVICE_BIT_IN) == 0 ? DEVICE_OUT_ALL_SET : DEVICE_IN_ALL_SET;
+        for (int deviceType : allDeviceTypes) {
+            if ((types & deviceType) == deviceType) {
+                deviceTypes.add(deviceType);
+            }
+        }
+        return deviceTypes;
+    }
+
+    /**
+     * Return the intersection of two audio device types collections.
+     */
+    public static Set<Integer> intersectionAudioDeviceTypes(
+            @NonNull Set<Integer> a, @NonNull Set<Integer> b) {
+        Set<Integer> intersection = new HashSet<>(a);
+        intersection.retainAll(b);
+        return intersection;
+    }
+
+    /**
+     * Return true if the audio device types collection only contains the given device type.
+     */
+    public static boolean isSingleAudioDeviceType(@NonNull Set<Integer> types, int type) {
+        return types.size() == 1 && types.contains(type);
+    }
+
     public static final int DEFAULT_MUTE_STREAMS_AFFECTED =
             (1 << STREAM_MUSIC) |
             (1 << STREAM_RING) |
diff --git a/media/java/android/media/IMediaRouterService.aidl b/media/java/android/media/IMediaRouterService.aidl
index ced8615..81a7ee2 100644
--- a/media/java/android/media/IMediaRouterService.aidl
+++ b/media/java/android/media/IMediaRouterService.aidl
@@ -43,6 +43,7 @@
     void setControlCategories(IMediaRouterClient client, in List<String> categories);
 
     // Methods for media router 2
+    List<MediaRoute2Info> getSystemRoutes();
     void registerClient2(IMediaRouter2Client client, String packageName);
     void unregisterClient2(IMediaRouter2Client client);
     void sendControlRequest(IMediaRouter2Client client, in MediaRoute2Info route, in Intent request);
diff --git a/media/java/android/media/MediaRouter2.java b/media/java/android/media/MediaRouter2.java
index 74d26f0..94ac77a 100644
--- a/media/java/android/media/MediaRouter2.java
+++ b/media/java/android/media/MediaRouter2.java
@@ -131,6 +131,25 @@
         mPackageName = mContext.getPackageName();
         //TODO: read control categories from the manifest
         mHandler = new Handler(Looper.getMainLooper());
+
+        List<MediaRoute2Info> currentSystemRoutes = null;
+        try {
+            currentSystemRoutes = mMediaRouterService.getSystemRoutes();
+        } catch (RemoteException ex) {
+            Log.e(TAG, "Unable to get current currentSystemRoutes", ex);
+        }
+
+        if (currentSystemRoutes == null || currentSystemRoutes.isEmpty()) {
+            throw new RuntimeException("Null or empty currentSystemRoutes. Something is wrong.");
+        }
+
+        for (MediaRoute2Info route : currentSystemRoutes) {
+            mRoutes.put(route.getId(), route);
+        }
+        // The first route is the currently selected system route.
+        // For example, if there are two system routes (BT and device speaker),
+        // BT will be the first route in the list.
+        mSelectedRoute = currentSystemRoutes.get(0);
     }
 
     /**
@@ -409,6 +428,10 @@
     }
 
     void addRoutesOnHandler(List<MediaRoute2Info> routes) {
+        // TODO: When onRoutesAdded is first called,
+        //  1) clear mRoutes before adding the routes
+        //  2) Call onRouteSelected(system_route, reason_fallback) if previously selected route
+        //     does not exist anymore. => We may need 'boolean MediaRoute2Info#isSystemRoute()'.
         List<MediaRoute2Info> addedRoutes = new ArrayList<>();
         for (MediaRoute2Info route : routes) {
             mRoutes.put(route.getUniqueId(), route);
diff --git a/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouter2Test.java b/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouter2Test.java
new file mode 100644
index 0000000..2c60d6b
--- /dev/null
+++ b/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouter2Test.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.mediaroutertest;
+
+import static org.junit.Assert.assertNotNull;
+
+import android.content.Context;
+import android.media.MediaRoute2Info;
+import android.media.MediaRouter2;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class MediaRouter2Test {
+    Context mContext;
+
+    @Before
+    public void setUp() throws Exception {
+        mContext = InstrumentationRegistry.getTargetContext();
+    }
+
+    @After
+    public void tearDown() throws Exception {
+    }
+
+    @Test
+    public void testGetSelectedRoute_afterCreation() throws Exception {
+        MediaRouter2 router = MediaRouter2.getInstance(mContext);
+        MediaRoute2Info initiallySelectedRoute = router.getSelectedRoute();
+        assertNotNull(initiallySelectedRoute);
+    }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
index d619300..d577b5a 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
@@ -748,7 +748,20 @@
                 || (mConfig != null && mConfig.shared != config.shared)) {
             return false;
         }
-        return security == getSecurity(config);
+
+        final int configSecurity = getSecurity(config);
+        final WifiManager wifiManager = getWifiManager();
+        switch (security) {
+            case SECURITY_PSK_SAE_TRANSITION:
+                return configSecurity == SECURITY_PSK
+                        || (wifiManager.isWpa3SaeSupported() && configSecurity == SECURITY_SAE);
+            case SECURITY_OWE_TRANSITION:
+                return configSecurity == SECURITY_NONE
+                        || (wifiManager.isEnhancedOpenSupported()
+                                && configSecurity == SECURITY_OWE);
+            default:
+                return security == configSecurity;
+        }
     }
 
     public WifiConfiguration getConfig() {
@@ -1321,10 +1334,34 @@
         mAccessPointListener = listener;
     }
 
+    private static final String sPskSuffix = "," + String.valueOf(SECURITY_PSK);
+    private static final String sSaeSuffix = "," + String.valueOf(SECURITY_SAE);
+    private static final String sPskSaeSuffix = "," + String.valueOf(SECURITY_PSK_SAE_TRANSITION);
+    private static final String sOweSuffix = "," + String.valueOf(SECURITY_OWE);
+    private static final String sOpenSuffix = "," + String.valueOf(SECURITY_NONE);
+    private static final String sOweTransSuffix = "," + String.valueOf(SECURITY_OWE_TRANSITION);
+
     private boolean isKeyEqual(String compareTo) {
         if (mKey == null) {
             return false;
         }
+
+        if (compareTo.endsWith(sPskSuffix) || compareTo.endsWith(sSaeSuffix)) {
+            if (mKey.endsWith(sPskSaeSuffix)) {
+                // Special handling for PSK-SAE transition mode. If the AP has advertised both,
+                // we compare the key with both PSK and SAE for a match.
+                return TextUtils.equals(mKey.substring(0, mKey.lastIndexOf(',')),
+                        compareTo.substring(0, compareTo.lastIndexOf(',')));
+            }
+        }
+        if (compareTo.endsWith(sOpenSuffix) || compareTo.endsWith(sOweSuffix)) {
+            if (mKey.endsWith(sOweTransSuffix)) {
+                // Special handling for OWE/Open networks. If AP advertises OWE in transition mode
+                // and we have an Open network saved, allow this connection to be established.
+                return TextUtils.equals(mKey.substring(0, mKey.lastIndexOf(',')),
+                        compareTo.substring(0, compareTo.lastIndexOf(',')));
+            }
+        }
         return mKey.equals(compareTo);
     }
 
@@ -1661,6 +1698,8 @@
     private static int getSecurity(ScanResult result) {
         if (result.capabilities.contains("WEP")) {
             return SECURITY_WEP;
+        } else if (result.capabilities.contains("PSK+SAE")) {
+            return SECURITY_PSK_SAE_TRANSITION;
         } else if (result.capabilities.contains("SAE")) {
             return SECURITY_SAE;
         } else if (result.capabilities.contains("PSK")) {
@@ -1669,6 +1708,8 @@
             return SECURITY_EAP_SUITE_B;
         } else if (result.capabilities.contains("EAP")) {
             return SECURITY_EAP;
+        } else if (result.capabilities.contains("OWE_TRANSITION")) {
+            return SECURITY_OWE_TRANSITION;
         } else if (result.capabilities.contains("OWE")) {
             return SECURITY_OWE;
         }
@@ -1715,6 +1756,10 @@
             return "SUITE_B";
         } else if (security == SECURITY_OWE) {
             return "OWE";
+        } else if (security == SECURITY_PSK_SAE_TRANSITION) {
+            return "PSK+SAE";
+        } else if (security == SECURITY_OWE_TRANSITION) {
+            return "OWE_TRANSITION";
         }
         return "NONE";
     }
@@ -1892,16 +1937,4 @@
             }
         }
     }
-
-    /**
-     * Lets the caller know if the network was cloned from another network
-     *
-     * @return true if the network is cloned
-     */
-    public boolean isCloned() {
-        if (mConfig == null) {
-            return false;
-        }
-        return mConfig.clonedNetworkConfigKey != null;
-    }
 }
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
index 51e37d1..8591116 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
@@ -142,7 +142,7 @@
 
     private void updateRssi(int newRssi) {
         rssi = newRssi;
-        level = WifiManager.calculateSignalLevel(rssi, WifiManager.RSSI_LEVELS);
+        level = mWifiManager.calculateSignalLevel(rssi);
     }
 
     private void maybeRequestNetworkScore() {
diff --git a/packages/SettingsProvider/Android.bp b/packages/SettingsProvider/Android.bp
index 681b494..f40d3a1 100644
--- a/packages/SettingsProvider/Android.bp
+++ b/packages/SettingsProvider/Android.bp
@@ -29,6 +29,7 @@
         "src/com/android/providers/settings/SettingsBackupAgent.java",
         "src/com/android/providers/settings/SettingsState.java",
         "src/com/android/providers/settings/SettingsHelper.java",
+        "src/com/android/providers/settings/WifiSoftApBandChangedNotifier.java",
     ],
     static_libs: [
         "androidx.test.rules",
diff --git a/packages/SettingsProvider/res/drawable/ic_wifi_settings.xml b/packages/SettingsProvider/res/drawable/ic_wifi_settings.xml
new file mode 100644
index 0000000..cb42656
--- /dev/null
+++ b/packages/SettingsProvider/res/drawable/ic_wifi_settings.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2019 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+
+    <path
+        android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" />
+    <path
+        android:fillColor="#000000"
+        android:pathData="M12.584,15.93c0.026-0.194,0.044-0.397,0.044-0.608c0-0.211-0.018-0.405-0.044-0.608l1.304-1.022
+c0.115-0.088,0.15-0.256,0.071-0.397l-1.234-2.133c-0.071-0.132-0.238-0.185-0.379-0.132l-1.533,0.617
+c-0.317-0.247-0.67-0.449-1.04-0.608L9.535,9.4c-0.018-0.132-0.141-0.247-0.3-0.247H6.768c-0.15,0-0.282,0.115-0.3,0.256
+L6.23,11.048c-0.379,0.159-0.723,0.361-1.04,0.608l-1.533-0.617c-0.141-0.053-0.3,0-0.379,0.132l-1.234,2.133
+c-0.079,0.132-0.044,0.3,0.07,0.397l1.304,1.022c-0.026,0.194-0.044,0.405-0.044,0.608s0.018,0.405,0.044,0.608l-1.304,1.022
+c-0.115,0.088-0.15,0.256-0.07,0.397l1.234,2.133c0.07,0.132,0.238,0.185,0.379,0.132l1.533-0.617
+c0.317,0.247,0.67,0.449,1.04,0.608l0.238,1.639c0.018,0.15,0.15,0.256,0.3,0.256h2.467c0.159,0,0.282-0.115,0.3-0.256
+l0.238-1.639c0.379-0.15,0.723-0.361,1.04-0.608l1.533,0.617c0.141,0.053,0.3,0,0.379-0.132l1.234-2.133
+c0.071-0.132,0.044-0.3-0.07-0.397L12.584,15.93z
+M8.002,17.481c-1.19,0-2.159-0.969-2.159-2.159s0.969-2.159,2.159-2.159
+s2.159,0.969,2.159,2.159C10.161,16.512,9.191,17.481,8.002,17.481z" />
+    <path
+        android:fillColor="#000000"
+        android:pathData="M16.003,12.026l5.995-7.474c-0.229-0.172-2.537-2.06-6-2.06s-5.771,1.889-6,2.06l5.995,7.469l0.005,0.01L16.003,12.026z" />
+</vector>
diff --git a/packages/SettingsProvider/res/values/strings.xml b/packages/SettingsProvider/res/values/strings.xml
index 9ca575e..3787727 100644
--- a/packages/SettingsProvider/res/values/strings.xml
+++ b/packages/SettingsProvider/res/values/strings.xml
@@ -19,4 +19,19 @@
 <resources>
     <!-- Name of the activity for Settings storage. -->
     <string name="app_label">Settings Storage</string>
+
+    <!-- A notification is shown when the user's softap config has been changed due to underlying
+     hardware restrictions. This is the notifications's title.
+     [CHAR_LIMIT=NONE] -->
+    <string name="wifi_softap_config_change">Changes to your hotspot settings</string>
+
+    <!-- A notification is shown when the user's softap config has been changed due to underlying
+         hardware restrictions. This is the notification's summary message.
+         [CHAR_LIMIT=NONE] -->
+    <string name="wifi_softap_config_change_summary">Your hotspot band has changed.</string>
+
+    <!-- A notification is shown when the user's softap config has been changed due to underlying
+         hardware restrictions. This is the notification's full message.
+         [CHAR_LIMIT=NONE] -->
+    <string name="wifi_softap_config_change_detailed">This device doesn\u2019t support your preference for 5GHz only. Instead, this device will use the 5GHz band when available.</string>
 </resources>
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
index 7e60452..443288c 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
@@ -895,11 +895,9 @@
             // the apBand preference
             boolean dualMode = mWifiManager.isDualModeSupported();
             int storedApBand = mWifiManager.getWifiApConfiguration().apBand;
-            if (dualMode) {
-                if (storedApBand != originalApBand) {
-                    Log.d(TAG, "restored ap configuration requires a conversion, notify the user");
-                    mWifiManager.notifyUserOfApBandConversion();
-                }
+            if (dualMode && storedApBand != originalApBand) {
+                Log.d(TAG, "restored ap configuration requires a conversion, notify the user");
+                WifiSoftApBandChangedNotifier.notifyUserOfApBandConversion(this);
             }
         } catch (IOException | BackupUtils.BadVersionException e) {
             Log.e(TAG, "Failed to unMarshal SoftAPConfiguration " + e.getMessage());
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/WifiSoftApBandChangedNotifier.java b/packages/SettingsProvider/src/com/android/providers/settings/WifiSoftApBandChangedNotifier.java
new file mode 100644
index 0000000..d0d4956
--- /dev/null
+++ b/packages/SettingsProvider/src/com/android/providers/settings/WifiSoftApBandChangedNotifier.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.providers.settings;
+
+import android.app.Notification;
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.Resources;
+
+import com.android.internal.messages.nano.SystemMessageProto;
+import com.android.internal.notification.SystemNotificationChannels;
+
+/**
+ * Helper class for sending notifications when the user's Soft AP Band was changed upon restore.
+ */
+public class WifiSoftApBandChangedNotifier {
+    private WifiSoftApBandChangedNotifier() {}
+
+    /**
+     * Send a notification informing the user that their' Soft AP Band was changed upon restore.
+     * When the user taps on the notification, they are taken to the Wifi Tethering page in
+     * Settings.
+     */
+    public static void notifyUserOfApBandConversion(Context context) {
+        NotificationManager notificationManager =
+                context.getSystemService(NotificationManager.class);
+
+        // create channel, or update it if it already exists
+        NotificationChannel channel = new NotificationChannel(
+                SystemNotificationChannels.NETWORK_STATUS,
+                context.getString(android.R.string.notification_channel_network_status),
+                NotificationManager.IMPORTANCE_LOW);
+        notificationManager.createNotificationChannel(channel);
+
+        notificationManager.notify(
+                SystemMessageProto.SystemMessage.NOTE_SOFTAP_CONFIG_CHANGED,
+                createConversionNotification(context));
+    }
+
+    private static Notification createConversionNotification(Context context) {
+        Resources resources = context.getResources();
+        CharSequence title = resources.getText(R.string.wifi_softap_config_change);
+        CharSequence contentSummary = resources.getText(R.string.wifi_softap_config_change_summary);
+        CharSequence content = resources.getText(R.string.wifi_softap_config_change_detailed);
+        int color = resources.getColor(
+                android.R.color.system_notification_accent_color, context.getTheme());
+
+        return new Notification.Builder(context, SystemNotificationChannels.NETWORK_STATUS)
+                .setSmallIcon(R.drawable.ic_wifi_settings)
+                .setPriority(Notification.PRIORITY_HIGH)
+                .setCategory(Notification.CATEGORY_SYSTEM)
+                .setContentTitle(title)
+                .setContentText(contentSummary)
+                .setContentIntent(getPendingActivity(context))
+                .setTicker(title)
+                .setShowWhen(false)
+                .setLocalOnly(true)
+                .setColor(color)
+                .setStyle(new Notification.BigTextStyle()
+                        .bigText(content)
+                        .setBigContentTitle(title)
+                        .setSummaryText(contentSummary))
+                .setAutoCancel(true)
+                .build();
+    }
+
+    private static PendingIntent getPendingActivity(Context context) {
+        Intent intent = new Intent("com.android.settings.WIFI_TETHER_SETTINGS")
+                .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        return PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
+    }
+}
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index c3f410e..86ef031 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -125,7 +125,7 @@
 
     <!-- The tiles to display in QuickSettings in retail mode -->
     <string name="quick_settings_tiles_retail_mode" translatable="false">
-        cell,battery,dnd,flashlight,rotation,location
+        night,dark,dnd,flashlight,rotation,location
     </string>
 
     <!-- Whether or not the RSSI tile is capitalized or not. -->
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
index 4d86613..61a7cc7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
@@ -139,6 +139,14 @@
         when(mMockCm.getDefaultNetworkCapabilitiesForUser(0)).thenReturn(
                 new NetworkCapabilities[] { mNetCapabilities });
         when(mMockTm.createForSubscriptionId(anyInt())).thenReturn(mMockTm);
+        doAnswer(invocation -> {
+            int rssi = invocation.getArgument(0);
+            if (rssi < -88) return 0;
+            if (rssi < -77) return 1;
+            if (rssi < -66) return 2;
+            if (rssi < -55) return 3;
+            return 4;
+        }).when(mMockWm).calculateSignalLevel(anyInt());
 
         mSignalStrength = mock(SignalStrength.class);
         mServiceState = mock(ServiceState.class);
diff --git a/services/Android.bp b/services/Android.bp
index 6953e86..35dc44e 100644
--- a/services/Android.bp
+++ b/services/Android.bp
@@ -1,3 +1,38 @@
+filegroup {
+    name: "services-main-sources",
+    srcs: ["java/**/*.java"],
+    path: "java",
+    visibility: ["//visibility:private"],
+}
+
+filegroup {
+    name: "services-sources",
+    srcs: [
+        ":services.core-sources",
+        ":services.accessibility-sources",
+        ":services.appprediction-sources",
+        ":services.appwidget-sources",
+        ":services.autofill-sources",
+        ":services.backup-sources",
+        ":services.companion-sources",
+        ":services.contentcapture-sources",
+        ":services.contentsuggestions-sources",
+        ":services.coverage-sources",
+        ":services.devicepolicy-sources",
+        ":services.midi-sources",
+        ":services.net-sources",
+        ":services.print-sources",
+        ":services.restrictions-sources",
+        ":services.startop.iorap-sources",
+        ":services.systemcaptions-sources",
+        ":services.usage-sources",
+        ":services.usb-sources",
+        ":services.voiceinteraction-sources",
+        ":services.wifi-sources",
+    ],
+    visibility: ["//visibility:private"],
+}
+
 // merge all required services into one jar
 // ============================================================
 java_library {
@@ -9,9 +44,7 @@
         profile: "art-profile",
     },
 
-    srcs: [
-        "java/**/*.java",
-    ],
+    srcs: [":services-main-sources"],
 
     // The convention is to name each service module 'services.$(module_name)'
     static_libs: [
diff --git a/services/accessibility/Android.bp b/services/accessibility/Android.bp
index f991d7b..284a2f2 100644
--- a/services/accessibility/Android.bp
+++ b/services/accessibility/Android.bp
@@ -1,5 +1,12 @@
+filegroup {
+    name: "services.accessibility-sources",
+    srcs: ["java/**/*.java"],
+    path: "java",
+    visibility: ["//frameworks/base/services"],
+}
+
 java_library_static {
     name: "services.accessibility",
-    srcs: ["java/**/*.java"],
+    srcs: [":services.accessibility-sources"],
     libs: ["services.core"],
 }
diff --git a/services/appprediction/Android.bp b/services/appprediction/Android.bp
index a7be587..e14e1df 100644
--- a/services/appprediction/Android.bp
+++ b/services/appprediction/Android.bp
@@ -1,5 +1,12 @@
+filegroup {
+    name: "services.appprediction-sources",
+    srcs: ["java/**/*.java"],
+    path: "java",
+    visibility: ["//frameworks/base/services"],
+}
+
 java_library_static {
     name: "services.appprediction",
-    srcs: ["java/**/*.java"],
+    srcs: [":services.appprediction-sources"],
     libs: ["services.core"],
 }
diff --git a/services/appwidget/Android.bp b/services/appwidget/Android.bp
index aad2ad19..54cf6ce 100644
--- a/services/appwidget/Android.bp
+++ b/services/appwidget/Android.bp
@@ -1,5 +1,12 @@
+filegroup {
+    name: "services.appwidget-sources",
+    srcs: ["java/**/*.java"],
+    path: "java",
+    visibility: ["//frameworks/base/services"],
+}
+
 java_library_static {
     name: "services.appwidget",
-    srcs: ["java/**/*.java"],
+    srcs: [":services.appwidget-sources"],
     libs: ["services.core"],
 }
diff --git a/services/autofill/Android.bp b/services/autofill/Android.bp
index 2768c18..539eb1a 100644
--- a/services/autofill/Android.bp
+++ b/services/autofill/Android.bp
@@ -1,5 +1,12 @@
+filegroup {
+    name: "services.autofill-sources",
+    srcs: ["java/**/*.java"],
+    path: "java",
+    visibility: ["//frameworks/base/services"],
+}
+
 java_library_static {
     name: "services.autofill",
-    srcs: ["java/**/*.java"],
+    srcs: [":services.autofill-sources"],
     libs: ["services.core"],
 }
diff --git a/services/backup/Android.bp b/services/backup/Android.bp
index a3b0c89..f02da20 100644
--- a/services/backup/Android.bp
+++ b/services/backup/Android.bp
@@ -1,6 +1,13 @@
+filegroup {
+    name: "services.backup-sources",
+    srcs: ["java/**/*.java"],
+    path: "java",
+    visibility: ["//frameworks/base/services"],
+}
+
 java_library_static {
     name: "services.backup",
-    srcs: ["java/**/*.java"],
+    srcs: [":services.backup-sources"],
     libs: ["services.core"],
     static_libs: ["backuplib"],
 }
diff --git a/services/backup/backuplib/Android.bp b/services/backup/backuplib/Android.bp
index 7b194a092..00f51c9 100644
--- a/services/backup/backuplib/Android.bp
+++ b/services/backup/backuplib/Android.bp
@@ -1,5 +1,12 @@
+filegroup {
+    name: "backuplib-sources",
+    srcs: ["java/**/*.java"],
+    path: "java",
+    visibility: ["//frameworks/base/services"],
+}
+
 java_library {
     name: "backuplib",
-    srcs: ["java/**/*.java"],
+    srcs: [":backuplib-sources"],
     libs: ["services.core"],
 }
diff --git a/services/companion/Android.bp b/services/companion/Android.bp
index d2dac35..9677a7d 100644
--- a/services/companion/Android.bp
+++ b/services/companion/Android.bp
@@ -1,5 +1,12 @@
+filegroup {
+    name: "services.companion-sources",
+    srcs: ["java/**/*.java"],
+    path: "java",
+    visibility: ["//frameworks/base/services"],
+}
+
 java_library_static {
     name: "services.companion",
-    srcs: ["java/**/*.java"],
+    srcs: [":services.companion-sources"],
     libs: ["services.core"],
 }
diff --git a/services/contentcapture/Android.bp b/services/contentcapture/Android.bp
index 57e859e..96e2072 100644
--- a/services/contentcapture/Android.bp
+++ b/services/contentcapture/Android.bp
@@ -1,5 +1,12 @@
+filegroup {
+    name: "services.contentcapture-sources",
+    srcs: ["java/**/*.java"],
+    path: "java",
+    visibility: ["//frameworks/base/services"],
+}
+
 java_library_static {
     name: "services.contentcapture",
-    srcs: ["java/**/*.java"],
+    srcs: [":services.contentcapture-sources"],
     libs: ["services.core"],
 }
diff --git a/services/contentsuggestions/Android.bp b/services/contentsuggestions/Android.bp
index fc09d2e..d17f06f 100644
--- a/services/contentsuggestions/Android.bp
+++ b/services/contentsuggestions/Android.bp
@@ -1,5 +1,12 @@
+filegroup {
+    name: "services.contentsuggestions-sources",
+    srcs: ["java/**/*.java"],
+    path: "java",
+    visibility: ["//frameworks/base/services"],
+}
+
 java_library_static {
     name: "services.contentsuggestions",
-    srcs: ["java/**/*.java"],
+    srcs: [":services.contentsuggestions-sources"],
     libs: ["services.core"],
-}
\ No newline at end of file
+}
diff --git a/services/core/Android.bp b/services/core/Android.bp
index b8caefd..594ac10 100644
--- a/services/core/Android.bp
+++ b/services/core/Android.bp
@@ -1,3 +1,10 @@
+filegroup {
+    name: "services.core-sources",
+    srcs: ["java/**/*.java"],
+    path: "java",
+    visibility: ["//frameworks/base/services"],
+}
+
 java_library {
     name: "protolog-common",
     srcs: [
@@ -16,7 +23,10 @@
 
 genrule {
     name: "services.core.protologsrc",
-    srcs: [":services.core.wm.protologgroups", "java/**/*.java"],
+    srcs: [
+        ":services.core.wm.protologgroups",
+        ":services.core-sources",
+    ],
     tools: ["protologtool"],
     cmd: "$(location protologtool) transform-protolog-calls " +
       "--protolog-class com.android.server.protolog.common.ProtoLog " +
@@ -25,20 +35,23 @@
       "--loggroups-class com.android.server.wm.ProtoLogGroup " +
       "--loggroups-jar $(location :services.core.wm.protologgroups) " +
       "--output-srcjar $(out) " +
-      "$(locations java/**/*.java)",
+      "$(locations :services.core-sources)",
     out: ["services.core.protolog.srcjar"],
 }
 
 genrule {
     name: "generate-protolog.json",
-    srcs: [":services.core.wm.protologgroups", "java/**/*.java"],
+    srcs: [
+        ":services.core.wm.protologgroups",
+        ":services.core-sources",
+    ],
     tools: ["protologtool"],
     cmd: "$(location protologtool) generate-viewer-config " +
       "--protolog-class com.android.server.protolog.common.ProtoLog " +
       "--loggroups-class com.android.server.wm.ProtoLogGroup " +
       "--loggroups-jar $(location :services.core.wm.protologgroups) " +
       "--viewer-conf $(out) " +
-      "$(locations java/**/*.java)",
+      "$(locations :services.core-sources)",
     out: ["services.core.protolog.json"],
 }
 
@@ -60,25 +73,15 @@
 
 java_library_static {
     name: "services.core.unboosted",
-
-    aidl: {
-        include_dirs: [
-            "frameworks/base/cmds/idmap2/idmap2d/aidl",
-            "frameworks/native/aidl/binder",
-            "frameworks/native/cmds/dumpstate/binder",
-            "system/core/storaged/binder",
-            "system/vold/binder",
-            "system/gsid/aidl",
-        ],
-    },
     srcs: [
         ":services.core.protologsrc",
         ":dumpstate_aidl",
+        ":framework_native_aidl",
+        ":gsiservice_aidl",
         ":idmap2_aidl",
         ":installd_aidl",
         ":storaged_aidl",
         ":vold_aidl",
-        ":gsiservice_aidl",
         ":platform-compat-config",
         ":tethering-servicescore-srcs",
         "java/com/android/server/EventLogTags.logtags",
diff --git a/services/core/java/android/app/usage/UsageStatsManagerInternal.java b/services/core/java/android/app/usage/UsageStatsManagerInternal.java
index 6641b5b..2f8c506 100644
--- a/services/core/java/android/app/usage/UsageStatsManagerInternal.java
+++ b/services/core/java/android/app/usage/UsageStatsManagerInternal.java
@@ -281,4 +281,13 @@
             return mUsageRemaining;
         }
     }
+
+    /**
+     * Called by {@link com.android.server.usage.UsageStatsIdleService} when the device is idle to
+     * prune usage stats data for uninstalled packages.
+     *
+     * @param userId the user associated with the job
+     * @return {@code true} if the pruning was successful, {@code false} otherwise
+     */
+    public abstract boolean pruneUninstalledPackagesData(@UserIdInt int userId);
 }
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index e1f6597..9ebe896 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -1947,11 +1947,11 @@
         if (workSource.size() > 0) {
             // If the WorkSource has one or more non-chained UIDs, make sure they're accompanied
             // by tags.
-            return workSource.getName(0) != null;
+            return workSource.getPackageName(0) != null;
         } else {
             // For now, make sure callers have supplied an attribution tag for use with
             // AppOpsManager. This might be relaxed in the future.
-            final ArrayList<WorkChain> workChains = workSource.getWorkChains();
+            final List<WorkChain> workChains = workSource.getWorkChains();
             return workChains != null && !workChains.isEmpty() &&
                     workChains.get(0).getAttributionTag() != null;
         }
@@ -3309,18 +3309,24 @@
                 ipw.decreaseIndent();
             }
 
-            mSettingsStore.dump(fd, pw, args);
+            ipw.println("Location Settings:");
+            ipw.increaseIndent();
+            mSettingsStore.dump(fd, ipw, args);
+            ipw.decreaseIndent();
 
             ipw.println("Location Providers:");
             ipw.increaseIndent();
             for (LocationProvider provider : mProviders) {
                 provider.dumpLocked(fd, ipw, args);
             }
+            ipw.decreaseIndent();
         }
 
         if (mGnssManagerService != null) {
+            ipw.println("GNSS:");
+            ipw.increaseIndent();
+            mGnssManagerService.dump(fd, ipw, args);
             ipw.decreaseIndent();
-            mGnssManagerService.dump(fd, pw, args);
         }
     }
 }
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 3dc745b..88d0e4b 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -8649,7 +8649,7 @@
 
         mBatteryStatsService.noteWakupAlarm(sourcePkg, sourceUid, workSource, tag);
         if (workSource != null) {
-            String workSourcePackage = workSource.getName(0);
+            String workSourcePackage = workSource.getPackageName(0);
             int workSourceUid = workSource.getAttributionUid();
             if (workSourcePackage == null) {
                 workSourcePackage = sourcePkg;
diff --git a/services/core/java/com/android/server/audio/AudioDeviceInventory.java b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
index 90973a8..a2b3574 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceInventory.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
@@ -44,6 +44,8 @@
 import com.android.internal.annotations.VisibleForTesting;
 
 import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Set;
 
 /**
  * Class to manage the inventory of all connected devices.
@@ -372,9 +374,14 @@
         mDeviceBroker.postObserveDevicesForAllStreams();
     }
 
-    private static final int DEVICE_OVERRIDE_A2DP_ROUTE_ON_PLUG =
-            AudioSystem.DEVICE_OUT_WIRED_HEADSET | AudioSystem.DEVICE_OUT_WIRED_HEADPHONE
-                    | AudioSystem.DEVICE_OUT_LINE | AudioSystem.DEVICE_OUT_ALL_USB;
+    private static final Set<Integer> DEVICE_OVERRIDE_A2DP_ROUTE_ON_PLUG_SET;
+    static {
+        DEVICE_OVERRIDE_A2DP_ROUTE_ON_PLUG_SET = new HashSet<>();
+        DEVICE_OVERRIDE_A2DP_ROUTE_ON_PLUG_SET.add(AudioSystem.DEVICE_OUT_WIRED_HEADSET);
+        DEVICE_OVERRIDE_A2DP_ROUTE_ON_PLUG_SET.add(AudioSystem.DEVICE_OUT_WIRED_HEADPHONE);
+        DEVICE_OVERRIDE_A2DP_ROUTE_ON_PLUG_SET.add(AudioSystem.DEVICE_OUT_LINE);
+        DEVICE_OVERRIDE_A2DP_ROUTE_ON_PLUG_SET.addAll(AudioSystem.DEVICE_OUT_ALL_USB_SET);
+    }
 
     /*package*/ void onSetWiredDeviceConnectionState(
                             AudioDeviceInventory.WiredDeviceConnectionState wdcs) {
@@ -382,7 +389,7 @@
 
         synchronized (mConnectedDevices) {
             if ((wdcs.mState == AudioService.CONNECTION_STATE_DISCONNECTED)
-                    && ((wdcs.mType & DEVICE_OVERRIDE_A2DP_ROUTE_ON_PLUG) != 0)) {
+                    && DEVICE_OVERRIDE_A2DP_ROUTE_ON_PLUG_SET.contains(wdcs.mType)) {
                 mDeviceBroker.setBluetoothA2dpOnInt(true,
                         "onSetWiredDeviceConnectionState state DISCONNECTED");
             }
@@ -393,7 +400,7 @@
                 return;
             }
             if (wdcs.mState != AudioService.CONNECTION_STATE_DISCONNECTED) {
-                if ((wdcs.mType & DEVICE_OVERRIDE_A2DP_ROUTE_ON_PLUG) != 0) {
+                if (DEVICE_OVERRIDE_A2DP_ROUTE_ON_PLUG_SET.contains(wdcs.mType)) {
                     mDeviceBroker.setBluetoothA2dpOnInt(false,
                             "onSetWiredDeviceConnectionState state not DISCONNECTED");
                 }
@@ -764,13 +771,19 @@
     // - none of these devices are connected anymore after one is disconnected AND
     // - the device being disconnected is actually used for music.
     // Access synchronized on mConnectedDevices
-    private int mBecomingNoisyIntentDevices =
-            AudioSystem.DEVICE_OUT_WIRED_HEADSET | AudioSystem.DEVICE_OUT_WIRED_HEADPHONE
-                    | AudioSystem.DEVICE_OUT_ALL_A2DP | AudioSystem.DEVICE_OUT_HDMI
-                    | AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET
-                    | AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET
-                    | AudioSystem.DEVICE_OUT_ALL_USB | AudioSystem.DEVICE_OUT_LINE
-                    | AudioSystem.DEVICE_OUT_HEARING_AID;
+    private static final Set<Integer> BECOMING_NOISY_INTENT_DEVICES_SET;
+    static {
+        BECOMING_NOISY_INTENT_DEVICES_SET = new HashSet<>();
+        BECOMING_NOISY_INTENT_DEVICES_SET.add(AudioSystem.DEVICE_OUT_WIRED_HEADSET);
+        BECOMING_NOISY_INTENT_DEVICES_SET.add(AudioSystem.DEVICE_OUT_WIRED_HEADPHONE);
+        BECOMING_NOISY_INTENT_DEVICES_SET.add(AudioSystem.DEVICE_OUT_HDMI);
+        BECOMING_NOISY_INTENT_DEVICES_SET.add(AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET);
+        BECOMING_NOISY_INTENT_DEVICES_SET.add(AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET);
+        BECOMING_NOISY_INTENT_DEVICES_SET.add(AudioSystem.DEVICE_OUT_LINE);
+        BECOMING_NOISY_INTENT_DEVICES_SET.add(AudioSystem.DEVICE_OUT_HEARING_AID);
+        BECOMING_NOISY_INTENT_DEVICES_SET.addAll(AudioSystem.DEVICE_OUT_ALL_A2DP_SET);
+        BECOMING_NOISY_INTENT_DEVICES_SET.addAll(AudioSystem.DEVICE_OUT_ALL_USB_SET);
+    }
 
     // must be called before removing the device from mConnectedDevices
     // musicDevice argument is used when not AudioSystem.DEVICE_NONE instead of querying
@@ -781,16 +794,16 @@
         if (state != AudioService.CONNECTION_STATE_DISCONNECTED) {
             return 0;
         }
-        if ((device & mBecomingNoisyIntentDevices) == 0) {
+        if (!BECOMING_NOISY_INTENT_DEVICES_SET.contains(device)) {
             return 0;
         }
         int delay = 0;
-        int devices = 0;
+        Set<Integer> devices = new HashSet<>();
         for (int i = 0; i < mConnectedDevices.size(); i++) {
             int dev = mConnectedDevices.valueAt(i).mDeviceType;
             if (((dev & AudioSystem.DEVICE_BIT_IN) == 0)
-                    && ((dev & mBecomingNoisyIntentDevices) != 0)) {
-                devices |= dev;
+                    && BECOMING_NOISY_INTENT_DEVICES_SET.contains(dev)) {
+                devices.add(dev);
             }
         }
         if (musicDevice == AudioSystem.DEVICE_NONE) {
@@ -801,8 +814,9 @@
         // because music routing is altered in this case.
         // also checks whether media routing if affected by a dynamic policy or mirroring
         if (((device == musicDevice) || mDeviceBroker.isInCommunication())
-                && (device == devices) && !mDeviceBroker.hasMediaDynamicPolicy()
-                        && ((musicDevice & AudioSystem.DEVICE_OUT_REMOTE_SUBMIX) == 0)) {
+                && AudioSystem.isSingleAudioDeviceType(devices, device)
+                && !mDeviceBroker.hasMediaDynamicPolicy()
+                && (musicDevice != AudioSystem.DEVICE_OUT_REMOTE_SUBMIX)) {
             if (!AudioSystem.isStreamActive(AudioSystem.STREAM_MUSIC, 0 /*not looking in past*/)
                     && !mDeviceBroker.hasAudioFocusUsers()) {
                 // no media playback, not a "becoming noisy" situation, otherwise it could cause
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 9a92778..e426c6c 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -147,6 +147,7 @@
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -501,18 +502,20 @@
     private volatile IRingtonePlayer mRingtonePlayer;
 
     // Devices for which the volume is fixed (volume is either max or muted)
-    int mFixedVolumeDevices = AudioSystem.DEVICE_OUT_HDMI |
-            AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET |
-            AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET |
-            AudioSystem.DEVICE_OUT_HDMI_ARC |
-            AudioSystem.DEVICE_OUT_SPDIF |
-            AudioSystem.DEVICE_OUT_AUX_LINE;
+    Set<Integer> mFixedVolumeDevices = new HashSet<>(Arrays.asList(
+            AudioSystem.DEVICE_OUT_HDMI,
+            AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET,
+            AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET,
+            AudioSystem.DEVICE_OUT_HDMI_ARC,
+            AudioSystem.DEVICE_OUT_SPDIF,
+            AudioSystem.DEVICE_OUT_AUX_LINE));
     // Devices for which the volume is always max, no volume panel
-    int mFullVolumeDevices = 0;
+    Set<Integer> mFullVolumeDevices = new HashSet<>();
     // Devices for the which use the "absolute volume" concept (framework sends audio signal
     // full scale, and volume control separately) and can be used for multiple use cases reflected
     // by the audio mode (e.g. media playback in MODE_NORMAL, and phone calls in MODE_IN_CALL).
-    int mAbsVolumeMultiModeCaseDevices = AudioSystem.DEVICE_OUT_HEARING_AID;
+    Set<Integer> mAbsVolumeMultiModeCaseDevices = new HashSet<>(
+            Arrays.asList(AudioSystem.DEVICE_OUT_HEARING_AID));
 
     private final boolean mMonitorRotation;
 
@@ -866,13 +869,14 @@
                 }
                 mHdmiTvClient = mHdmiManager.getTvClient();
                 if (mHdmiTvClient != null) {
-                    mFixedVolumeDevices &= ~AudioSystem.DEVICE_ALL_HDMI_SYSTEM_AUDIO_AND_SPEAKER;
+                    mFixedVolumeDevices.removeAll(
+                            AudioSystem.DEVICE_ALL_HDMI_SYSTEM_AUDIO_AND_SPEAKER_SET);
                 }
                 mHdmiPlaybackClient = mHdmiManager.getPlaybackClient();
                 if (mHdmiPlaybackClient != null) {
                     // not a television: HDMI output will be always at max
-                    mFixedVolumeDevices &= ~AudioSystem.DEVICE_OUT_HDMI;
-                    mFullVolumeDevices |= AudioSystem.DEVICE_OUT_HDMI;
+                    mFixedVolumeDevices.remove(AudioSystem.DEVICE_OUT_HDMI);
+                    mFullVolumeDevices.add(AudioSystem.DEVICE_OUT_HDMI);
                 }
                 mHdmiAudioSystemClient = mHdmiManager.getAudioSystemClient();
             }
@@ -1131,7 +1135,7 @@
             @AudioService.ConnectionState int state, String caller) {
         if (state == AudioService.CONNECTION_STATE_CONNECTED) {
             // DEVICE_OUT_HDMI is now connected
-            if ((AudioSystem.DEVICE_OUT_HDMI & mSafeMediaVolumeDevices) != 0) {
+            if (mSafeMediaVolumeDevices.contains(AudioSystem.DEVICE_OUT_HDMI)) {
                 sendMsg(mAudioHandler,
                         MSG_CHECK_MUSIC_ACTIVE,
                         SENDMSG_REPLACE,
@@ -1762,8 +1766,8 @@
 
         // skip a2dp absolute volume control request when the device
         // is not an a2dp device
-        if ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) == 0 &&
-            (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) != 0) {
+        if (!AudioSystem.DEVICE_OUT_ALL_A2DP_SET.contains(device)
+                && (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) != 0) {
             return;
         }
 
@@ -1784,14 +1788,14 @@
 
         flags &= ~AudioManager.FLAG_FIXED_VOLUME;
         if ((streamTypeAlias == AudioSystem.STREAM_MUSIC) &&
-                ((device & mFixedVolumeDevices) != 0)) {
+                mFixedVolumeDevices.contains(device)) {
             flags |= AudioManager.FLAG_FIXED_VOLUME;
 
             // Always toggle between max safe volume and 0 for fixed volume devices where safe
             // volume is enforced, and max and 0 for the others.
             // This is simulated by stepping by the full allowed volume range
             if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE &&
-                    (device & mSafeMediaVolumeDevices) != 0) {
+                    mSafeMediaVolumeDevices.contains(device)) {
                 step = safeMediaVolumeIndex(device);
             } else {
                 step = streamState.getMaxIndex();
@@ -1861,7 +1865,7 @@
                     !checkSafeMediaVolume(streamTypeAlias, aliasIndex + step, device)) {
                 Log.e(TAG, "adjustStreamVolume() safe volume index = " + oldIndex);
                 mVolumeController.postDisplaySafeVolumeWarning(flags);
-            } else if (((device & mFullVolumeDevices) == 0)
+            } else if (!mFullVolumeDevices.contains(device)
                     && (streamState.adjustIndex(direction * step, device, caller)
                             || streamState.mIsMuted)) {
                 // Post message to set system volume (it in turn will post a
@@ -1890,9 +1894,9 @@
             int newIndex = mStreamStates[streamType].getIndex(device);
 
             // Check if volume update should be send to AVRCP
-            if (streamTypeAlias == AudioSystem.STREAM_MUSIC &&
-                (device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 &&
-                (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) == 0) {
+            if (streamTypeAlias == AudioSystem.STREAM_MUSIC
+                    && AudioSystem.DEVICE_OUT_ALL_A2DP_SET.contains(device)
+                    && (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) == 0) {
                 if (DEBUG_VOL) {
                     Log.d(TAG, "adjustSreamVolume: postSetAvrcpAbsoluteVolumeIndex index="
                             + newIndex + "stream=" + streamType);
@@ -1901,7 +1905,7 @@
             }
 
             // Check if volume update should be send to Hearing Aid
-            if ((device & AudioSystem.DEVICE_OUT_HEARING_AID) != 0) {
+            if (device == AudioSystem.DEVICE_OUT_HEARING_AID) {
                 // only modify the hearing aid attenuation when the stream to modify matches
                 // the one expected by the hearing aid
                 if (streamType == getHearingAidStreamType()) {
@@ -1923,7 +1927,7 @@
                     if (mHdmiCecSink
                             && streamTypeAlias == AudioSystem.STREAM_MUSIC
                             // vol change on a full volume device
-                            && ((device & mFullVolumeDevices) != 0)) {
+                            && mFullVolumeDevices.contains(device)) {
                         int keyCode = KeyEvent.KEYCODE_UNKNOWN;
                         switch (direction) {
                             case AudioManager.ADJUST_RAISE:
@@ -2291,13 +2295,17 @@
 
         int streamType = getHearingAidStreamType(newMode);
 
-        final int device = AudioSystem.getDevicesForStream(streamType);
-        if ((device & mAbsVolumeMultiModeCaseDevices) == 0) {
+        final Set<Integer> deviceTypes = AudioSystem.generateAudioDeviceTypesSet(
+                AudioSystem.getDevicesForStream(streamType));
+        final Set<Integer> absVolumeMultiModeCaseDevices = AudioSystem.intersectionAudioDeviceTypes(
+                mAbsVolumeMultiModeCaseDevices, deviceTypes);
+        if (absVolumeMultiModeCaseDevices.isEmpty()) {
             return;
         }
 
         // handling of specific interfaces goes here:
-        if ((device & mAbsVolumeMultiModeCaseDevices) == AudioSystem.DEVICE_OUT_HEARING_AID) {
+        if (AudioSystem.isSingleAudioDeviceType(
+                absVolumeMultiModeCaseDevices, AudioSystem.DEVICE_OUT_HEARING_AID)) {
             final int index = getStreamVolume(streamType);
             sVolumeLogger.log(new VolumeEvent(VolumeEvent.VOL_MODE_CHANGE_HEARING_AID,
                     newMode, streamType, index));
@@ -2324,8 +2332,8 @@
 
         // skip a2dp absolute volume control request when the device
         // is not an a2dp device
-        if ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) == 0 &&
-            (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) != 0) {
+        if (!AudioSystem.DEVICE_OUT_ALL_A2DP_SET.contains(device)
+                && (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) != 0) {
             return;
         }
         // If we are being called by the system (e.g. hardware keys) check for current user
@@ -2357,7 +2365,7 @@
             index = rescaleIndex(index * 10, streamType, streamTypeAlias);
 
             if (streamTypeAlias == AudioSystem.STREAM_MUSIC
-                    && (device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0
+                    && AudioSystem.DEVICE_OUT_ALL_A2DP_SET.contains(device)
                     && (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) == 0) {
                 if (DEBUG_VOL) {
                     Log.d(TAG, "setStreamVolume postSetAvrcpAbsoluteVolumeIndex index=" + index
@@ -2366,7 +2374,7 @@
                 mDeviceBroker.postSetAvrcpAbsoluteVolumeIndex(index / 10);
             }
 
-            if ((device & AudioSystem.DEVICE_OUT_HEARING_AID) != 0
+            if (device == AudioSystem.DEVICE_OUT_HEARING_AID
                     && streamType == getHearingAidStreamType()) {
                 Log.i(TAG, "setStreamVolume postSetHearingAidVolumeIndex index=" + index
                         + " stream=" + streamType);
@@ -2379,13 +2387,13 @@
 
             flags &= ~AudioManager.FLAG_FIXED_VOLUME;
             if ((streamTypeAlias == AudioSystem.STREAM_MUSIC) &&
-                    ((device & mFixedVolumeDevices) != 0)) {
+                    mFixedVolumeDevices.contains(device)) {
                 flags |= AudioManager.FLAG_FIXED_VOLUME;
 
                 // volume is either 0 or max allowed for fixed volume devices
                 if (index != 0) {
                     if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE &&
-                            (device & mSafeMediaVolumeDevices) != 0) {
+                            mSafeMediaVolumeDevices.contains(device)) {
                         index = safeMediaVolumeIndex(device);
                     } else {
                         index = streamState.getMaxIndex();
@@ -2568,7 +2576,7 @@
 
         if (streamType == AudioSystem.STREAM_MUSIC) {
             flags = updateFlagsForTvPlatform(flags);
-            if ((device & mFullVolumeDevices) != 0) {
+            if (mFullVolumeDevices.contains(device)) {
                 flags &= ~AudioManager.FLAG_SHOW_UI;
             }
         }
@@ -2614,7 +2622,7 @@
                                     int device,
                                     boolean force,
                                     String caller) {
-        if ((device & mFullVolumeDevices) != 0) {
+        if (mFullVolumeDevices.contains(device)) {
             return;
         }
         VolumeStreamState streamState = mStreamStates[streamType];
@@ -2731,8 +2739,8 @@
                 if (!hasRmtSbmxFullVolDeathHandlerFor(cb)) {
                     mRmtSbmxFullVolDeathHandlers.add(new RmtSbmxFullVolDeathHandler(cb));
                     if (mRmtSbmxFullVolRefCount == 0) {
-                        mFullVolumeDevices |= AudioSystem.DEVICE_OUT_REMOTE_SUBMIX;
-                        mFixedVolumeDevices |= AudioSystem.DEVICE_OUT_REMOTE_SUBMIX;
+                        mFullVolumeDevices.add(AudioSystem.DEVICE_OUT_REMOTE_SUBMIX);
+                        mFixedVolumeDevices.add(AudioSystem.DEVICE_OUT_REMOTE_SUBMIX);
                         applyRequired = true;
                     }
                     mRmtSbmxFullVolRefCount++;
@@ -2741,8 +2749,8 @@
                 if (discardRmtSbmxFullVolDeathHandlerFor(cb) && (mRmtSbmxFullVolRefCount > 0)) {
                     mRmtSbmxFullVolRefCount--;
                     if (mRmtSbmxFullVolRefCount == 0) {
-                        mFullVolumeDevices &= ~AudioSystem.DEVICE_OUT_REMOTE_SUBMIX;
-                        mFixedVolumeDevices &= ~AudioSystem.DEVICE_OUT_REMOTE_SUBMIX;
+                        mFullVolumeDevices.remove(AudioSystem.DEVICE_OUT_REMOTE_SUBMIX);
+                        mFixedVolumeDevices.remove(AudioSystem.DEVICE_OUT_REMOTE_SUBMIX);
                         applyRequired = true;
                     }
                 }
@@ -2824,7 +2832,7 @@
                 index = 0;
             }
             if (index != 0 && (mStreamVolumeAlias[streamType] == AudioSystem.STREAM_MUSIC) &&
-                    (device & mFixedVolumeDevices) != 0) {
+                    mFixedVolumeDevices.contains(device)) {
                 index = mStreamStates[streamType].getMaxIndex();
             }
             return (index + 5) / 10;
@@ -3699,7 +3707,7 @@
             if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_INACTIVE) {
                 int device = getDeviceForStream(AudioSystem.STREAM_MUSIC);
 
-                if ((device & mSafeMediaVolumeDevices) != 0) {
+                if (mSafeMediaVolumeDevices.contains(device)) {
                     sendMsg(mAudioHandler,
                             MSG_CHECK_MUSIC_ACTIVE,
                             SENDMSG_REPLACE,
@@ -4251,6 +4259,8 @@
             // retain the device on the A2DP output as the other must not correspond to an active
             // selection if not the speaker.
             //  - HDMI-CEC system audio mode only output: give priority to available item in order.
+            // FIXME: Haven't applied audio device type refactor to this API
+            //  as it is going to be deprecated.
             if ((device & AudioSystem.DEVICE_OUT_SPEAKER) != 0) {
                 device = AudioSystem.DEVICE_OUT_SPEAKER;
             } else if ((device & AudioSystem.DEVICE_OUT_HDMI_ARC) != 0) {
@@ -4260,7 +4270,11 @@
             } else if ((device & AudioSystem.DEVICE_OUT_AUX_LINE) != 0) {
                 device = AudioSystem.DEVICE_OUT_AUX_LINE;
             } else {
-                device &= AudioSystem.DEVICE_OUT_ALL_A2DP;
+                for (int deviceType : AudioSystem.DEVICE_OUT_ALL_A2DP_SET) {
+                    if ((deviceType & device) == deviceType) {
+                        return deviceType;
+                    }
+                }
             }
         }
         return device;
@@ -4393,12 +4407,16 @@
         mDeviceBroker.postBluetoothA2dpDeviceConfigChange(device);
     }
 
-    private static final int DEVICE_MEDIA_UNMUTED_ON_PLUG =
-            AudioSystem.DEVICE_OUT_WIRED_HEADSET | AudioSystem.DEVICE_OUT_WIRED_HEADPHONE |
-            AudioSystem.DEVICE_OUT_LINE |
-            AudioSystem.DEVICE_OUT_ALL_A2DP |
-            AudioSystem.DEVICE_OUT_ALL_USB |
-            AudioSystem.DEVICE_OUT_HDMI;
+    private static final Set<Integer> DEVICE_MEDIA_UNMUTED_ON_PLUG_SET;
+    static {
+        DEVICE_MEDIA_UNMUTED_ON_PLUG_SET = new HashSet<>();
+        DEVICE_MEDIA_UNMUTED_ON_PLUG_SET.add(AudioSystem.DEVICE_OUT_WIRED_HEADSET);
+        DEVICE_MEDIA_UNMUTED_ON_PLUG_SET.add(AudioSystem.DEVICE_OUT_WIRED_HEADPHONE);
+        DEVICE_MEDIA_UNMUTED_ON_PLUG_SET.add(AudioSystem.DEVICE_OUT_LINE);
+        DEVICE_MEDIA_UNMUTED_ON_PLUG_SET.addAll(AudioSystem.DEVICE_OUT_ALL_A2DP_SET);
+        DEVICE_MEDIA_UNMUTED_ON_PLUG_SET.addAll(AudioSystem.DEVICE_OUT_ALL_USB_SET);
+        DEVICE_MEDIA_UNMUTED_ON_PLUG_SET.add(AudioSystem.DEVICE_OUT_HDMI);
+    }
 
     /** only public for mocking/spying, do not call outside of AudioService */
     @VisibleForTesting
@@ -4414,7 +4432,7 @@
         }
 
         if (mNm.getZenMode() != Settings.Global.ZEN_MODE_NO_INTERRUPTIONS
-                && (newDevice & DEVICE_MEDIA_UNMUTED_ON_PLUG) != 0
+                && DEVICE_MEDIA_UNMUTED_ON_PLUG_SET.contains(newDevice)
                 && mStreamStates[AudioSystem.STREAM_MUSIC].mIsMuted
                 && mStreamStates[AudioSystem.STREAM_MUSIC].getIndex(newDevice) != 0
                 && (newDevice & AudioSystem.getDevicesForStream(AudioSystem.STREAM_MUSIC)) != 0) {
@@ -4543,14 +4561,7 @@
                 }
             }
             synchronized (VolumeStreamState.class) {
-                int remainingDevices = AudioSystem.DEVICE_OUT_ALL;
-
-                for (int i = 0; remainingDevices != 0; i++) {
-                    int device = (1 << i);
-                    if ((device & remainingDevices) == 0) {
-                        continue;
-                    }
-                    remainingDevices &= ~device;
+                for (int device : AudioSystem.DEVICE_OUT_ALL_SET) {
 
                     // retrieve current volume for device
                     // if no volume stored for current stream and device, use default volume if default
@@ -4610,11 +4621,12 @@
             int index;
             if (mIsMuted) {
                 index = 0;
-            } else if ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 && isAvrcpAbsVolSupported) {
+            } else if (AudioSystem.DEVICE_OUT_ALL_A2DP_SET.contains(device)
+                    && isAvrcpAbsVolSupported) {
                 index = getAbsoluteVolumeIndex((getIndex(device) + 5)/10);
-            } else if ((device & mFullVolumeDevices) != 0) {
+            } else if (mFullVolumeDevices.contains(device)) {
                 index = (mIndexMax + 5)/10;
-            } else if ((device & AudioSystem.DEVICE_OUT_HEARING_AID) != 0) {
+            } else if (device == AudioSystem.DEVICE_OUT_HEARING_AID) {
                 index = (mIndexMax + 5)/10;
             } else {
                 index = (getIndex(device) + 5)/10;
@@ -4632,12 +4644,12 @@
                     if (device != AudioSystem.DEVICE_OUT_DEFAULT) {
                         if (mIsMuted) {
                             index = 0;
-                        } else if ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 &&
-                                isAvrcpAbsVolSupported) {
+                        } else if (AudioSystem.DEVICE_OUT_ALL_A2DP_SET.contains(device)
+                                && isAvrcpAbsVolSupported) {
                             index = getAbsoluteVolumeIndex((getIndex(device) + 5)/10);
-                        } else if ((device & mFullVolumeDevices) != 0) {
+                        } else if (mFullVolumeDevices.contains(device)) {
                             index = (mIndexMax + 5)/10;
-                        } else if ((device & AudioSystem.DEVICE_OUT_HEARING_AID) != 0) {
+                        } else if (device == AudioSystem.DEVICE_OUT_HEARING_AID) {
                             index = (mIndexMax + 5)/10;
                         } else {
                             index = (mIndexMap.valueAt(i) + 5)/10;
@@ -4698,7 +4710,7 @@
                             && device == AudioSystem.DEVICE_OUT_SPEAKER) {
                         for (int i = 0; i < mIndexMap.size(); i++) {
                             int otherDevice = mIndexMap.keyAt(i);
-                            if ((otherDevice & AudioSystem.DEVICE_OUT_ALL_SCO) != 0) {
+                            if (AudioSystem.DEVICE_OUT_ALL_SCO_SET.contains(otherDevice)) {
                                 mIndexMap.put(otherDevice, index);
                             }
                         }
@@ -4836,8 +4848,8 @@
                     for (int i = 0; i < mIndexMap.size(); i++) {
                         int device = mIndexMap.keyAt(i);
                         int index = mIndexMap.valueAt(i);
-                        if (((device & mFullVolumeDevices) != 0)
-                                || (((device & mFixedVolumeDevices) != 0) && index != 0)) {
+                        if (mFullVolumeDevices.contains(device)
+                                || (mFixedVolumeDevices.contains(device) && index != 0)) {
                             mIndexMap.put(device, mIndexMax);
                         }
                         applyDeviceVolume_syncVSS(device, isAvrcpAbsVolSupported);
@@ -5008,7 +5020,7 @@
                     // that may have a different device selected
                     int streamDevice = getDeviceForStream(streamType);
                     if ((device != streamDevice) && isAvrcpAbsVolSupported
-                            && ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0)) {
+                            && AudioSystem.DEVICE_OUT_ALL_A2DP_SET.contains(device)) {
                         mStreamStates[streamType].applyDeviceVolume_syncVSS(device,
                                 isAvrcpAbsVolSupported);
                     }
@@ -5337,7 +5349,7 @@
     }
 
     /*package*/ void checkMusicActive(int deviceType, String caller) {
-        if ((deviceType & mSafeMediaVolumeDevices) != 0) {
+        if (mSafeMediaVolumeDevices.contains(deviceType)) {
             sendMsg(mAudioHandler,
                     MSG_CHECK_MUSIC_ACTIVE,
                     SENDMSG_REPLACE,
@@ -5783,9 +5795,9 @@
     // the headset is compliant to EN 60950 with a max loudness of 100dB SPL.
     private int mSafeUsbMediaVolumeIndex;
     // mSafeMediaVolumeDevices lists the devices for which safe media volume is enforced,
-    /*package*/ final int mSafeMediaVolumeDevices = AudioSystem.DEVICE_OUT_WIRED_HEADSET
-            | AudioSystem.DEVICE_OUT_WIRED_HEADPHONE
-            | AudioSystem.DEVICE_OUT_USB_HEADSET;
+    /*package*/ final Set<Integer> mSafeMediaVolumeDevices = new HashSet<>(
+            Arrays.asList(AudioSystem.DEVICE_OUT_WIRED_HEADSET,
+                    AudioSystem.DEVICE_OUT_WIRED_HEADPHONE, AudioSystem.DEVICE_OUT_USB_HEADSET));
     // mMusicActiveMs is the cumulative time of music activity since safe volume was disabled.
     // When this time reaches UNSAFE_VOLUME_MUSIC_ACTIVE_MS_MAX, the safe media volume is re-enabled
     // automatically. mMusicActiveMs is rounded to a multiple of MUSIC_ACTIVE_POLL_PERIOD_MS.
@@ -5795,7 +5807,7 @@
     private static final int SAFE_VOLUME_CONFIGURE_TIMEOUT_MS = 30000;  // 30s after boot completed
 
     private int safeMediaVolumeIndex(int device) {
-        if ((device & mSafeMediaVolumeDevices) == 0) {
+        if (!mSafeMediaVolumeDevices.contains(device)) {
             return MAX_STREAM_VOLUME[AudioSystem.STREAM_MUSIC];
         }
         if (device == AudioSystem.DEVICE_OUT_USB_HEADSET) {
@@ -5830,14 +5842,9 @@
 
     private void enforceSafeMediaVolume(String caller) {
         VolumeStreamState streamState = mStreamStates[AudioSystem.STREAM_MUSIC];
-        int devices = mSafeMediaVolumeDevices;
-        int i = 0;
+        Set<Integer> devices = mSafeMediaVolumeDevices;
 
-        while (devices != 0) {
-            int device = 1 << i++;
-            if ((device & devices) == 0) {
-                continue;
-            }
+        for (int device : devices) {
             int index = streamState.getIndex(device);
             if (index > safeMediaVolumeIndex(device)) {
                 streamState.setIndex(safeMediaVolumeIndex(device), device, caller);
@@ -5849,16 +5856,15 @@
                         streamState,
                         0);
             }
-            devices &= ~device;
         }
     }
 
     private boolean checkSafeMediaVolume(int streamType, int index, int device) {
         synchronized (mSafeMediaVolumeStateLock) {
-            if ((mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE) &&
-                    (mStreamVolumeAlias[streamType] == AudioSystem.STREAM_MUSIC) &&
-                    ((device & mSafeMediaVolumeDevices) != 0) &&
-                    (index > safeMediaVolumeIndex(device))) {
+            if ((mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE)
+                    && (mStreamVolumeAlias[streamType] == AudioSystem.STREAM_MUSIC)
+                    && (mSafeMediaVolumeDevices.contains(device))
+                    && (index > safeMediaVolumeIndex(device))) {
                 return false;
             }
             return true;
@@ -5899,14 +5905,14 @@
             if (DEBUG_VOL) {
                 Log.d(TAG, "CEC sink: setting HDMI as full vol device");
             }
-            mFullVolumeDevices |= AudioSystem.DEVICE_OUT_HDMI;
+            mFullVolumeDevices.add(AudioSystem.DEVICE_OUT_HDMI);
         } else {
             if (DEBUG_VOL) {
                 Log.d(TAG, "TV, no CEC: setting HDMI as regular vol device");
             }
             // Android TV devices without CEC service apply software volume on
             // HDMI output
-            mFullVolumeDevices &= ~AudioSystem.DEVICE_OUT_HDMI;
+            mFullVolumeDevices.remove(AudioSystem.DEVICE_OUT_HDMI);
         }
 
         checkAddAllFixedVolumeDevices(AudioSystem.DEVICE_OUT_HDMI,
@@ -6127,6 +6133,19 @@
         pw.println();
     }
 
+    private String dumpDeviceTypes(@NonNull Set<Integer> deviceTypes) {
+        Iterator<Integer> it = deviceTypes.iterator();
+        if (!it.hasNext()) {
+            return "";
+        }
+        final StringBuilder sb = new StringBuilder();
+        sb.append("0x" + Integer.toHexString(it.next()));
+        while (it.hasNext()) {
+            sb.append("," + "0x" + Integer.toHexString(it.next()));
+        }
+        return sb.toString();
+    }
+
     @Override
     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
@@ -6163,7 +6182,7 @@
         pw.println(mDeviceBroker.isAvrcpAbsoluteVolumeSupported());
         pw.print("  mIsSingleVolume="); pw.println(mIsSingleVolume);
         pw.print("  mUseFixedVolume="); pw.println(mUseFixedVolume);
-        pw.print("  mFixedVolumeDevices=0x"); pw.println(Integer.toHexString(mFixedVolumeDevices));
+        pw.print("  mFixedVolumeDevices="); pw.println(dumpDeviceTypes(mFixedVolumeDevices));
         pw.print("  mHdmiCecSink="); pw.println(mHdmiCecSink);
         pw.print("  mHdmiAudioSystemClient="); pw.println(mHdmiAudioSystemClient);
         pw.print("  mHdmiPlaybackClient="); pw.println(mHdmiPlaybackClient);
diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java
index 637bcae..c84745e 100644
--- a/services/core/java/com/android/server/location/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/GnssLocationProvider.java
@@ -1169,14 +1169,15 @@
             if (newWork != null) {
                 for (int i = 0; i < newWork.size(); i++) {
                     mAppOps.startOpNoThrow(AppOpsManager.OP_GPS,
-                            newWork.get(i), newWork.getName(i));
+                            newWork.getUid(i), newWork.getPackageName(i));
                 }
             }
 
             // Update sources that are no longer tracked.
             if (goneWork != null) {
                 for (int i = 0; i < goneWork.size(); i++) {
-                    mAppOps.finishOp(AppOpsManager.OP_GPS, goneWork.get(i), goneWork.getName(i));
+                    mAppOps.finishOp(AppOpsManager.OP_GPS, goneWork.getUid(i),
+                            goneWork.getPackageName(i));
                 }
             }
         }
diff --git a/services/core/java/com/android/server/location/LocationSettingsStore.java b/services/core/java/com/android/server/location/LocationSettingsStore.java
index a4b6d97..dc5628e 100644
--- a/services/core/java/com/android/server/location/LocationSettingsStore.java
+++ b/services/core/java/com/android/server/location/LocationSettingsStore.java
@@ -237,9 +237,6 @@
         IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "  ");
         int userId = ActivityManager.getCurrentUser();
 
-        ipw.println("--Location Settings--");
-        ipw.increaseIndent();
-
         ipw.print("Location Enabled: ");
         ipw.println(isLocationEnabled(userId));
 
diff --git a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
index 7820cd7..2cf920d 100644
--- a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
+++ b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
@@ -83,6 +83,24 @@
         mContext = context;
     }
 
+    @NonNull
+    public List<MediaRoute2Info> getSystemRoutes() {
+        final int uid = Binder.getCallingUid();
+        final int userId = UserHandle.getUserId(uid);
+
+        Collection<MediaRoute2Info> systemRoutes;
+        synchronized (mLock) {
+            UserRecord userRecord = mUserRecords.get(userId);
+            if (userRecord == null) {
+                userRecord = new UserRecord(userId);
+                mUserRecords.put(userId, userRecord);
+                initializeUserLocked(userRecord);
+            }
+            systemRoutes = userRecord.mHandler.mSystemProvider.getProviderInfo().getRoutes();
+        }
+        return new ArrayList<>(systemRoutes);
+    }
+
     public void registerClient(@NonNull IMediaRouter2Client client,
             @NonNull String packageName) {
         Objects.requireNonNull(client, "client must not be null");
diff --git a/services/core/java/com/android/server/media/MediaRouterService.java b/services/core/java/com/android/server/media/MediaRouterService.java
index ecc1aba..9336af4 100644
--- a/services/core/java/com/android/server/media/MediaRouterService.java
+++ b/services/core/java/com/android/server/media/MediaRouterService.java
@@ -443,6 +443,12 @@
 
     // Binder call
     @Override
+    public List<MediaRoute2Info> getSystemRoutes() {
+        return mService2.getSystemRoutes();
+    }
+
+    // Binder call
+    @Override
     public void registerClient2(IMediaRouter2Client client, String packageName) {
         final int uid = Binder.getCallingUid();
         if (!validatePackageName(uid, packageName)) {
diff --git a/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java b/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java
index 620775e..4f64177 100644
--- a/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java
+++ b/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java
@@ -42,8 +42,8 @@
     private static final String TAG = "MR2SystemProvider";
     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
 
-    private static final String DEFAULT_ROUTE_ID = "DEFAULT_ROUTE";
-    private static final String BLUETOOTH_ROUTE_ID = "BLUETOOTH_ROUTE";
+    static final String DEFAULT_ROUTE_ID = "DEFAULT_ROUTE";
+    static final String BLUETOOTH_ROUTE_ID = "BLUETOOTH_ROUTE";
 
     // TODO: Move these to a proper place
     public static final String CATEGORY_LIVE_AUDIO = "android.media.intent.category.LIVE_AUDIO";
@@ -191,12 +191,20 @@
 
         publishRoutes();
     }
+
+    /**
+     * The first route should be the currently selected system route.
+     * For example, if there are two system routes (BT and device speaker),
+     * BT will be the first route in the list.
+     *
+     * TODO: Support multiple BT devices
+     */
     void publishRoutes() {
-        MediaRoute2ProviderInfo.Builder builder = new MediaRoute2ProviderInfo.Builder()
-                .addRoute(mDefaultRoute);
+        MediaRoute2ProviderInfo.Builder builder = new MediaRoute2ProviderInfo.Builder();
         if (mBluetoothA2dpRoute != null) {
             builder.addRoute(mBluetoothA2dpRoute);
         }
+        builder.addRoute(mDefaultRoute);
         setAndNotifyProviderInfo(builder.build());
     }
 }
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 0ae4a8f..b60306b 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -360,9 +360,11 @@
     private static final String EXTRA_KEY = "key";
 
     /**
-     * Apps targeting R+ that post custom toasts in the background will have those blocked. Apps can
+     * Apps that post custom toasts in the background will have those blocked. Apps can
      * still post toasts created with {@link Toast#makeText(Context, CharSequence, int)} and its
      * variants while in the background.
+     *
+     * TODO(b/144152069): Add @EnabledAfter(Q) to target R+ after assessing impact on dogfood
      */
     @ChangeId
     private static final long CHANGE_BACKGROUND_CUSTOM_TOAST_BLOCK = 128611929L;
diff --git a/services/core/java/com/android/server/om/OverlayActorEnforcer.java b/services/core/java/com/android/server/om/OverlayActorEnforcer.java
new file mode 100644
index 0000000..e055116
--- /dev/null
+++ b/services/core/java/com/android/server/om/OverlayActorEnforcer.java
@@ -0,0 +1,261 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.om;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.om.OverlayInfo;
+import android.content.om.OverlayableInfo;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.net.Uri;
+import android.os.Process;
+import android.os.RemoteException;
+import android.text.TextUtils;
+
+import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.CollectionUtils;
+import com.android.server.SystemConfig;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Performs verification that a calling UID can act on a target package's overlayable.
+ *
+ * @hide
+ */
+public class OverlayActorEnforcer {
+
+    private final VerifyCallback mVerifyCallback;
+
+    public OverlayActorEnforcer(@NonNull VerifyCallback verifyCallback) {
+        mVerifyCallback = verifyCallback;
+    }
+
+    void enforceActor(@NonNull OverlayInfo overlayInfo, @NonNull String methodName,
+            int callingUid, int userId) throws SecurityException {
+        ActorState actorState = isAllowedActor(methodName, overlayInfo, callingUid, userId);
+        if (actorState == ActorState.ALLOWED) {
+            return;
+        }
+
+        String targetOverlayableName = overlayInfo.targetOverlayableName;
+        throw new SecurityException("UID" + callingUid + " is not allowed to call "
+                + methodName + " for "
+                + (TextUtils.isEmpty(targetOverlayableName) ? "" : (targetOverlayableName + " in "))
+                + overlayInfo.targetPackageName + " because " + actorState
+        );
+    }
+
+    /**
+     * An actor is valid if any of the following is true:
+     * - is {@link Process#ROOT_UID}, {@link Process#SYSTEM_UID}
+     * - is the target overlay package
+     * - has the CHANGE_OVERLAY_PACKAGES permission and an actor is not defined
+     * - is the same the as the package defined in {@link SystemConfig#getNamedActors()} for a given
+     *     namespace and actor name
+     *
+     * @return true if the actor is allowed to act on the target overlayInfo
+     */
+    private ActorState isAllowedActor(String methodName, OverlayInfo overlayInfo,
+            int callingUid, int userId) {
+        switch (callingUid) {
+            case Process.ROOT_UID:
+            case Process.SYSTEM_UID:
+                return ActorState.ALLOWED;
+        }
+
+        String[] callingPackageNames = mVerifyCallback.getPackagesForUid(callingUid);
+        if (ArrayUtils.isEmpty(callingPackageNames)) {
+            return ActorState.NO_PACKAGES_FOR_UID;
+        }
+
+        // A target is always an allowed actor for itself
+        String targetPackageName = overlayInfo.targetPackageName;
+        if (ArrayUtils.contains(callingPackageNames, targetPackageName)) {
+            return ActorState.ALLOWED;
+        }
+
+        String targetOverlayableName = overlayInfo.targetOverlayableName;
+
+        if (TextUtils.isEmpty(targetOverlayableName)) {
+            try {
+                if (mVerifyCallback.doesTargetDefineOverlayable(targetPackageName, userId)) {
+                    return ActorState.MISSING_TARGET_OVERLAYABLE_NAME;
+                } else {
+                    // If there's no overlayable defined, fallback to the legacy permission check
+                    try {
+                        mVerifyCallback.enforcePermission(
+                                android.Manifest.permission.CHANGE_OVERLAY_PACKAGES, methodName);
+
+                        // If the previous method didn't throw, check passed
+                        return ActorState.ALLOWED;
+                    } catch (SecurityException e) {
+                        return ActorState.MISSING_LEGACY_PERMISSION;
+                    }
+                }
+            } catch (RemoteException | IOException e) {
+                return ActorState.ERROR_READING_OVERLAYABLE;
+            }
+        }
+
+        OverlayableInfo targetOverlayable;
+        try {
+            targetOverlayable = mVerifyCallback.getOverlayableForTarget(targetPackageName,
+                    targetOverlayableName, userId);
+        } catch (IOException e) {
+            return ActorState.UNABLE_TO_GET_TARGET;
+        }
+
+        if (targetOverlayable == null) {
+            return ActorState.MISSING_OVERLAYABLE;
+        }
+
+        String actor = targetOverlayable.actor;
+        if (TextUtils.isEmpty(actor)) {
+            // If there's no actor defined, fallback to the legacy permission check
+            try {
+                mVerifyCallback.enforcePermission(
+                        android.Manifest.permission.CHANGE_OVERLAY_PACKAGES, methodName);
+
+                // If the previous method didn't throw, check passed
+                return ActorState.ALLOWED;
+            } catch (SecurityException e) {
+                return ActorState.MISSING_LEGACY_PERMISSION;
+            }
+        }
+
+        Map<String, ? extends Map<String, String>> namedActors = mVerifyCallback.getNamedActors();
+        if (namedActors.isEmpty()) {
+            return ActorState.NO_NAMED_ACTORS;
+        }
+
+        Uri actorUri = Uri.parse(actor);
+
+        String actorScheme = actorUri.getScheme();
+        List<String> actorPathSegments = actorUri.getPathSegments();
+        if (!"overlay".equals(actorScheme) || CollectionUtils.size(actorPathSegments) != 1) {
+            return ActorState.INVALID_OVERLAYABLE_ACTOR_NAME;
+        }
+
+        String actorNamespace = actorUri.getAuthority();
+        Map<String, String> namespace = namedActors.get(actorNamespace);
+        if (namespace == null) {
+            return ActorState.MISSING_NAMESPACE;
+        }
+
+        String actorName = actorPathSegments.get(0);
+        String packageName = namespace.get(actorName);
+        if (TextUtils.isEmpty(packageName)) {
+            return ActorState.MISSING_ACTOR_NAME;
+        }
+
+        PackageInfo packageInfo = mVerifyCallback.getPackageInfo(packageName, userId);
+        if (packageInfo == null) {
+            return ActorState.MISSING_APP_INFO;
+        }
+
+        ApplicationInfo appInfo = packageInfo.applicationInfo;
+        if (appInfo == null) {
+            return ActorState.MISSING_APP_INFO;
+        }
+
+        // Currently only pre-installed apps can be actors
+        if (!appInfo.isSystemApp() && !appInfo.isUpdatedSystemApp()) {
+            return ActorState.ACTOR_NOT_PREINSTALLED;
+        }
+
+        if (ArrayUtils.contains(callingPackageNames, packageName)) {
+            return ActorState.ALLOWED;
+        }
+
+        return ActorState.INVALID_ACTOR;
+    }
+
+    /**
+     * For easier logging/debugging, a set of all possible failure/success states when running
+     * enforcement.
+     */
+    private enum ActorState {
+        ALLOWED,
+        INVALID_ACTOR,
+        MISSING_NAMESPACE,
+        MISSING_PACKAGE,
+        MISSING_APP_INFO,
+        ACTOR_NOT_PREINSTALLED,
+        NO_PACKAGES_FOR_UID,
+        MISSING_ACTOR_NAME,
+        ERROR_READING_OVERLAYABLE,
+        MISSING_TARGET_OVERLAYABLE_NAME,
+        MISSING_OVERLAYABLE,
+        INVALID_OVERLAYABLE_ACTOR_NAME,
+        NO_NAMED_ACTORS,
+        UNABLE_TO_GET_TARGET,
+        MISSING_LEGACY_PERMISSION
+    }
+
+    /**
+     * Delegate to the system for querying information about packages.
+     */
+    public interface VerifyCallback {
+
+        /**
+         * Read from the APK and AndroidManifest of a package to return the overlayable defined for
+         * a given name.
+         *
+         * @throws IOException if the target can't be read
+         */
+        @Nullable
+        OverlayableInfo getOverlayableForTarget(@NonNull String packageName,
+                @Nullable String targetOverlayableName, int userId)
+                throws IOException;
+
+        /**
+         * @see android.content.pm.PackageManager#getPackagesForUid(int)
+         */
+        @Nullable
+        String[] getPackagesForUid(int uid);
+
+        /**
+         * @param userId user to filter package visibility by
+         * @see android.content.pm.PackageManager#getPackageInfo(String, int)
+         */
+        @Nullable
+        PackageInfo getPackageInfo(@NonNull String packageName, int userId);
+
+        /**
+         * @return map of system pre-defined, uniquely named actors; keys are namespace,
+         * value maps actor name to package name
+         */
+        @NonNull
+        Map<String, ? extends Map<String, String>> getNamedActors();
+
+        /**
+         * @return true if the target package has declared an overlayable
+         */
+        boolean doesTargetDefineOverlayable(String targetPackageName, int userId)
+                throws RemoteException, IOException;
+
+        /**
+         * @throws SecurityException containing message if the caller doesn't have the given
+         *                           permission
+         */
+        void enforcePermission(String permission, String message) throws SecurityException;
+    }
+}
diff --git a/services/core/java/com/android/server/om/OverlayManagerService.java b/services/core/java/com/android/server/om/OverlayManagerService.java
index 5f3e503..63de61c 100644
--- a/services/core/java/com/android/server/om/OverlayManagerService.java
+++ b/services/core/java/com/android/server/om/OverlayManagerService.java
@@ -39,10 +39,12 @@
 import android.content.IntentFilter;
 import android.content.om.IOverlayManager;
 import android.content.om.OverlayInfo;
+import android.content.om.OverlayableInfo;
 import android.content.pm.IPackageManager;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManagerInternal;
 import android.content.pm.UserInfo;
+import android.content.res.ApkAssets;
 import android.net.Uri;
 import android.os.Binder;
 import android.os.Environment;
@@ -63,6 +65,7 @@
 import com.android.server.FgThread;
 import com.android.server.IoThread;
 import com.android.server.LocalServices;
+import com.android.server.SystemConfig;
 import com.android.server.SystemService;
 import com.android.server.pm.UserManagerService;
 
@@ -229,6 +232,8 @@
 
     private final OverlayManagerServiceImpl mImpl;
 
+    private final OverlayActorEnforcer mActorEnforcer;
+
     private final AtomicBoolean mPersistSettingsScheduled = new AtomicBoolean(false);
 
     public OverlayManagerService(@NonNull final Context context) {
@@ -237,12 +242,13 @@
             traceBegin(TRACE_TAG_RRO, "OMS#OverlayManagerService");
             mSettingsFile = new AtomicFile(
                     new File(Environment.getDataSystemDirectory(), "overlays.xml"), "overlays");
-            mPackageManager = new PackageManagerHelper();
+            mPackageManager = new PackageManagerHelper(context);
             mUserManager = UserManagerService.getInstance();
             IdmapManager im = new IdmapManager(mPackageManager);
             mSettings = new OverlayManagerSettings();
             mImpl = new OverlayManagerServiceImpl(mPackageManager, im, mSettings,
                     getDefaultOverlayPackages(), new OverlayChangeListener());
+            mActorEnforcer = new OverlayActorEnforcer(mPackageManager);
 
             final IntentFilter packageFilter = new IntentFilter();
             packageFilter.addAction(ACTION_PACKAGE_ADDED);
@@ -581,7 +587,7 @@
                 int userId) throws RemoteException {
             try {
                 traceBegin(TRACE_TAG_RRO, "OMS#setEnabled " + packageName + " " + enable);
-                enforceChangeOverlayPackagesPermission("setEnabled");
+                enforceActor(packageName, "setEnabled", userId);
                 userId = handleIncomingUser(userId, "setEnabled");
                 if (packageName == null) {
                     return false;
@@ -605,7 +611,7 @@
                 int userId) throws RemoteException {
             try {
                 traceBegin(TRACE_TAG_RRO, "OMS#setEnabledExclusive " + packageName + " " + enable);
-                enforceChangeOverlayPackagesPermission("setEnabledExclusive");
+                enforceActor(packageName, "setEnabledExclusive", userId);
                 userId = handleIncomingUser(userId, "setEnabledExclusive");
                 if (packageName == null || !enable) {
                     return false;
@@ -630,7 +636,7 @@
                 throws RemoteException {
             try {
                 traceBegin(TRACE_TAG_RRO, "OMS#setEnabledExclusiveInCategory " + packageName);
-                enforceChangeOverlayPackagesPermission("setEnabledExclusiveInCategory");
+                enforceActor(packageName, "setEnabledExclusiveInCategory", userId);
                 userId = handleIncomingUser(userId, "setEnabledExclusiveInCategory");
                 if (packageName == null) {
                     return false;
@@ -656,7 +662,7 @@
             try {
                 traceBegin(TRACE_TAG_RRO, "OMS#setPriority " + packageName + " "
                         + parentPackageName);
-                enforceChangeOverlayPackagesPermission("setPriority");
+                enforceActor(packageName, "setPriority", userId);
                 userId = handleIncomingUser(userId, "setPriority");
                 if (packageName == null || parentPackageName == null) {
                     return false;
@@ -680,7 +686,7 @@
                 throws RemoteException {
             try {
                 traceBegin(TRACE_TAG_RRO, "OMS#setHighestPriority " + packageName);
-                enforceChangeOverlayPackagesPermission("setHighestPriority");
+                enforceActor(packageName, "setHighestPriority", userId);
                 userId = handleIncomingUser(userId, "setHighestPriority");
                 if (packageName == null) {
                     return false;
@@ -704,7 +710,7 @@
                 throws RemoteException {
             try {
                 traceBegin(TRACE_TAG_RRO, "OMS#setLowestPriority " + packageName);
-                enforceChangeOverlayPackagesPermission("setLowestPriority");
+                enforceActor(packageName, "setLowestPriority", userId);
                 userId = handleIncomingUser(userId, "setLowestPriority");
                 if (packageName == null) {
                     return false;
@@ -750,7 +756,7 @@
                 return;
             }
 
-            enforceChangeOverlayPackagesPermission("invalidateCachesForOverlay");
+            enforceActor(packageName, "invalidateCachesForOverlay", userId);
             userId = handleIncomingUser(userId, "invalidateCachesForOverlay");
             final long ident = Binder.clearCallingIdentity();
             try {
@@ -861,18 +867,6 @@
         }
 
         /**
-         * Enforce that the caller holds the CHANGE_OVERLAY_PACKAGES permission (or is
-         * system or root).
-         *
-         * @param message used as message if SecurityException is thrown
-         * @throws SecurityException if the permission check fails
-         */
-        private void enforceChangeOverlayPackagesPermission(@NonNull final String message) {
-            getContext().enforceCallingOrSelfPermission(
-                    android.Manifest.permission.CHANGE_OVERLAY_PACKAGES, message);
-        }
-
-        /**
          * Enforce that the caller holds the DUMP permission (or is system or root).
          *
          * @param message used as message if SecurityException is thrown
@@ -881,6 +875,13 @@
         private void enforceDumpPermission(@NonNull final String message) {
             getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, message);
         }
+
+        private void enforceActor(String packageName, String methodName, int userId)
+                throws SecurityException {
+            OverlayInfo overlayInfo = mImpl.getOverlayInfo(packageName, userId);
+            int callingUid = Binder.getCallingUid();
+            mActorEnforcer.enforceActor(overlayInfo, methodName, callingUid, userId);
+        }
     };
 
     private final class OverlayChangeListener
@@ -1035,9 +1036,16 @@
         }
     }
 
-    private static final class PackageManagerHelper implements
-            OverlayManagerServiceImpl.PackageManagerHelper {
+    /**
+     * Delegate for {@link android.content.pm.PackageManager} and {@link PackageManagerInternal}
+     * functionality, separated for easy testing.
+     *
+     * @hide
+     */
+    public static final class PackageManagerHelper implements
+            OverlayManagerServiceImpl.PackageManagerHelper, OverlayActorEnforcer.VerifyCallback {
 
+        private final Context mContext;
         private final IPackageManager mPackageManager;
         private final PackageManagerInternal mPackageManagerInternal;
 
@@ -1048,11 +1056,14 @@
         // behind until all pending intents have been processed.
         private final SparseArray<HashMap<String, PackageInfo>> mCache = new SparseArray<>();
 
-        PackageManagerHelper() {
+        PackageManagerHelper(Context context) {
+            mContext = context;
             mPackageManager = getPackageManager();
             mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class);
         }
 
+        // TODO(b/143096091): Remove PackageInfo cache so that PackageManager is always queried
+        //  to enforce visibility/other permission checks
         public PackageInfo getPackageInfo(@NonNull final String packageName, final int userId,
                 final boolean useCache) {
             if (useCache) {
@@ -1075,7 +1086,19 @@
 
         @Override
         public PackageInfo getPackageInfo(@NonNull final String packageName, final int userId) {
-            return getPackageInfo(packageName, userId, true);
+            // TODO(b/143096091): Remove clearing calling ID
+            long callingIdentity = Binder.clearCallingIdentity();
+            try {
+                return getPackageInfo(packageName, userId, true);
+            } finally {
+                Binder.restoreCallingIdentity(callingIdentity);
+            }
+        }
+
+        @NonNull
+        @Override
+        public Map<String, ? extends Map<String, String>> getNamedActors() {
+            return SystemConfig.getInstance().getNamedActors();
         }
 
         @Override
@@ -1097,6 +1120,70 @@
             return mPackageManagerInternal.getOverlayPackages(userId);
         }
 
+        @Nullable
+        @Override
+        public OverlayableInfo getOverlayableForTarget(@NonNull String packageName,
+                @Nullable String targetOverlayableName, int userId)
+                throws IOException {
+            // TODO(b/143096091): Remove clearing calling ID
+            long callingIdentity = Binder.clearCallingIdentity();
+            try {
+                PackageInfo packageInfo = getPackageInfo(packageName, userId);
+                if (packageInfo == null) {
+                    throw new IOException("Unable to get target package");
+                }
+
+                String baseCodePath = packageInfo.applicationInfo.getBaseCodePath();
+
+                ApkAssets apkAssets = null;
+                try {
+                    apkAssets = ApkAssets.loadFromPath(baseCodePath);
+                    return apkAssets.getOverlayableInfo(targetOverlayableName);
+                } finally {
+                    if (apkAssets != null) {
+                        try {
+                            apkAssets.close();
+                        } catch (Throwable ignored) {
+                        }
+                    }
+                }
+            } finally {
+                Binder.restoreCallingIdentity(callingIdentity);
+            }
+        }
+
+        @Override
+        public boolean doesTargetDefineOverlayable(String targetPackageName, int userId)
+                throws RemoteException, IOException {
+            // TODO(b/143096091): Remove clearing calling ID
+            long callingIdentity = Binder.clearCallingIdentity();
+            try {
+                PackageInfo packageInfo = mPackageManager.getPackageInfo(targetPackageName, 0,
+                        userId);
+                String baseCodePath = packageInfo.applicationInfo.getBaseCodePath();
+
+                ApkAssets apkAssets = null;
+                try {
+                    apkAssets = ApkAssets.loadFromPath(baseCodePath);
+                    return apkAssets.definesOverlayable();
+                } finally {
+                    if (apkAssets != null) {
+                        try {
+                            apkAssets.close();
+                        } catch (Throwable ignored) {
+                        }
+                    }
+                }
+            } finally {
+                Binder.restoreCallingIdentity(callingIdentity);
+            }
+        }
+
+        @Override
+        public void enforcePermission(String permission, String message) throws SecurityException {
+            mContext.enforceCallingOrSelfPermission(permission, message);
+        }
+
         public PackageInfo getCachedPackageInfo(@NonNull final String packageName,
                 final int userId) {
             final HashMap<String, PackageInfo> map = mCache.get(userId);
@@ -1128,6 +1215,22 @@
             mCache.delete(userId);
         }
 
+        @Nullable
+        @Override
+        public String[] getPackagesForUid(int uid) {
+            // TODO(b/143096091): Remove clearing calling ID
+            long callingIdentity = Binder.clearCallingIdentity();
+            try {
+                try {
+                    return mPackageManager.getPackagesForUid(uid);
+                } catch (RemoteException ignored) {
+                    return null;
+                }
+            } finally {
+                Binder.restoreCallingIdentity(callingIdentity);
+            }
+        }
+
         private static final String TAB1 = "    ";
         private static final String TAB2 = TAB1 + TAB1;
 
diff --git a/services/core/java/com/android/server/pm/OWNERS b/services/core/java/com/android/server/pm/OWNERS
index 62ea95b..f8c173f 100644
--- a/services/core/java/com/android/server/pm/OWNERS
+++ b/services/core/java/com/android/server/pm/OWNERS
@@ -32,6 +32,9 @@
 per-file CrossProfileIntentResolver.java = omakoto@google.com, yamasani@google.com
 per-file UserManagerService.java = omakoto@google.com, yamasani@google.com
 per-file UserRestrictionsUtils.java = omakoto@google.com, rubinxu@google.com, sandness@google.com, yamasani@google.com
+per-file UserSystemPackageInstaller.java = bookatz@google.com, omakoto@google.com, yamasani@google.com
+per-file UserTypeDetails.java = bookatz@google.com, omakoto@google.com, yamasani@google.com
+per-file UserTypeFactory.java = bookatz@google.com, omakoto@google.com, yamasani@google.com
 
 # security
 per-file KeySetHandle.java = cbrubaker@google.com, nnk@google.com
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index fce7f04..9cfd095 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -107,6 +107,7 @@
 import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.List;
 import java.util.Objects;
 
 /**
@@ -1174,9 +1175,9 @@
                     opPackageName = workChain.getAttributionTag();
                     opUid = workChain.getAttributionUid();
                 } else {
-                    opPackageName = workSource.getName(0) != null
-                            ? workSource.getName(0) : wakeLock.mPackageName;
-                    opUid = workSource.get(0);
+                    opPackageName = workSource.getPackageName(0) != null
+                            ? workSource.getPackageName(0) : wakeLock.mPackageName;
+                    opUid = workSource.getUid(0);
                 }
             } else {
                 opPackageName = wakeLock.mPackageName;
@@ -2004,13 +2005,13 @@
     private boolean wakeLockAffectsUser(WakeLock wakeLock, @UserIdInt int userId) {
         if (wakeLock.mWorkSource != null) {
             for (int k = 0; k < wakeLock.mWorkSource.size(); k++) {
-                final int uid = wakeLock.mWorkSource.get(k);
+                final int uid = wakeLock.mWorkSource.getUid(k);
                 if (userId == UserHandle.getUserId(uid)) {
                     return true;
                 }
             }
 
-            final ArrayList<WorkChain> workChains = wakeLock.mWorkSource.getWorkChains();
+            final List<WorkChain> workChains = wakeLock.mWorkSource.getWorkChains();
             if (workChains != null) {
                 for (int k = 0; k < workChains.size(); k++) {
                     final int uid = workChains.get(k).getAttributionUid();
diff --git a/services/core/java/com/android/server/recoverysystem/RecoverySystemService.java b/services/core/java/com/android/server/recoverysystem/RecoverySystemService.java
index d78aaa5..fe18fbf 100644
--- a/services/core/java/com/android/server/recoverysystem/RecoverySystemService.java
+++ b/services/core/java/com/android/server/recoverysystem/RecoverySystemService.java
@@ -27,6 +27,7 @@
 import android.os.SystemProperties;
 import android.util.Slog;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.server.SystemService;
 
 import libcore.io.IoUtils;
@@ -35,6 +36,7 @@
 import java.io.DataOutputStream;
 import java.io.FileWriter;
 import java.io.IOException;
+import java.nio.charset.StandardCharsets;
 
 /**
  * The recovery system service is responsible for coordinating recovery related
@@ -43,7 +45,7 @@
  * triggers /system/bin/uncrypt via init to de-encrypt an OTA package on the
  * /data partition so that it can be accessed under the recovery image.
  */
-public final class RecoverySystemService extends SystemService {
+public class RecoverySystemService extends IRecoverySystem.Stub {
     private static final String TAG = "RecoverySystemService";
     private static final boolean DEBUG = false;
 
@@ -51,191 +53,321 @@
     private static final String UNCRYPT_SOCKET = "uncrypt";
 
     // The init services that communicate with /system/bin/uncrypt.
-    private static final String INIT_SERVICE_UNCRYPT = "init.svc.uncrypt";
-    private static final String INIT_SERVICE_SETUP_BCB = "init.svc.setup-bcb";
-    private static final String INIT_SERVICE_CLEAR_BCB = "init.svc.clear-bcb";
-
-    private static final int SOCKET_CONNECTION_MAX_RETRY = 30;
+    @VisibleForTesting
+    static final String INIT_SERVICE_UNCRYPT = "init.svc.uncrypt";
+    @VisibleForTesting
+    static final String INIT_SERVICE_SETUP_BCB = "init.svc.setup-bcb";
+    @VisibleForTesting
+    static final String INIT_SERVICE_CLEAR_BCB = "init.svc.clear-bcb";
 
     private static final Object sRequestLock = new Object();
 
-    private Context mContext;
+    private static final int SOCKET_CONNECTION_MAX_RETRY = 30;
 
-    public RecoverySystemService(Context context) {
-        super(context);
-        mContext = context;
+    private final Injector mInjector;
+    private final Context mContext;
+
+    static class Injector {
+        protected final Context mContext;
+
+        Injector(Context context) {
+            mContext = context;
+        }
+
+        public Context getContext() {
+            return mContext;
+        }
+
+        public PowerManager getPowerManager() {
+            return (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
+        }
+
+        public String systemPropertiesGet(String key) {
+            return SystemProperties.get(key);
+        }
+
+        public void systemPropertiesSet(String key, String value) {
+            SystemProperties.set(key, value);
+        }
+
+        public boolean uncryptPackageFileDelete() {
+            return RecoverySystem.UNCRYPT_PACKAGE_FILE.delete();
+        }
+
+        public String getUncryptPackageFileName() {
+            return RecoverySystem.UNCRYPT_PACKAGE_FILE.getName();
+        }
+
+        public FileWriter getUncryptPackageFileWriter() throws IOException {
+            return new FileWriter(RecoverySystem.UNCRYPT_PACKAGE_FILE);
+        }
+
+        public UncryptSocket connectService() {
+            UncryptSocket socket = new UncryptSocket();
+            if (!socket.connectService()) {
+                socket.close();
+                return null;
+            }
+            return socket;
+        }
+
+        public void threadSleep(long millis) throws InterruptedException {
+            Thread.sleep(millis);
+        }
     }
 
-    @Override
-    public void onStart() {
-        publishBinderService(Context.RECOVERY_SERVICE, new BinderService());
+    /**
+     * Handles the lifecycle events for the RecoverySystemService.
+     */
+    public static final class Lifecycle extends SystemService {
+        public Lifecycle(Context context) {
+            super(context);
+        }
+
+        @Override
+        public void onStart() {
+            RecoverySystemService recoverySystemService = new RecoverySystemService(getContext());
+            publishBinderService(Context.RECOVERY_SERVICE, recoverySystemService);
+        }
     }
 
-    private final class BinderService extends IRecoverySystem.Stub {
-        @Override // Binder call
-        public boolean uncrypt(String filename, IRecoverySystemProgressListener listener) {
-            if (DEBUG) Slog.d(TAG, "uncrypt: " + filename);
+    private RecoverySystemService(Context context) {
+        this(new Injector(context));
+    }
 
-            synchronized (sRequestLock) {
-                mContext.enforceCallingOrSelfPermission(android.Manifest.permission.RECOVERY, null);
+    @VisibleForTesting
+    RecoverySystemService(Injector injector) {
+        mInjector = injector;
+        mContext = injector.getContext();
+    }
 
-                final boolean available = checkAndWaitForUncryptService();
-                if (!available) {
-                    Slog.e(TAG, "uncrypt service is unavailable.");
-                    return false;
-                }
+    @Override // Binder call
+    public boolean uncrypt(String filename, IRecoverySystemProgressListener listener) {
+        if (DEBUG) Slog.d(TAG, "uncrypt: " + filename);
 
-                // Write the filename into UNCRYPT_PACKAGE_FILE to be read by
-                // uncrypt.
-                RecoverySystem.UNCRYPT_PACKAGE_FILE.delete();
+        synchronized (sRequestLock) {
+            mContext.enforceCallingOrSelfPermission(android.Manifest.permission.RECOVERY, null);
 
-                try (FileWriter uncryptFile = new FileWriter(RecoverySystem.UNCRYPT_PACKAGE_FILE)) {
-                    uncryptFile.write(filename + "\n");
-                } catch (IOException e) {
-                    Slog.e(TAG, "IOException when writing \"" +
-                            RecoverySystem.UNCRYPT_PACKAGE_FILE + "\":", e);
-                    return false;
-                }
+            if (!checkAndWaitForUncryptService()) {
+                Slog.e(TAG, "uncrypt service is unavailable.");
+                return false;
+            }
 
-                // Trigger uncrypt via init.
-                SystemProperties.set("ctl.start", "uncrypt");
+            // Write the filename into uncrypt package file to be read by
+            // uncrypt.
+            mInjector.uncryptPackageFileDelete();
 
-                // Connect to the uncrypt service socket.
-                LocalSocket socket = connectService();
-                if (socket == null) {
-                    Slog.e(TAG, "Failed to connect to uncrypt socket");
-                    return false;
-                }
+            try (FileWriter uncryptFile = mInjector.getUncryptPackageFileWriter()) {
+                uncryptFile.write(filename + "\n");
+            } catch (IOException e) {
+                Slog.e(TAG, "IOException when writing \""
+                        + mInjector.getUncryptPackageFileName() + "\":", e);
+                return false;
+            }
 
-                // Read the status from the socket.
-                DataInputStream dis = null;
-                DataOutputStream dos = null;
-                try {
-                    dis = new DataInputStream(socket.getInputStream());
-                    dos = new DataOutputStream(socket.getOutputStream());
-                    int lastStatus = Integer.MIN_VALUE;
-                    while (true) {
-                        int status = dis.readInt();
-                        // Avoid flooding the log with the same message.
-                        if (status == lastStatus && lastStatus != Integer.MIN_VALUE) {
-                            continue;
-                        }
-                        lastStatus = status;
+            // Trigger uncrypt via init.
+            mInjector.systemPropertiesSet("ctl.start", "uncrypt");
 
-                        if (status >= 0 && status <= 100) {
-                            // Update status
-                            Slog.i(TAG, "uncrypt read status: " + status);
-                            if (listener != null) {
-                                try {
-                                    listener.onProgress(status);
-                                } catch (RemoteException ignored) {
-                                    Slog.w(TAG, "RemoteException when posting progress");
-                                }
-                            }
-                            if (status == 100) {
-                                Slog.i(TAG, "uncrypt successfully finished.");
-                                // Ack receipt of the final status code. uncrypt
-                                // waits for the ack so the socket won't be
-                                // destroyed before we receive the code.
-                                dos.writeInt(0);
-                                break;
-                            }
-                        } else {
-                            // Error in /system/bin/uncrypt.
-                            Slog.e(TAG, "uncrypt failed with status: " + status);
-                            // Ack receipt of the final status code. uncrypt waits
-                            // for the ack so the socket won't be destroyed before
-                            // we receive the code.
-                            dos.writeInt(0);
-                            return false;
-                        }
+            // Connect to the uncrypt service socket.
+            UncryptSocket socket = mInjector.connectService();
+            if (socket == null) {
+                Slog.e(TAG, "Failed to connect to uncrypt socket");
+                return false;
+            }
+
+            // Read the status from the socket.
+            try {
+                int lastStatus = Integer.MIN_VALUE;
+                while (true) {
+                    int status = socket.getPercentageUncrypted();
+                    // Avoid flooding the log with the same message.
+                    if (status == lastStatus && lastStatus != Integer.MIN_VALUE) {
+                        continue;
                     }
-                } catch (IOException e) {
-                    Slog.e(TAG, "IOException when reading status: ", e);
-                    return false;
-                } finally {
-                    IoUtils.closeQuietly(dis);
-                    IoUtils.closeQuietly(dos);
-                    IoUtils.closeQuietly(socket);
-                }
+                    lastStatus = status;
 
+                    if (status >= 0 && status <= 100) {
+                        // Update status
+                        Slog.i(TAG, "uncrypt read status: " + status);
+                        if (listener != null) {
+                            try {
+                                listener.onProgress(status);
+                            } catch (RemoteException ignored) {
+                                Slog.w(TAG, "RemoteException when posting progress");
+                            }
+                        }
+                        if (status == 100) {
+                            Slog.i(TAG, "uncrypt successfully finished.");
+                            // Ack receipt of the final status code. uncrypt
+                            // waits for the ack so the socket won't be
+                            // destroyed before we receive the code.
+                            socket.sendAck();
+                            break;
+                        }
+                    } else {
+                        // Error in /system/bin/uncrypt.
+                        Slog.e(TAG, "uncrypt failed with status: " + status);
+                        // Ack receipt of the final status code. uncrypt waits
+                        // for the ack so the socket won't be destroyed before
+                        // we receive the code.
+                        socket.sendAck();
+                        return false;
+                    }
+                }
+            } catch (IOException e) {
+                Slog.e(TAG, "IOException when reading status: ", e);
+                return false;
+            } finally {
+                socket.close();
+            }
+
+            return true;
+        }
+    }
+
+    @Override // Binder call
+    public boolean clearBcb() {
+        if (DEBUG) Slog.d(TAG, "clearBcb");
+        synchronized (sRequestLock) {
+            return setupOrClearBcb(false, null);
+        }
+    }
+
+    @Override // Binder call
+    public boolean setupBcb(String command) {
+        if (DEBUG) Slog.d(TAG, "setupBcb: [" + command + "]");
+        synchronized (sRequestLock) {
+            return setupOrClearBcb(true, command);
+        }
+    }
+
+    @Override // Binder call
+    public void rebootRecoveryWithCommand(String command) {
+        if (DEBUG) Slog.d(TAG, "rebootRecoveryWithCommand: [" + command + "]");
+        synchronized (sRequestLock) {
+            if (!setupOrClearBcb(true, command)) {
+                return;
+            }
+
+            // Having set up the BCB, go ahead and reboot.
+            PowerManager pm = mInjector.getPowerManager();
+            pm.reboot(PowerManager.REBOOT_RECOVERY);
+        }
+    }
+
+    /**
+     * Check if any of the init services is still running. If so, we cannot
+     * start a new uncrypt/setup-bcb/clear-bcb service right away; otherwise
+     * it may break the socket communication since init creates / deletes
+     * the socket (/dev/socket/uncrypt) on service start / exit.
+     */
+    private boolean checkAndWaitForUncryptService() {
+        for (int retry = 0; retry < SOCKET_CONNECTION_MAX_RETRY; retry++) {
+            final String uncryptService = mInjector.systemPropertiesGet(INIT_SERVICE_UNCRYPT);
+            final String setupBcbService = mInjector.systemPropertiesGet(INIT_SERVICE_SETUP_BCB);
+            final String clearBcbService = mInjector.systemPropertiesGet(INIT_SERVICE_CLEAR_BCB);
+            final boolean busy = "running".equals(uncryptService)
+                    || "running".equals(setupBcbService) || "running".equals(clearBcbService);
+            if (DEBUG) {
+                Slog.i(TAG, "retry: " + retry + " busy: " + busy
+                        + " uncrypt: [" + uncryptService + "]"
+                        + " setupBcb: [" + setupBcbService + "]"
+                        + " clearBcb: [" + clearBcbService + "]");
+            }
+
+            if (!busy) {
                 return true;
             }
-        }
 
-        @Override // Binder call
-        public boolean clearBcb() {
-            if (DEBUG) Slog.d(TAG, "clearBcb");
-            synchronized (sRequestLock) {
-                return setupOrClearBcb(false, null);
+            try {
+                mInjector.threadSleep(1000);
+            } catch (InterruptedException e) {
+                Slog.w(TAG, "Interrupted:", e);
             }
         }
 
-        @Override // Binder call
-        public boolean setupBcb(String command) {
-            if (DEBUG) Slog.d(TAG, "setupBcb: [" + command + "]");
-            synchronized (sRequestLock) {
-                return setupOrClearBcb(true, command);
-            }
-        }
+        return false;
+    }
 
-        @Override // Binder call
-        public void rebootRecoveryWithCommand(String command) {
-            if (DEBUG) Slog.d(TAG, "rebootRecoveryWithCommand: [" + command + "]");
-            synchronized (sRequestLock) {
-                if (!setupOrClearBcb(true, command)) {
-                    return;
-                }
+    private boolean setupOrClearBcb(boolean isSetup, String command) {
+        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.RECOVERY, null);
 
-                // Having set up the BCB, go ahead and reboot.
-                PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
-                pm.reboot(PowerManager.REBOOT_RECOVERY);
-            }
-        }
-
-        /**
-         * Check if any of the init services is still running. If so, we cannot
-         * start a new uncrypt/setup-bcb/clear-bcb service right away; otherwise
-         * it may break the socket communication since init creates / deletes
-         * the socket (/dev/socket/uncrypt) on service start / exit.
-         */
-        private boolean checkAndWaitForUncryptService() {
-            for (int retry = 0; retry < SOCKET_CONNECTION_MAX_RETRY; retry++) {
-                final String uncryptService = SystemProperties.get(INIT_SERVICE_UNCRYPT);
-                final String setupBcbService = SystemProperties.get(INIT_SERVICE_SETUP_BCB);
-                final String clearBcbService = SystemProperties.get(INIT_SERVICE_CLEAR_BCB);
-                final boolean busy = "running".equals(uncryptService) ||
-                        "running".equals(setupBcbService) || "running".equals(clearBcbService);
-                if (DEBUG) {
-                    Slog.i(TAG, "retry: " + retry + " busy: " + busy +
-                            " uncrypt: [" + uncryptService + "]" +
-                            " setupBcb: [" + setupBcbService + "]" +
-                            " clearBcb: [" + clearBcbService + "]");
-                }
-
-                if (!busy) {
-                    return true;
-                }
-
-                try {
-                    Thread.sleep(1000);
-                } catch (InterruptedException e) {
-                    Slog.w(TAG, "Interrupted:", e);
-                }
-            }
-
+        final boolean available = checkAndWaitForUncryptService();
+        if (!available) {
+            Slog.e(TAG, "uncrypt service is unavailable.");
             return false;
         }
 
-        private LocalSocket connectService() {
-            LocalSocket socket = new LocalSocket();
+        if (isSetup) {
+            mInjector.systemPropertiesSet("ctl.start", "setup-bcb");
+        } else {
+            mInjector.systemPropertiesSet("ctl.start", "clear-bcb");
+        }
+
+        // Connect to the uncrypt service socket.
+        UncryptSocket socket = mInjector.connectService();
+        if (socket == null) {
+            Slog.e(TAG, "Failed to connect to uncrypt socket");
+            return false;
+        }
+
+        try {
+            // Send the BCB commands if it's to setup BCB.
+            if (isSetup) {
+                socket.sendCommand(command);
+            }
+
+            // Read the status from the socket.
+            int status = socket.getPercentageUncrypted();
+
+            // Ack receipt of the status code. uncrypt waits for the ack so
+            // the socket won't be destroyed before we receive the code.
+            socket.sendAck();
+
+            if (status == 100) {
+                Slog.i(TAG, "uncrypt " + (isSetup ? "setup" : "clear")
+                        + " bcb successfully finished.");
+            } else {
+                // Error in /system/bin/uncrypt.
+                Slog.e(TAG, "uncrypt failed with status: " + status);
+                return false;
+            }
+        } catch (IOException e) {
+            Slog.e(TAG, "IOException when communicating with uncrypt:", e);
+            return false;
+        } finally {
+            socket.close();
+        }
+
+        return true;
+    }
+
+    /**
+     * Provides a wrapper for the low-level details of framing packets sent to the uncrypt
+     * socket.
+     */
+    public static class UncryptSocket {
+        private LocalSocket mLocalSocket;
+        private DataInputStream mInputStream;
+        private DataOutputStream mOutputStream;
+
+        /**
+         * Attempt to connect to the uncrypt service. Connection will be retried for up to
+         * {@link #SOCKET_CONNECTION_MAX_RETRY} times. If the connection is unsuccessful, the
+         * socket will be closed. If the connection is successful, the connection must be closed
+         * by the caller.
+         *
+         * @return true if connection was successful, false if unsuccessful
+         */
+        public boolean connectService() {
+            mLocalSocket = new LocalSocket();
             boolean done = false;
             // The uncrypt socket will be created by init upon receiving the
             // service request. It may not be ready by this point. So we will
             // keep retrying until success or reaching timeout.
             for (int retry = 0; retry < SOCKET_CONNECTION_MAX_RETRY; retry++) {
                 try {
-                    socket.connect(new LocalSocketAddress(UNCRYPT_SOCKET,
+                    mLocalSocket.connect(new LocalSocketAddress(UNCRYPT_SOCKET,
                             LocalSocketAddress.Namespace.RESERVED));
                     done = true;
                     break;
@@ -249,71 +381,69 @@
             }
             if (!done) {
                 Slog.e(TAG, "Timed out connecting to uncrypt socket");
-                return null;
-            }
-            return socket;
-        }
-
-        private boolean setupOrClearBcb(boolean isSetup, String command) {
-            mContext.enforceCallingOrSelfPermission(android.Manifest.permission.RECOVERY, null);
-
-            final boolean available = checkAndWaitForUncryptService();
-            if (!available) {
-                Slog.e(TAG, "uncrypt service is unavailable.");
+                close();
                 return false;
             }
 
-            if (isSetup) {
-                SystemProperties.set("ctl.start", "setup-bcb");
-            } else {
-                SystemProperties.set("ctl.start", "clear-bcb");
-            }
-
-            // Connect to the uncrypt service socket.
-            LocalSocket socket = connectService();
-            if (socket == null) {
-                Slog.e(TAG, "Failed to connect to uncrypt socket");
-                return false;
-            }
-
-            DataInputStream dis = null;
-            DataOutputStream dos = null;
             try {
-                dis = new DataInputStream(socket.getInputStream());
-                dos = new DataOutputStream(socket.getOutputStream());
-
-                // Send the BCB commands if it's to setup BCB.
-                if (isSetup) {
-                    byte[] cmdUtf8 = command.getBytes("UTF-8");
-                    dos.writeInt(cmdUtf8.length);
-                    dos.write(cmdUtf8, 0, cmdUtf8.length);
-                }
-
-                // Read the status from the socket.
-                int status = dis.readInt();
-
-                // Ack receipt of the status code. uncrypt waits for the ack so
-                // the socket won't be destroyed before we receive the code.
-                dos.writeInt(0);
-
-                if (status == 100) {
-                    Slog.i(TAG, "uncrypt " + (isSetup ? "setup" : "clear") +
-                            " bcb successfully finished.");
-                } else {
-                    // Error in /system/bin/uncrypt.
-                    Slog.e(TAG, "uncrypt failed with status: " + status);
-                    return false;
-                }
+                mInputStream = new DataInputStream(mLocalSocket.getInputStream());
+                mOutputStream = new DataOutputStream(mLocalSocket.getOutputStream());
             } catch (IOException e) {
-                Slog.e(TAG, "IOException when communicating with uncrypt:", e);
+                close();
                 return false;
-            } finally {
-                IoUtils.closeQuietly(dis);
-                IoUtils.closeQuietly(dos);
-                IoUtils.closeQuietly(socket);
             }
 
             return true;
         }
+
+        /**
+         * Sends a command to the uncrypt service.
+         *
+         * @param command command to send to the uncrypt service
+         * @throws IOException if the socket is closed or there was an error writing to the socket
+         */
+        public void sendCommand(String command) throws IOException {
+            if (mLocalSocket.isClosed()) {
+                throw new IOException("socket is closed");
+            }
+
+            byte[] cmdUtf8 = command.getBytes(StandardCharsets.UTF_8);
+            mOutputStream.writeInt(cmdUtf8.length);
+            mOutputStream.write(cmdUtf8, 0, cmdUtf8.length);
+        }
+
+        /**
+         * Reads the status from the uncrypt service which is usually represented as a percentage.
+         * @return an integer representing the percentage completed
+         * @throws IOException if the socket was closed or there was an error reading the socket
+         */
+        public int getPercentageUncrypted() throws IOException {
+            if (mLocalSocket.isClosed()) {
+                throw new IOException("socket is closed");
+            }
+
+            return mInputStream.readInt();
+        }
+
+        /**
+         * Sends a confirmation to the uncrypt service.
+         * @throws IOException if the socket was closed or there was an error writing to the socket
+         */
+        public void sendAck() throws IOException {
+            if (mLocalSocket.isClosed()) {
+                throw new IOException("socket is closed");
+            }
+
+            mOutputStream.writeInt(0);
+        }
+
+        /**
+         * Closes the socket and all underlying data streams.
+         */
+        public void close() {
+            IoUtils.closeQuietly(mInputStream);
+            IoUtils.closeQuietly(mOutputStream);
+            IoUtils.closeQuietly(mLocalSocket);
+        }
     }
 }
diff --git a/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java b/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java
index 11f09d0..a0b878c 100644
--- a/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java
+++ b/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java
@@ -92,12 +92,13 @@
         // Refer to WindowManagerService#applyImeVisibility(token, false).
         // If IMMS's imeTarget is child of DisplayContent's imeTarget and child window
         // is above the parent, we will consider it as the same target for now.
+        // Also, if imeTarget is closing, it would be considered as outdated target.
         // TODO(b/139861270): Remove the child & sublayer check once IMMS is aware of
         //  actual IME target.
-        return mImeTargetFromIme == mDisplayContent.mInputMethodTarget
-                || (mDisplayContent.mInputMethodTarget.getParentWindow() == mImeTargetFromIme
-                        && mDisplayContent.mInputMethodTarget.mSubLayer
-                                > mImeTargetFromIme.mSubLayer);
+        final WindowState dcTarget = mDisplayContent.mInputMethodTarget;
+        return (!dcTarget.isClosing() && mImeTargetFromIme == dcTarget)
+                || (dcTarget.getParentWindow() == mImeTargetFromIme
+                        && dcTarget.mSubLayer > mImeTargetFromIme.mSubLayer);
     }
 
 }
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 2d6d5f4..a42f2e1 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -143,6 +143,7 @@
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManagerInternal;
 import android.content.res.Configuration;
+import android.content.res.TypedArray;
 import android.database.ContentObserver;
 import android.graphics.Bitmap;
 import android.graphics.Insets;
@@ -1247,6 +1248,20 @@
 
         LocalServices.addService(WindowManagerInternal.class, new LocalService());
         mEmbeddedWindowController = new EmbeddedWindowController(mGlobalLock);
+        setGlobalShadowSettings();
+    }
+
+    private void setGlobalShadowSettings() {
+        final TypedArray a = mContext.obtainStyledAttributes(null, R.styleable.Lighting, 0, 0);
+        float lightY = a.getDimension(R.styleable.Lighting_lightY, 0);
+        float lightZ = a.getDimension(R.styleable.Lighting_lightZ, 0);
+        float lightRadius = a.getDimension(R.styleable.Lighting_lightRadius, 0);
+        float ambientShadowAlpha = a.getFloat(R.styleable.Lighting_ambientShadowAlpha, 0);
+        float spotShadowAlpha = a.getFloat(R.styleable.Lighting_spotShadowAlpha, 0);
+        float[] ambientColor = {0.f, 0.f, 0.f, ambientShadowAlpha};
+        float[] spotColor = {0.f, 0.f, 0.f, spotShadowAlpha};
+        SurfaceControl.setGlobalShadowSettings(ambientColor, spotColor, lightY, lightZ,
+                lightRadius);
     }
 
     /**
diff --git a/services/coverage/Android.bp b/services/coverage/Android.bp
index 16c9c1b..e4f5464 100644
--- a/services/coverage/Android.bp
+++ b/services/coverage/Android.bp
@@ -1,5 +1,12 @@
+filegroup {
+    name: "services.coverage-sources",
+    srcs: ["java/**/*.java"],
+    path: "java",
+    visibility: ["//frameworks/base/services"],
+}
+
 java_library_static {
     name: "services.coverage",
-    srcs: ["java/**/*.java"],
+    srcs: [":services.coverage-sources"],
     libs: ["jacocoagent"],
 }
diff --git a/services/devicepolicy/Android.bp b/services/devicepolicy/Android.bp
index bffa44e..380ee94 100644
--- a/services/devicepolicy/Android.bp
+++ b/services/devicepolicy/Android.bp
@@ -1,6 +1,13 @@
+filegroup {
+    name: "services.devicepolicy-sources",
+    srcs: ["java/**/*.java"],
+    path: "java",
+    visibility: ["//frameworks/base/services"],
+}
+
 java_library_static {
     name: "services.devicepolicy",
-    srcs: ["java/**/*.java"],
+    srcs: [":services.devicepolicy-sources"],
 
     libs: [
         "services.core",
@@ -15,4 +22,4 @@
 platform_compat_config {
     name: "services-devicepolicy-platform-compat-config",
     src: ":services.devicepolicy",
-}
\ No newline at end of file
+}
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index f1ed1d9..39d840f 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -281,7 +281,8 @@
             "com.android.server.DeviceIdleController";
     private static final String BLOB_STORE_MANAGER_SERVICE_CLASS =
             "com.android.server.blob.BlobStoreManagerService";
-
+    private static final String APP_SEARCH_MANAGER_SERVICE_CLASS =
+            "com.android.server.appsearch.AppSearchManagerService";
     private static final String PERSISTENT_DATA_BLOCK_PROP = "ro.frp.pst";
 
     private static final String UNCRYPT_PACKAGE_FILE = "/cache/recovery/uncrypt_file";
@@ -704,7 +705,7 @@
 
         // Bring up recovery system in case a rescue party needs a reboot
         t.traceBegin("StartRecoverySystemService");
-        mSystemServiceManager.startService(RecoverySystemService.class);
+        mSystemServiceManager.startService(RecoverySystemService.Lifecycle.class);
         t.traceEnd();
 
         // Now that we have the bare essentials of the OS up and running, take
@@ -2023,6 +2024,10 @@
         mSystemServiceManager.startBootPhase(t, SystemService.PHASE_DEVICE_SPECIFIC_SERVICES_READY);
         t.traceEnd();
 
+        t.traceBegin("AppSearchManagerService");
+        mSystemServiceManager.startService(APP_SEARCH_MANAGER_SERVICE_CLASS);
+        t.traceEnd();
+
         // These are needed to propagate to the runnable below.
         final NetworkManagementService networkManagementF = networkManagement;
         final NetworkStatsService networkStatsF = networkStats;
diff --git a/services/midi/Android.bp b/services/midi/Android.bp
index 3745e89..20e0083 100644
--- a/services/midi/Android.bp
+++ b/services/midi/Android.bp
@@ -1,5 +1,12 @@
+filegroup {
+    name: "services.midi-sources",
+    srcs: ["java/**/*.java"],
+    path: "java",
+    visibility: ["//frameworks/base/services"],
+}
+
 java_library_static {
     name: "services.midi",
-    srcs: ["java/**/*.java"],
+    srcs: [":services.midi-sources"],
     libs: ["services.core"],
 }
diff --git a/services/net/Android.bp b/services/net/Android.bp
index c56ecd6..42c69e0 100644
--- a/services/net/Android.bp
+++ b/services/net/Android.bp
@@ -1,8 +1,15 @@
+filegroup {
+    name: "services.net-sources",
+    srcs: ["java/**/*.java"],
+    path: "java",
+    visibility: ["//frameworks/base/services"],
+}
+
 java_library_static {
     name: "services.net",
     srcs: [
         ":tethering-servicesnet-srcs",
-        "java/**/*.java",
+        ":services.net-sources",
     ],
     static_libs: [
         "dnsresolver_aidl_interface-V2-java",
@@ -20,6 +27,8 @@
         "java/android/net/shared/*.java",
         "java/android/net/netlink/*.java",
     ],
+    path: "java",
+    visibility: ["//packages/modules/NetworkStack"],
 }
 
 filegroup {
@@ -35,4 +44,5 @@
         "java/android/net/util/NetworkConstants.java",
         "java/android/net/util/SharedLog.java"
     ],
+    visibility: ["//frameworks/base/packages/Tethering"],
 }
diff --git a/services/print/Android.bp b/services/print/Android.bp
index 80a8c75..aad24d7 100644
--- a/services/print/Android.bp
+++ b/services/print/Android.bp
@@ -1,5 +1,12 @@
+filegroup {
+    name: "services.print-sources",
+    srcs: ["java/**/*.java"],
+    path: "java",
+    visibility: ["//frameworks/base/services"],
+}
+
 java_library_static {
     name: "services.print",
-    srcs: ["java/**/*.java"],
+    srcs: [":services.print-sources"],
     libs: ["services.core"],
 }
diff --git a/services/restrictions/Android.bp b/services/restrictions/Android.bp
index 979e891..805858f 100644
--- a/services/restrictions/Android.bp
+++ b/services/restrictions/Android.bp
@@ -1,5 +1,12 @@
+filegroup {
+    name: "services.restrictions-sources",
+    srcs: ["java/**/*.java"],
+    path: "java",
+    visibility: ["//frameworks/base/services"],
+}
+
 java_library_static {
     name: "services.restrictions",
-    srcs: ["java/**/*.java"],
+    srcs: [":services.restrictions-sources"],
     libs: ["services.core"],
 }
diff --git a/services/robotests/backup/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java b/services/robotests/backup/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java
index 6a90d0b..2510b60 100644
--- a/services/robotests/backup/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java
+++ b/services/robotests/backup/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java
@@ -713,7 +713,7 @@
                     // Verify has set work source and hasn't unset yet.
                     verify(mBackupManagerService)
                             .setWorkSource(
-                                    argThat(workSource -> workSource.get(0) == PACKAGE_1.uid));
+                                    argThat(workSource -> workSource.getUid(0) == PACKAGE_1.uid));
                     verify(mBackupManagerService, never()).setWorkSource(null);
                 });
         KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
diff --git a/services/systemcaptions/Android.bp b/services/systemcaptions/Android.bp
index 4e190b6..1ce3e66 100644
--- a/services/systemcaptions/Android.bp
+++ b/services/systemcaptions/Android.bp
@@ -1,5 +1,12 @@
+filegroup {
+    name: "services.systemcaptions-sources",
+    srcs: ["java/**/*.java"],
+    path: "java",
+    visibility: ["//frameworks/base/services"],
+}
+
 java_library_static {
     name: "services.systemcaptions",
-    srcs: ["java/**/*.java"],
+    srcs: [":services.systemcaptions-sources"],
     libs: ["services.core"],
 }
diff --git a/services/tests/servicestests/Android.bp b/services/tests/servicestests/Android.bp
index 30ccb71..52fb69e 100644
--- a/services/tests/servicestests/Android.bp
+++ b/services/tests/servicestests/Android.bp
@@ -8,6 +8,7 @@
     // Include all test java files.
     srcs: [
         "src/**/*.java",
+        "src/**/*.kt",
 
         "aidl/com/android/servicestests/aidl/INetworkStateObserver.aidl",
         "aidl/com/android/servicestests/aidl/ICmdReceiverService.aidl",
diff --git a/services/tests/servicestests/src/com/android/server/om/OverlayActorEnforcerTests.kt b/services/tests/servicestests/src/com/android/server/om/OverlayActorEnforcerTests.kt
new file mode 100644
index 0000000..233e16c
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/om/OverlayActorEnforcerTests.kt
@@ -0,0 +1,197 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.om
+
+import android.content.om.OverlayInfo
+import android.content.om.OverlayableInfo
+import android.content.pm.ApplicationInfo
+import android.content.pm.PackageInfo
+import android.os.Process
+import org.junit.Rule
+import org.junit.Test
+import org.junit.rules.ExpectedException
+
+class OverlayActorEnforcerTests {
+    companion object {
+        private const val NAMESPACE = "testnamespace"
+        private const val ACTOR_NAME = "testactor"
+        private const val ACTOR_PKG_NAME = "com.test.actor.one"
+        private const val OVERLAYABLE_NAME = "TestOverlayable"
+        private const val UID = 3536
+        private const val USER_ID = 55
+    }
+
+    @get:Rule
+    val expectedException = ExpectedException.none()!!
+
+    @Test
+    fun isRoot() {
+        verify(callingUid = Process.ROOT_UID)
+    }
+
+    @Test(expected = SecurityException::class)
+    fun isShell() {
+        verify(callingUid = Process.SHELL_UID)
+    }
+
+    @Test
+    fun isSystem() {
+        verify(callingUid = Process.SYSTEM_UID)
+    }
+
+    @Test(expected = SecurityException::class)
+    fun noOverlayable_noTarget() {
+        verify(targetOverlayableName = null)
+    }
+
+    @Test
+    fun noOverlayable_noTarget_withPermission() {
+        verify(targetOverlayableName = null, hasPermission = true)
+    }
+
+    @Test(expected = SecurityException::class)
+    fun noOverlayable_withTarget() {
+        verify(targetOverlayableName = OVERLAYABLE_NAME)
+    }
+
+    @Test(expected = SecurityException::class)
+    fun withOverlayable_noTarget() {
+        verify(
+                targetOverlayableName = null,
+                overlayableInfo = OverlayableInfo(OVERLAYABLE_NAME, null)
+        )
+    }
+
+    @Test(expected = SecurityException::class)
+    fun withOverlayable_noActor() {
+        verify(
+                overlayableInfo = OverlayableInfo(OVERLAYABLE_NAME, null)
+        )
+    }
+
+    @Test
+    fun withOverlayable_noActor_withPermission() {
+        verify(
+                hasPermission = true,
+                overlayableInfo = OverlayableInfo(OVERLAYABLE_NAME, null)
+        )
+    }
+
+    @Test(expected = SecurityException::class)
+    fun withOverlayable_withActor_notActor() {
+        verify(
+                isActor = false,
+                overlayableInfo = OverlayableInfo(OVERLAYABLE_NAME,
+                        "overlay://$NAMESPACE/$ACTOR_NAME")
+        )
+    }
+
+    @Test(expected = SecurityException::class)
+    fun withOverlayable_withActor_isActor_notPreInstalled() {
+        verify(
+                isActor = true,
+                isPreInstalled = false,
+                overlayableInfo = OverlayableInfo(OVERLAYABLE_NAME,
+                        "overlay://$NAMESPACE/$ACTOR_NAME")
+        )
+    }
+
+    @Test
+    fun withOverlayable_withActor_isActor_isPreInstalled() {
+        verify(
+                isActor = true,
+                isPreInstalled = true,
+                overlayableInfo = OverlayableInfo(OVERLAYABLE_NAME,
+                        "overlay://$NAMESPACE/$ACTOR_NAME")
+        )
+    }
+
+    @Test(expected = SecurityException::class)
+    fun withOverlayable_invalidActor() {
+        verify(
+                isActor = true,
+                isPreInstalled = true,
+                overlayableInfo = OverlayableInfo(OVERLAYABLE_NAME, "notValidActor")
+        )
+    }
+
+    private fun verify(
+        isActor: Boolean = false,
+        isPreInstalled: Boolean = false,
+        hasPermission: Boolean = false,
+        overlayableInfo: OverlayableInfo? = null,
+        callingUid: Int = UID,
+        targetOverlayableName: String? = OVERLAYABLE_NAME
+    ) {
+        val callback = MockCallback(
+                isActor = isActor,
+                isPreInstalled = isPreInstalled,
+                hasPermission = hasPermission,
+                overlayableInfo = overlayableInfo
+        )
+
+        val overlayInfo = overlayInfo(targetOverlayableName)
+        OverlayActorEnforcer(callback)
+                .enforceActor(overlayInfo, "test", callingUid, USER_ID)
+    }
+
+    private fun overlayInfo(targetOverlayableName: String?) = OverlayInfo("com.test.overlay",
+            "com.test.target", targetOverlayableName, null, "/path", OverlayInfo.STATE_UNKNOWN, 0,
+            0, false)
+
+    private class MockCallback(
+        private val isActor: Boolean = false,
+        private val isPreInstalled: Boolean = false,
+        private val hasPermission: Boolean = false,
+        private val overlayableInfo: OverlayableInfo? = null,
+        private vararg val packageNames: String = arrayOf("com.test.actor.one")
+    ) : OverlayActorEnforcer.VerifyCallback {
+
+        override fun getNamedActors() = if (isActor) {
+            mapOf(NAMESPACE to mapOf(ACTOR_NAME to ACTOR_PKG_NAME))
+        } else {
+            emptyMap()
+        }
+
+        override fun getOverlayableForTarget(
+            packageName: String,
+            targetOverlayableName: String?,
+            userId: Int
+        ) = overlayableInfo
+
+        override fun getPackagesForUid(uid: Int) = when (uid) {
+            UID -> packageNames
+            else -> null
+        }
+
+        override fun getPackageInfo(packageName: String, userId: Int) = PackageInfo().apply {
+            applicationInfo = ApplicationInfo().apply {
+                flags = if (isPreInstalled) ApplicationInfo.FLAG_SYSTEM else 0
+            }
+        }
+
+        override fun doesTargetDefineOverlayable(targetPackageName: String?, userId: Int): Boolean {
+            return overlayableInfo != null
+        }
+
+        override fun enforcePermission(permission: String?, message: String?) {
+            if (!hasPermission) {
+                throw SecurityException()
+            }
+        }
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/recoverysystem/RecoverySystemServiceTest.java b/services/tests/servicestests/src/com/android/server/recoverysystem/RecoverySystemServiceTest.java
new file mode 100644
index 0000000..1f312bf
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/recoverysystem/RecoverySystemServiceTest.java
@@ -0,0 +1,197 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.recoverysystem;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.os.Handler;
+import android.os.IPowerManager;
+import android.os.IRecoverySystemProgressListener;
+import android.os.Looper;
+import android.os.PowerManager;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.FileWriter;
+
+/**
+ * atest FrameworksServicesTests:RecoverySystemServiceTest
+ */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class RecoverySystemServiceTest {
+    private RecoverySystemService mRecoverySystemService;
+    private RecoverySystemServiceTestable.FakeSystemProperties mSystemProperties;
+    private RecoverySystemService.UncryptSocket mUncryptSocket;
+    private Context mContext;
+    private IPowerManager mIPowerManager;
+    private FileWriter mUncryptUpdateFileWriter;
+
+    @Before
+    public void setup() {
+        mContext = mock(Context.class);
+        mSystemProperties = new RecoverySystemServiceTestable.FakeSystemProperties();
+        mUncryptSocket = mock(RecoverySystemService.UncryptSocket.class);
+        mUncryptUpdateFileWriter = mock(FileWriter.class);
+
+        Looper looper = InstrumentationRegistry.getContext().getMainLooper();
+        mIPowerManager = mock(IPowerManager.class);
+        PowerManager powerManager = new PowerManager(mock(Context.class), mIPowerManager,
+                new Handler(looper));
+
+        mRecoverySystemService = new RecoverySystemServiceTestable(mContext, mSystemProperties,
+                powerManager, mUncryptUpdateFileWriter, mUncryptSocket);
+    }
+
+    @Test
+    public void clearBcb_success() throws Exception {
+        doNothing().when(mContext).enforceCallingOrSelfPermission(
+                eq(android.Manifest.permission.RECOVERY), any());
+        when(mUncryptSocket.getPercentageUncrypted()).thenReturn(100);
+
+        assertThat(mRecoverySystemService.clearBcb(), is(true));
+
+        assertThat(mSystemProperties.getCtlStart(), is("clear-bcb"));
+        verify(mUncryptSocket).sendAck();
+        verify(mUncryptSocket).close();
+    }
+
+    @Test
+    public void clearBcb_uncrypt_failure() throws Exception {
+        doNothing().when(mContext).enforceCallingOrSelfPermission(
+                eq(android.Manifest.permission.RECOVERY), any());
+        when(mUncryptSocket.getPercentageUncrypted()).thenReturn(0);
+
+        assertThat(mRecoverySystemService.clearBcb(), is(false));
+
+        assertThat(mSystemProperties.getCtlStart(), is("clear-bcb"));
+        verify(mUncryptSocket).sendAck();
+        verify(mUncryptSocket).close();
+    }
+
+    @Test(expected = SecurityException.class)
+    public void clearBcb_noPerm() {
+        doThrow(SecurityException.class).when(mContext).enforceCallingOrSelfPermission(
+                eq(android.Manifest.permission.RECOVERY), any());
+        mRecoverySystemService.clearBcb();
+    }
+
+    @Test
+    public void setupBcb_success() throws Exception {
+        doNothing().when(mContext).enforceCallingOrSelfPermission(
+                eq(android.Manifest.permission.RECOVERY), any());
+        when(mUncryptSocket.getPercentageUncrypted()).thenReturn(100);
+
+        assertThat(mRecoverySystemService.setupBcb("foo"), is(true));
+
+        assertThat(mSystemProperties.getCtlStart(), is("setup-bcb"));
+        verify(mUncryptSocket).sendCommand("foo");
+        verify(mUncryptSocket).sendAck();
+        verify(mUncryptSocket).close();
+    }
+
+    @Test
+    public void setupBcb_uncrypt_failure() throws Exception {
+        doNothing().when(mContext).enforceCallingOrSelfPermission(
+                eq(android.Manifest.permission.RECOVERY), any());
+        when(mUncryptSocket.getPercentageUncrypted()).thenReturn(0);
+
+        assertThat(mRecoverySystemService.setupBcb("foo"), is(false));
+
+        assertThat(mSystemProperties.getCtlStart(), is("setup-bcb"));
+        verify(mUncryptSocket).sendCommand("foo");
+        verify(mUncryptSocket).sendAck();
+        verify(mUncryptSocket).close();
+    }
+
+    @Test(expected = SecurityException.class)
+    public void setupBcb_noPerm() {
+        doThrow(SecurityException.class).when(mContext).enforceCallingOrSelfPermission(
+                eq(android.Manifest.permission.RECOVERY), any());
+        mRecoverySystemService.setupBcb("foo");
+    }
+
+    @Test
+    public void rebootRecoveryWithCommand_success() throws Exception {
+        doNothing().when(mContext).enforceCallingOrSelfPermission(
+                eq(android.Manifest.permission.RECOVERY), any());
+        when(mUncryptSocket.getPercentageUncrypted()).thenReturn(100);
+
+        mRecoverySystemService.rebootRecoveryWithCommand("foo");
+
+        assertThat(mSystemProperties.getCtlStart(), is("setup-bcb"));
+        verify(mUncryptSocket).sendCommand("foo");
+        verify(mUncryptSocket).sendAck();
+        verify(mUncryptSocket).close();
+        verify(mIPowerManager).reboot(anyBoolean(), eq("recovery"), anyBoolean());
+    }
+
+    @Test
+    public void rebootRecoveryWithCommand_failure() throws Exception {
+        doNothing().when(mContext).enforceCallingOrSelfPermission(
+                eq(android.Manifest.permission.RECOVERY), any());
+        when(mUncryptSocket.getPercentageUncrypted()).thenReturn(0);
+
+        mRecoverySystemService.rebootRecoveryWithCommand("foo");
+
+        assertThat(mSystemProperties.getCtlStart(), is("setup-bcb"));
+        verify(mUncryptSocket).sendCommand("foo");
+        verify(mUncryptSocket).sendAck();
+        verify(mUncryptSocket).close();
+        verifyNoMoreInteractions(mIPowerManager);
+    }
+
+    @Test(expected = SecurityException.class)
+    public void rebootRecoveryWithCommand_noPerm() {
+        doThrow(SecurityException.class).when(mContext).enforceCallingOrSelfPermission(
+                eq(android.Manifest.permission.RECOVERY), any());
+        mRecoverySystemService.rebootRecoveryWithCommand("foo");
+    }
+
+    @Test
+    public void uncrypt_success() throws Exception {
+        doNothing().when(mContext).enforceCallingOrSelfPermission(
+                eq(android.Manifest.permission.RECOVERY), any());
+        when(mUncryptSocket.getPercentageUncrypted()).thenReturn(0, 5, 25, 50, 90, 99, 100);
+
+        IRecoverySystemProgressListener listener = mock(IRecoverySystemProgressListener.class);
+        assertThat(mRecoverySystemService.uncrypt("foo.zip", listener), is(true));
+
+        assertThat(mSystemProperties.getCtlStart(), is("uncrypt"));
+        verify(mUncryptSocket, times(7)).getPercentageUncrypted();
+        verify(mUncryptSocket).sendAck();
+        verify(mUncryptSocket).close();
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/recoverysystem/RecoverySystemServiceTestable.java b/services/tests/servicestests/src/com/android/server/recoverysystem/RecoverySystemServiceTestable.java
new file mode 100644
index 0000000..a986b71
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/recoverysystem/RecoverySystemServiceTestable.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.recoverysystem;
+
+import android.content.Context;
+import android.os.PowerManager;
+
+import java.io.FileWriter;
+
+public class RecoverySystemServiceTestable extends RecoverySystemService {
+    private static class MockInjector extends RecoverySystemService.Injector {
+        private final FakeSystemProperties mSystemProperties;
+        private final PowerManager mPowerManager;
+        private final FileWriter mUncryptPackageFileWriter;
+        private final UncryptSocket mUncryptSocket;
+
+        MockInjector(Context context, FakeSystemProperties systemProperties,
+                PowerManager powerManager, FileWriter uncryptPackageFileWriter,
+                UncryptSocket uncryptSocket) {
+            super(context);
+            mSystemProperties = systemProperties;
+            mPowerManager = powerManager;
+            mUncryptPackageFileWriter = uncryptPackageFileWriter;
+            mUncryptSocket = uncryptSocket;
+        }
+
+        @Override
+        public PowerManager getPowerManager() {
+            return mPowerManager;
+        }
+
+        @Override
+        public String systemPropertiesGet(String key) {
+            return mSystemProperties.get(key);
+        }
+
+        @Override
+        public void systemPropertiesSet(String key, String value) {
+            mSystemProperties.set(key, value);
+        }
+
+        @Override
+        public boolean uncryptPackageFileDelete() {
+            return true;
+        }
+
+        @Override
+        public String getUncryptPackageFileName() {
+            return "mock-file.txt";
+        }
+
+        @Override
+        public FileWriter getUncryptPackageFileWriter() {
+            return mUncryptPackageFileWriter;
+        }
+
+        @Override
+        public UncryptSocket connectService() {
+            return mUncryptSocket;
+        }
+
+        @Override
+        public void threadSleep(long millis) {
+        }
+    }
+
+    RecoverySystemServiceTestable(Context context, FakeSystemProperties systemProperties,
+            PowerManager powerManager, FileWriter uncryptPackageFileWriter,
+            UncryptSocket uncryptSocket) {
+        super(new MockInjector(context, systemProperties, powerManager, uncryptPackageFileWriter,
+                uncryptSocket));
+    }
+
+    public static class FakeSystemProperties {
+        private String mCtlStart = null;
+
+        public String get(String key) {
+            if (RecoverySystemService.INIT_SERVICE_UNCRYPT.equals(key)
+                    || RecoverySystemService.INIT_SERVICE_SETUP_BCB.equals(key)
+                    || RecoverySystemService.INIT_SERVICE_CLEAR_BCB.equals(key)) {
+                return null;
+            } else {
+                throw new IllegalArgumentException("unexpected test key: " + key);
+            }
+        }
+
+        public void set(String key, String value) {
+            if ("ctl.start".equals(key)) {
+                mCtlStart = value;
+            } else {
+                throw new IllegalArgumentException("unexpected test key: " + key);
+            }
+        }
+
+        public String getCtlStart() {
+            return mCtlStart;
+        }
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigNamedActorTest.kt b/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigNamedActorTest.kt
new file mode 100644
index 0000000..b7199d4
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigNamedActorTest.kt
@@ -0,0 +1,232 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.systemconfig
+
+import android.content.Context
+import androidx.test.InstrumentationRegistry
+import com.android.server.SystemConfig
+import com.google.common.truth.Truth.assertThat
+import org.junit.Rule
+import org.junit.Test
+import org.junit.rules.ExpectedException
+import org.junit.rules.TemporaryFolder
+
+class SystemConfigNamedActorTest {
+
+    companion object {
+        private const val NAMESPACE_TEST = "someTestNamespace"
+        private const val NAMESPACE_ANDROID = "android"
+        private const val ACTOR_ONE = "iconShaper"
+        private const val ACTOR_TWO = "colorChanger"
+        private const val PACKAGE_ONE = "com.test.actor.one"
+        private const val PACKAGE_TWO = "com.test.actor.two"
+    }
+
+    private val context: Context = InstrumentationRegistry.getContext()
+
+    @get:Rule
+    val tempFolder = TemporaryFolder(context.filesDir)
+
+    @get:Rule
+    val expected = ExpectedException.none()
+
+    private var uniqueCounter = 0
+
+    @Test
+    fun twoUnique() {
+        """
+            <config>
+                <named-actor
+                    namespace="$NAMESPACE_TEST"
+                    name="$ACTOR_ONE"
+                    package="$PACKAGE_ONE"
+                    />
+                <named-actor
+                    namespace="$NAMESPACE_TEST"
+                    name="$ACTOR_TWO"
+                    package="$PACKAGE_TWO"
+                    />
+            </config>
+        """.write()
+
+        assertPermissions().containsExactlyEntriesIn(
+                mapOf(
+                        NAMESPACE_TEST to mapOf(
+                            ACTOR_ONE to PACKAGE_ONE,
+                            ACTOR_TWO to PACKAGE_TWO
+                        )
+                )
+        )
+    }
+
+    @Test
+    fun twoSamePackage() {
+        """
+            <config>
+                <named-actor
+                    namespace="$NAMESPACE_TEST"
+                    name="$ACTOR_ONE"
+                    package="$PACKAGE_ONE"
+                    />
+                <named-actor
+                    namespace="$NAMESPACE_TEST"
+                    name="$ACTOR_TWO"
+                    package="$PACKAGE_ONE"
+                    />
+            </config>
+        """.write()
+
+        assertPermissions().containsExactlyEntriesIn(
+                mapOf(
+                        NAMESPACE_TEST to mapOf(
+                            ACTOR_ONE to PACKAGE_ONE,
+                            ACTOR_TWO to PACKAGE_ONE
+                        )
+                )
+        )
+    }
+
+    @Test
+    fun missingNamespace() {
+        """
+            <config>
+                <named-actor
+                    name="$ACTOR_ONE"
+                    package="$PACKAGE_ONE"
+                    />
+                <named-actor
+                    namespace="$NAMESPACE_TEST"
+                    name="$ACTOR_TWO"
+                    package="$PACKAGE_TWO"
+                    />
+            </config>
+        """.write()
+
+        assertPermissions().containsExactlyEntriesIn(
+                mapOf(
+                        NAMESPACE_TEST to mapOf(
+                                ACTOR_TWO to PACKAGE_TWO
+                        )
+                )
+        )
+    }
+
+    @Test
+    fun missingName() {
+        """
+            <config>
+                <named-actor
+                    namespace="$NAMESPACE_TEST"
+                    package="$PACKAGE_ONE"
+                    />
+                <named-actor
+                    namespace="$NAMESPACE_TEST"
+                    name="$ACTOR_TWO"
+                    package="$PACKAGE_TWO"
+                    />
+            </config>
+        """.write()
+
+        assertPermissions().containsExactlyEntriesIn(
+                mapOf(
+                        NAMESPACE_TEST to mapOf(
+                                ACTOR_TWO to PACKAGE_TWO
+                        )
+                )
+        )
+    }
+
+    @Test
+    fun missingPackage() {
+        """
+            <config>
+                <named-actor
+                    namespace="$NAMESPACE_TEST"
+                    name="$ACTOR_ONE"
+                    />
+                <named-actor
+                    namespace="$NAMESPACE_TEST"
+                    name="$ACTOR_TWO"
+                    package="$PACKAGE_TWO"
+                    />
+            </config>
+        """.write()
+
+        assertPermissions().containsExactlyEntriesIn(
+                mapOf(
+                        NAMESPACE_TEST to mapOf(
+                                ACTOR_TWO to PACKAGE_TWO
+                        )
+                )
+        )
+    }
+
+    @Test
+    fun androidNamespaceThrows() {
+        """
+            <config>
+                <named-actor
+                    namespace="$NAMESPACE_TEST"
+                    name="$ACTOR_ONE"
+                    package="$PACKAGE_ONE"
+                    />
+                <named-actor
+                    namespace="$NAMESPACE_ANDROID"
+                    name="$ACTOR_ONE"
+                    package="$PACKAGE_ONE"
+                    />
+            </config>
+        """.write()
+
+        expected.expect(IllegalStateException::class.java)
+        expected.expectMessage("Defining $ACTOR_ONE as $PACKAGE_ONE " +
+                "for the android namespace is not allowed")
+
+        assertPermissions()
+    }
+
+    @Test
+    fun duplicateActorNameThrows() {
+        """
+            <config>
+                <named-actor
+                    namespace="$NAMESPACE_TEST"
+                    name="$ACTOR_ONE"
+                    package="$PACKAGE_ONE"
+                    />
+                <named-actor
+                    namespace="$NAMESPACE_TEST"
+                    name="$ACTOR_ONE"
+                    package="$PACKAGE_TWO"
+                    />
+            </config>
+        """.write()
+
+        expected.expect(IllegalStateException::class.java)
+        expected.expectMessage("Duplicate actor definition for $NAMESPACE_TEST/$ACTOR_ONE;" +
+                " defined as both $PACKAGE_ONE and $PACKAGE_TWO")
+
+        assertPermissions()
+    }
+
+    private fun String.write() = tempFolder.root.resolve("${uniqueCounter++}.xml")
+            .writeText(this.trimIndent())
+
+    private fun assertPermissions() = SystemConfig(false).apply {
+        readPermissions(tempFolder.root, 0)
+    }. let { assertThat(it.namedActors) }
+}
diff --git a/services/tests/servicestests/src/com/android/server/SystemConfigTest.java b/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigTest.java
similarity index 98%
rename from services/tests/servicestests/src/com/android/server/SystemConfigTest.java
rename to services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigTest.java
index ff03391..fde0ddf 100644
--- a/services/tests/servicestests/src/com/android/server/SystemConfigTest.java
+++ b/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.server;
+package com.android.server.systemconfig;
 
 import static org.junit.Assert.assertEquals;
 
@@ -25,6 +25,8 @@
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
+import com.android.server.SystemConfig;
+
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
diff --git a/services/tests/servicestests/src/com/android/server/usage/UsageStatsDatabaseTest.java b/services/tests/servicestests/src/com/android/server/usage/UsageStatsDatabaseTest.java
index e32103f..e6bb244 100644
--- a/services/tests/servicestests/src/com/android/server/usage/UsageStatsDatabaseTest.java
+++ b/services/tests/servicestests/src/com/android/server/usage/UsageStatsDatabaseTest.java
@@ -45,6 +45,7 @@
 import java.io.IOException;
 import java.util.List;
 import java.util.Locale;
+import java.util.Set;
 
 @RunWith(AndroidJUnit4.class)
 @SmallTest
@@ -93,6 +94,8 @@
                 for (File f : usageFiles) {
                     f.delete();
                 }
+            } else {
+                intervalDir.delete();
             }
         }
     }
@@ -587,6 +590,7 @@
         db.readMappingsLocked();
         db.init(1);
         db.putUsageStats(interval, mIntervalStats);
+        db.writeMappingsLocked();
 
         final String removedPackage = "fake.package.name0";
         // invoke handler call directly from test to remove package
@@ -594,19 +598,19 @@
 
         List<IntervalStats> stats = db.queryUsageStats(interval, 0, mEndTime,
                 mIntervalStatsVerifier);
-        for (int i = 0; i < stats.size(); i++) {
-            final IntervalStats stat = stats.get(i);
-            if (stat.packageStats.containsKey(removedPackage)) {
-                fail("Found removed package " + removedPackage + " in package stats.");
+        assertEquals(1, stats.size(),
+                "Only one interval stats object should exist for the given time range.");
+        final IntervalStats stat = stats.get(0);
+        if (stat.packageStats.containsKey(removedPackage)) {
+            fail("Found removed package " + removedPackage + " in package stats.");
+            return;
+        }
+        for (int i = 0; i < stat.events.size(); i++) {
+            final Event event = stat.events.get(i);
+            if (removedPackage.equals(event.mPackage)) {
+                fail("Found an event from removed package " + removedPackage);
                 return;
             }
-            for (int j = 0; j < stat.events.size(); j++) {
-                final Event event = stat.events.get(j);
-                if (removedPackage.equals(event.mPackage)) {
-                    fail("Found an event from removed package " + removedPackage);
-                    return;
-                }
-            }
         }
     }
 
@@ -617,4 +621,90 @@
         verifyPackageNotRetained(UsageStatsManager.INTERVAL_MONTHLY);
         verifyPackageNotRetained(UsageStatsManager.INTERVAL_YEARLY);
     }
+
+    private void verifyPackageDataIsRemoved(UsageStatsDatabase db, int interval,
+            String removedPackage) {
+        List<IntervalStats> stats = db.queryUsageStats(interval, 0, mEndTime,
+                mIntervalStatsVerifier);
+        assertEquals(1, stats.size(),
+                "Only one interval stats object should exist for the given time range.");
+        final IntervalStats stat = stats.get(0);
+        if (stat.packageStats.containsKey(removedPackage)) {
+            fail("Found removed package " + removedPackage + " in package stats.");
+            return;
+        }
+        for (int i = 0; i < stat.events.size(); i++) {
+            final Event event = stat.events.get(i);
+            if (removedPackage.equals(event.mPackage)) {
+                fail("Found an event from removed package " + removedPackage);
+                return;
+            }
+        }
+    }
+
+    private void verifyPackageDataIsNotRemoved(UsageStatsDatabase db, int interval,
+            Set<String> installedPackages) {
+        List<IntervalStats> stats = db.queryUsageStats(interval, 0, mEndTime,
+                mIntervalStatsVerifier);
+        assertEquals(1, stats.size(),
+                "Only one interval stats object should exist for the given time range.");
+        final IntervalStats stat = stats.get(0);
+        if (!stat.packageStats.containsAll(installedPackages)) {
+            fail("Could not find some installed packages in package stats.");
+            return;
+        }
+        // attempt to find an event from each installed package
+        for (String installedPackage : installedPackages) {
+            for (int i = 0; i < stat.events.size(); i++) {
+                if (installedPackage.equals(stat.events.get(i).mPackage)) {
+                    break;
+                }
+                if (i == stat.events.size() - 1) {
+                    fail("Could not find any event for: " + installedPackage);
+                    return;
+                }
+            }
+        }
+    }
+
+    @Test
+    public void testPackageDataIsRemoved() throws IOException {
+        UsageStatsDatabase db = new UsageStatsDatabase(mTestDir);
+        db.readMappingsLocked();
+        db.init(1);
+
+        // write stats to disk for each interval
+        db.putUsageStats(UsageStatsManager.INTERVAL_DAILY, mIntervalStats);
+        db.putUsageStats(UsageStatsManager.INTERVAL_WEEKLY, mIntervalStats);
+        db.putUsageStats(UsageStatsManager.INTERVAL_MONTHLY, mIntervalStats);
+        db.putUsageStats(UsageStatsManager.INTERVAL_YEARLY, mIntervalStats);
+        db.writeMappingsLocked();
+
+        final Set<String> installedPackages = mIntervalStats.packageStats.keySet();
+        final String removedPackage = installedPackages.iterator().next();
+        installedPackages.remove(removedPackage);
+
+        // mimic a package uninstall
+        db.onPackageRemoved(removedPackage, System.currentTimeMillis());
+
+        // mimic the idle prune job being triggered
+        db.pruneUninstalledPackagesData();
+
+        // read data from disk into a new db instance
+        UsageStatsDatabase newDB = new UsageStatsDatabase(mTestDir);
+        newDB.readMappingsLocked();
+        newDB.init(mEndTime);
+
+        // query data for each interval and ensure data for package doesn't exist
+        verifyPackageDataIsRemoved(newDB, UsageStatsManager.INTERVAL_DAILY, removedPackage);
+        verifyPackageDataIsRemoved(newDB, UsageStatsManager.INTERVAL_WEEKLY, removedPackage);
+        verifyPackageDataIsRemoved(newDB, UsageStatsManager.INTERVAL_MONTHLY, removedPackage);
+        verifyPackageDataIsRemoved(newDB, UsageStatsManager.INTERVAL_YEARLY, removedPackage);
+
+        // query data for each interval and ensure some data for installed packages exists
+        verifyPackageDataIsNotRemoved(newDB, UsageStatsManager.INTERVAL_DAILY, installedPackages);
+        verifyPackageDataIsNotRemoved(newDB, UsageStatsManager.INTERVAL_WEEKLY, installedPackages);
+        verifyPackageDataIsNotRemoved(newDB, UsageStatsManager.INTERVAL_MONTHLY, installedPackages);
+        verifyPackageDataIsNotRemoved(newDB, UsageStatsManager.INTERVAL_YEARLY, installedPackages);
+    }
 }
diff --git a/services/tests/wmtests/src/com/android/server/wm/SystemServiceTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/SystemServiceTestsBase.java
index d1b6f6f..7e31895 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SystemServiceTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SystemServiceTestsBase.java
@@ -40,6 +40,10 @@
         mLockRule.waitForLocked(mSystemServicesTestRule::waitUntilWindowManagerHandlersIdle);
     }
 
+    void cleanupWindowManagerHandlers() {
+        mLockRule.waitForLocked(mSystemServicesTestRule::cleanupWindowManagerHandlers);
+    }
+
     boolean waitHandlerIdle(Handler handler) {
         return waitHandlerIdle(handler, 0 /* timeout */);
     }
diff --git a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
index 2c34f33..d3b68e0 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
@@ -355,6 +355,8 @@
         }
         wm.mH.removeCallbacksAndMessages(null);
         wm.mAnimationHandler.removeCallbacksAndMessages(null);
+        // This is a different handler object than the wm.mAnimationHandler above.
+        AnimationThread.getHandler().removeCallbacksAndMessages(null);
         SurfaceAnimationThread.getHandler().removeCallbacksAndMessages(null);
     }
 
@@ -367,6 +369,8 @@
         wm.mH.removeMessages(WindowManagerService.H.FORCE_GC);
         waitHandlerIdle(wm.mH);
         waitHandlerIdle(wm.mAnimationHandler);
+        // This is a different handler object than the wm.mAnimationHandler above.
+        waitHandlerIdle(AnimationThread.getHandler());
         waitHandlerIdle(SurfaceAnimationThread.getHandler());
     }
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
index 0da9dc4..7aa5148 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
@@ -175,7 +175,7 @@
             }
 
             // Cleaned up everything in Handler.
-            mSystemServicesTestRule.cleanupWindowManagerHandlers();
+            cleanupWindowManagerHandlers();
         } catch (Exception e) {
             Log.e(TAG, "Failed to tear down test", e);
             throw e;
diff --git a/services/usage/Android.bp b/services/usage/Android.bp
index 1064b6e..156bf33 100644
--- a/services/usage/Android.bp
+++ b/services/usage/Android.bp
@@ -1,5 +1,12 @@
+filegroup {
+    name: "services.usage-sources",
+    srcs: ["java/**/*.java"],
+    path: "java",
+    visibility: ["//frameworks/base/services"],
+}
+
 java_library_static {
     name: "services.usage",
-    srcs: ["java/**/*.java"],
+    srcs: [":services.usage-sources"],
     libs: ["services.core"],
 }
diff --git a/services/usage/java/com/android/server/usage/IntervalStats.java b/services/usage/java/com/android/server/usage/IntervalStats.java
index 46b261b..8fb283a 100644
--- a/services/usage/java/com/android/server/usage/IntervalStats.java
+++ b/services/usage/java/com/android/server/usage/IntervalStats.java
@@ -448,8 +448,11 @@
     /**
      * Parses all of the tokens to strings in the obfuscated usage stats data. This includes
      * deobfuscating each of the package tokens and chooser actions and categories.
+     *
+     * @return {@code true} if any stats were omitted while deobfuscating, {@code false} otherwise.
      */
-    private void deobfuscateUsageStats(PackagesTokenData packagesTokenData) {
+    private boolean deobfuscateUsageStats(PackagesTokenData packagesTokenData) {
+        boolean dataOmitted = false;
         final int usageStatsSize = packageStatsObfuscated.size();
         for (int statsIndex = 0; statsIndex < usageStatsSize; statsIndex++) {
             final int packageToken = packageStatsObfuscated.keyAt(statsIndex);
@@ -457,6 +460,7 @@
             usageStats.mPackageName = packagesTokenData.getPackageString(packageToken);
             if (usageStats.mPackageName == null) {
                 Slog.e(TAG, "Unable to parse usage stats package " + packageToken);
+                dataOmitted = true;
                 continue;
             }
 
@@ -489,14 +493,18 @@
             }
             packageStats.put(usageStats.mPackageName, usageStats);
         }
+        return dataOmitted;
     }
 
     /**
      * Parses all of the tokens to strings in the obfuscated events data. This includes
      * deobfuscating the package token, along with any class, task root package/class tokens, and
      * shortcut or notification channel tokens.
+     *
+     * @return {@code true} if any events were omitted while deobfuscating, {@code false} otherwise.
      */
-    private void deobfuscateEvents(PackagesTokenData packagesTokenData) {
+    private boolean deobfuscateEvents(PackagesTokenData packagesTokenData) {
+        boolean dataOmitted = false;
         for (int i = this.events.size() - 1; i >= 0; i--) {
             final Event event = this.events.get(i);
             final int packageToken = event.mPackageToken;
@@ -504,6 +512,7 @@
             if (event.mPackage == null) {
                 Slog.e(TAG, "Unable to parse event package " + packageToken);
                 this.events.remove(i);
+                dataOmitted = true;
                 continue;
             }
 
@@ -543,6 +552,7 @@
                         Slog.e(TAG, "Unable to parse shortcut " + event.mShortcutIdToken
                                 + " for package " + packageToken);
                         this.events.remove(i);
+                        dataOmitted = true;
                         continue;
                     }
                     break;
@@ -554,21 +564,25 @@
                                 + event.mNotificationChannelIdToken + " for package "
                                 + packageToken);
                         this.events.remove(i);
+                        dataOmitted = true;
                         continue;
                     }
                     break;
             }
         }
+        return dataOmitted;
     }
 
     /**
      * Parses the obfuscated tokenized data held in this interval stats object.
      *
+     * @return {@code true} if any data was omitted while deobfuscating, {@code false} otherwise.
      * @hide
      */
-    public void deobfuscateData(PackagesTokenData packagesTokenData) {
-        deobfuscateUsageStats(packagesTokenData);
-        deobfuscateEvents(packagesTokenData);
+    public boolean deobfuscateData(PackagesTokenData packagesTokenData) {
+        final boolean statsOmitted = deobfuscateUsageStats(packagesTokenData);
+        final boolean eventsOmitted = deobfuscateEvents(packagesTokenData);
+        return statsOmitted || eventsOmitted;
     }
 
     /**
diff --git a/services/usage/java/com/android/server/usage/PackagesTokenData.java b/services/usage/java/com/android/server/usage/PackagesTokenData.java
index 4bf08a4..f19abbb 100644
--- a/services/usage/java/com/android/server/usage/PackagesTokenData.java
+++ b/services/usage/java/com/android/server/usage/PackagesTokenData.java
@@ -162,15 +162,18 @@
      *
      * @param packageName the package to be removed
      * @param timeRemoved the time stamp of when the package was removed
+     * @return the token mapped to the package removed or {@code PackagesTokenData.UNASSIGNED_TOKEN}
+     *         if not mapped
      */
-    public void removePackage(String packageName, long timeRemoved) {
+    public int removePackage(String packageName, long timeRemoved) {
         removedPackagesMap.put(packageName, timeRemoved);
 
         if (!packagesToTokensMap.containsKey(packageName)) {
-            return;
+            return UNASSIGNED_TOKEN;
         }
         final int packageToken = packagesToTokensMap.get(packageName).get(packageName);
         packagesToTokensMap.remove(packageName);
         tokensToPackagesMap.delete(packageToken);
+        return packageToken;
     }
 }
diff --git a/services/usage/java/com/android/server/usage/UsageStatsDatabase.java b/services/usage/java/com/android/server/usage/UsageStatsDatabase.java
index 27d7360..ce29527 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsDatabase.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsDatabase.java
@@ -52,6 +52,7 @@
 import java.nio.file.Files;
 import java.nio.file.StandardCopyOption;
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
 
 /**
@@ -122,6 +123,7 @@
     private int mCurrentVersion;
     private boolean mFirstUpdate;
     private boolean mNewUpdate;
+    private boolean mUpgradePerformed;
 
     // The obfuscated packages to tokens mappings file
     private final File mPackageMappingsFile;
@@ -325,6 +327,13 @@
         return mNewUpdate;
     }
 
+    /**
+     * Was an upgrade performed when this database was initialized?
+     */
+    boolean wasUpgradePerformed() {
+        return mUpgradePerformed;
+    }
+
     private void checkVersionAndBuildLocked() {
         int version;
         String buildFingerprint;
@@ -397,6 +406,8 @@
         if (mUpdateBreadcrumb.exists()) {
             // Files should be up to date with current version. Clear the version update breadcrumb
             mUpdateBreadcrumb.delete();
+            // update mUpgradePerformed after breadcrumb is deleted to indicate a successful upgrade
+            mUpgradePerformed = true;
         }
 
         if (mBackupsDir.exists() && !KEEP_BACKUP_DIR) {
@@ -545,12 +556,119 @@
         }
     }
 
-    void onPackageRemoved(String packageName, long timeRemoved) {
+    /**
+     * Returns the token mapped to the package removed or {@code PackagesTokenData.UNASSIGNED_TOKEN}
+     * if not mapped.
+     */
+    int onPackageRemoved(String packageName, long timeRemoved) {
         synchronized (mLock) {
-            mPackagesTokenData.removePackage(packageName, timeRemoved);
+            return mPackagesTokenData.removePackage(packageName, timeRemoved);
         }
     }
 
+    /**
+     * Reads all the usage stats data on disk and rewrites it with any data related to uninstalled
+     * packages omitted.
+     */
+    boolean pruneUninstalledPackagesData() {
+        synchronized (mLock) {
+            for (int i = 0; i < mIntervalDirs.length; i++) {
+                final File[] files = mIntervalDirs[i].listFiles();
+                if (files == null) {
+                    continue;
+                }
+                for (int j = 0; j < files.length; j++) {
+                    try {
+                        final IntervalStats stats = new IntervalStats();
+                        final AtomicFile atomicFile = new AtomicFile(files[j]);
+                        if (!readLocked(atomicFile, stats, mCurrentVersion, mPackagesTokenData)) {
+                            continue; // no data was omitted when read so no need to rewrite
+                        }
+                        // Any data related to packages that have been removed would have failed
+                        // the deobfuscation step on read so the IntervalStats object here only
+                        // contains data for packages that are currently installed - all we need
+                        // to do here is write the data back to disk.
+                        writeLocked(atomicFile, stats, mCurrentVersion, mPackagesTokenData);
+                    } catch (Exception e) {
+                        Slog.e(TAG, "Failed to prune data from: " + files[j].toString());
+                        return false;
+                    }
+                }
+            }
+            try {
+                writeMappingsLocked();
+            } catch (IOException e) {
+                Slog.e(TAG, "Failed to write package mappings after pruning data.");
+                return false;
+            }
+            return true;
+        }
+    }
+
+    /**
+     * Iterates through all the files on disk and prunes any data that belongs to packages that have
+     * been uninstalled (packages that are not in the given list).
+     * Note: this should only be called once, when there has been a database upgrade.
+     *
+     * @param installedPackages map of installed packages (package_name:package_install_time)
+     */
+    void prunePackagesDataOnUpgrade(HashMap<String, Long> installedPackages) {
+        if (installedPackages == null || installedPackages.isEmpty()) {
+            return;
+        }
+        synchronized (mLock) {
+            for (int i = 0; i < mIntervalDirs.length; i++) {
+                final File[] files = mIntervalDirs[i].listFiles();
+                if (files == null) {
+                    continue;
+                }
+                for (int j = 0; j < files.length; j++) {
+                    try {
+                        final IntervalStats stats = new IntervalStats();
+                        final AtomicFile atomicFile = new AtomicFile(files[j]);
+                        readLocked(atomicFile, stats, mCurrentVersion, mPackagesTokenData);
+                        if (!pruneStats(installedPackages, stats)) {
+                            continue; // no stats were pruned so no need to rewrite
+                        }
+                        writeLocked(atomicFile, stats, mCurrentVersion, mPackagesTokenData);
+                    } catch (Exception e) {
+                        Slog.e(TAG, "Failed to prune data from: " + files[j].toString());
+                    }
+                }
+            }
+        }
+    }
+
+    private boolean pruneStats(HashMap<String, Long> installedPackages, IntervalStats stats) {
+        boolean dataPruned = false;
+
+        // prune old package usage stats
+        for (int i = stats.packageStats.size() - 1; i >= 0; i--) {
+            final UsageStats usageStats = stats.packageStats.valueAt(i);
+            final Long timeInstalled = installedPackages.get(usageStats.mPackageName);
+            if (timeInstalled == null || timeInstalled > usageStats.mEndTimeStamp) {
+                stats.packageStats.removeAt(i);
+                dataPruned = true;
+            }
+        }
+        if (dataPruned) {
+            // ensure old stats don't linger around during the obfuscation step on write
+            stats.packageStatsObfuscated.clear();
+        }
+
+        // prune old events
+        for (int i = stats.events.size() - 1; i >= 0; i--) {
+            final UsageEvents.Event event = stats.events.get(i);
+            final Long timeInstalled = installedPackages.get(event.mPackage);
+            if (timeInstalled == null || timeInstalled > event.mTimeStamp) {
+                stats.events.remove(i);
+                dataPruned = true;
+            }
+        }
+
+        return dataPruned;
+    }
+
     public void onTimeChanged(long timeDiffMillis) {
         synchronized (mLock) {
             StringBuilder logBuilder = new StringBuilder();
@@ -645,7 +763,6 @@
         }
 
         // filter out events
-        final int eventsSize = stats.events.size();
         for (int i = stats.events.size() - 1; i >= 0; i--) {
             final UsageEvents.Event event = stats.events.get(i);
             final Long timeRemoved = removedPackagesMap.get(event.mPackage);
@@ -942,13 +1059,17 @@
         readLocked(file, statsOut, mCurrentVersion, mPackagesTokenData);
     }
 
-    private static void readLocked(AtomicFile file, IntervalStats statsOut, int version,
+    /**
+     * Returns {@code true} if any stats were omitted while reading, {@code false} otherwise.
+     */
+    private static boolean readLocked(AtomicFile file, IntervalStats statsOut, int version,
             PackagesTokenData packagesTokenData) throws IOException {
+        boolean dataOmitted = false;
         try {
             FileInputStream in = file.openRead();
             try {
                 statsOut.beginTime = parseBeginTime(file);
-                readLocked(in, statsOut, version, packagesTokenData);
+                dataOmitted = readLocked(in, statsOut, version, packagesTokenData);
                 statsOut.lastTimeSaved = file.getLastModifiedTime();
             } finally {
                 try {
@@ -961,10 +1082,15 @@
             Slog.e(TAG, "UsageStatsDatabase", e);
             throw e;
         }
+        return dataOmitted;
     }
 
-    private static void readLocked(InputStream in, IntervalStats statsOut, int version,
+    /**
+     * Returns {@code true} if any stats were omitted while reading, {@code false} otherwise.
+     */
+    private static boolean readLocked(InputStream in, IntervalStats statsOut, int version,
             PackagesTokenData packagesTokenData) throws IOException {
+        boolean dataOmitted = false;
         switch (version) {
             case 1:
             case 2:
@@ -989,14 +1115,14 @@
                 } catch (IOException e) {
                     Slog.e(TAG, "Unable to read interval stats from proto.", e);
                 }
-                statsOut.deobfuscateData(packagesTokenData);
+                dataOmitted = statsOut.deobfuscateData(packagesTokenData);
                 break;
             default:
                 throw new RuntimeException(
                         "Unhandled UsageStatsDatabase version: " + Integer.toString(version)
                                 + " on read.");
         }
-
+        return dataOmitted;
     }
 
     /**
diff --git a/services/usage/java/com/android/server/usage/UsageStatsIdleService.java b/services/usage/java/com/android/server/usage/UsageStatsIdleService.java
new file mode 100644
index 0000000..8677779
--- /dev/null
+++ b/services/usage/java/com/android/server/usage/UsageStatsIdleService.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.usage;
+
+import android.app.job.JobInfo;
+import android.app.job.JobParameters;
+import android.app.job.JobScheduler;
+import android.app.job.JobService;
+import android.app.usage.UsageStatsManagerInternal;
+import android.content.ComponentName;
+import android.content.Context;
+import android.os.AsyncTask;
+import android.os.PersistableBundle;
+
+import com.android.server.LocalServices;
+
+/**
+ * JobService used to do any work for UsageStats while the device is idle.
+ */
+public class UsageStatsIdleService extends JobService {
+
+    /**
+     * Base job ID for the pruning job - must be unique within the system server uid.
+     */
+    private static final int PRUNE_JOB_ID = 546357475;
+
+    private static final String USER_ID_KEY = "user_id";
+    private static final String REMOVED_TOKENS_KEY = "removed_tokens";
+
+    static void scheduleJob(Context context, int userId, int token) {
+        final int userJobId = PRUNE_JOB_ID + userId; // unique job id per user
+        final ComponentName component = new ComponentName(context.getPackageName(),
+                UsageStatsIdleService.class.getName());
+        final PersistableBundle bundle = new PersistableBundle();
+        bundle.putInt(USER_ID_KEY, userId);
+        bundle.putIntArray(REMOVED_TOKENS_KEY,
+                getOrCreateRemovedTokens(fetchRemovedTokens(context, userId), token));
+        final JobInfo pruneJob = new JobInfo.Builder(userJobId, component)
+                .setRequiresDeviceIdle(true)
+                .setExtras(bundle)
+                .setPersisted(true)
+                .build();
+
+        final JobScheduler jobScheduler = context.getSystemService(JobScheduler.class);
+        jobScheduler.schedule(pruneJob);
+    }
+
+    static void cancelJob(Context context, int userId) {
+        final int userJobId = PRUNE_JOB_ID + userId; // unique job id per user
+        final JobScheduler jobScheduler = context.getSystemService(JobScheduler.class);
+        jobScheduler.cancel(userJobId);
+    }
+
+    /**
+     * Fetches an array of removed tokens from previous prune jobs, if any.
+     */
+    static int[] fetchRemovedTokens(Context context, int userId) {
+        final JobScheduler jobScheduler = context.getSystemService(JobScheduler.class);
+        final int userJobId = PRUNE_JOB_ID + userId; // unique job id per user
+        final JobInfo pendingJob = jobScheduler.getPendingJob(userJobId);
+        if (pendingJob != null) {
+            final PersistableBundle bundle = pendingJob.getExtras();
+            return bundle.getIntArray(REMOVED_TOKENS_KEY);
+        }
+        return null;
+    }
+
+    @Override
+    public boolean onStartJob(JobParameters params) {
+        final PersistableBundle bundle = params.getExtras();
+        final int userId = bundle.getInt(USER_ID_KEY, -1);
+        if (userId == -1) {
+            return false;
+        }
+
+        AsyncTask.execute(() -> {
+            final UsageStatsManagerInternal usageStatsManagerInternal = LocalServices.getService(
+                    UsageStatsManagerInternal.class);
+            final boolean pruned = usageStatsManagerInternal.pruneUninstalledPackagesData(userId);
+            jobFinished(params, !pruned); // reschedule if data was not pruned
+        });
+        return true;
+    }
+
+    @Override
+    public boolean onStopJob(JobParameters params) {
+        // Since the pruning job isn't a heavy job, we don't want to cancel it's execution midway.
+        return false;
+    }
+
+    /**
+     * Helper method to create a cloned array of removed tokens from previous jobs (if any) with
+     * the newly removed token at index 0. If there are no removed tokens from previous jobs, it
+     * simply returns a new array containing the current token.
+     */
+    private static int[] getOrCreateRemovedTokens(int[] previousRemovedTokens, int token) {
+        final int[] removedTokens;
+        if (previousRemovedTokens == null) {
+            removedTokens = new int[1];
+        } else {
+            removedTokens = new int[previousRemovedTokens.length + 1];
+            System.arraycopy(previousRemovedTokens, 0, removedTokens, 1,
+                    previousRemovedTokens.length);
+        }
+        removedTokens[0] = token;
+        return removedTokens;
+    }
+}
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index f9b3659..5f5e7e8 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -846,6 +846,8 @@
             mUserState.remove(userId);
             mAppStandby.onUserRemoved(userId);
             mAppTimeLimit.onUserRemoved(userId);
+            // Cancel any scheduled jobs for this user since the user is being removed.
+            UsageStatsIdleService.cancelJob(getContext(), userId);
         }
     }
 
@@ -855,7 +857,7 @@
     private void onPackageRemoved(int userId, String packageName) {
         synchronized (mLock) {
             final long timeRemoved = System.currentTimeMillis();
-            if (!mUserUnlockedStates.get(userId, false)) {
+            if (!mUserUnlockedStates.get(userId)) {
                 // If user is not unlocked and a package is removed for them, we will handle it
                 // when the user service is initialized and package manager is queried.
                 return;
@@ -872,6 +874,24 @@
     /**
      * Called by the Binder stub.
      */
+    private boolean pruneUninstalledPackagesData(int userId) {
+        synchronized (mLock) {
+            if (!mUserUnlockedStates.get(userId)) {
+                return false; // user is no longer unlocked
+            }
+
+            final UserUsageStatsService userService = mUserState.get(userId);
+            if (userService == null) {
+                return false; // user was stopped or removed
+            }
+
+            return userService.pruneUninstalledPackagesData();
+        }
+    }
+
+    /**
+     * Called by the Binder stub.
+     */
     List<UsageStats> queryUsageStats(int userId, int bucketType, long beginTime, long endTime,
             boolean obfuscateInstantApps) {
         synchronized (mLock) {
@@ -2124,6 +2144,11 @@
         public AppUsageLimitData getAppUsageLimit(String packageName, UserHandle user) {
             return mAppTimeLimit.getAppUsageLimit(packageName, user);
         }
+
+        @Override
+        public boolean pruneUninstalledPackagesData(int userId) {
+            return UsageStatsService.this.pruneUninstalledPackagesData(userId);
+        }
     }
 
     private class MyPackageMonitor extends PackageMonitor {
diff --git a/services/usage/java/com/android/server/usage/UserUsageStatsService.java b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
index 5783932..d30f2ad 100644
--- a/services/usage/java/com/android/server/usage/UserUsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
@@ -34,10 +34,9 @@
 import android.app.usage.UsageStats;
 import android.app.usage.UsageStatsManager;
 import android.content.Context;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManagerInternal;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
 import android.content.res.Configuration;
-import android.os.Process;
 import android.os.SystemClock;
 import android.text.format.DateUtils;
 import android.util.ArrayMap;
@@ -47,7 +46,6 @@
 import android.util.SparseIntArray;
 
 import com.android.internal.util.IndentingPrintWriter;
-import com.android.server.LocalServices;
 import com.android.server.usage.UsageStatsDatabase.StatCombiner;
 
 import java.io.File;
@@ -55,7 +53,7 @@
 import java.text.SimpleDateFormat;
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.HashSet;
+import java.util.HashMap;
 import java.util.List;
 
 /**
@@ -115,6 +113,9 @@
     void init(final long currentTimeMillis) {
         readPackageMappingsLocked();
         mDatabase.init(currentTimeMillis);
+        if (mDatabase.wasUpgradePerformed()) {
+            mDatabase.prunePackagesDataOnUpgrade(getInstalledPackages());
+        }
 
         int nullCount = 0;
         for (int i = 0; i < mCurrentStats.length; i++) {
@@ -175,53 +176,70 @@
     }
 
     void onPackageRemoved(String packageName, long timeRemoved) {
-        mDatabase.onPackageRemoved(packageName, timeRemoved);
+        final int token = mDatabase.onPackageRemoved(packageName, timeRemoved);
+        if (token != PackagesTokenData.UNASSIGNED_TOKEN) {
+            UsageStatsIdleService.scheduleJob(mContext, mUserId, token);
+        }
     }
 
     private void readPackageMappingsLocked() {
         mDatabase.readMappingsLocked();
-        cleanUpPackageMappingsLocked();
+        updatePackageMappingsLocked();
     }
 
     /**
-     * Queries Package Manager for a list of installed packages and removes those packages from
-     * mPackagesTokenData which are not installed any more.
+     * Queries Job Scheduler for any pending data prune jobs and if any exist, it updates the
+     * package mappings in memory by removing those tokens.
      * This will only happen once per device boot, when the user is unlocked for the first time.
      */
-    private void cleanUpPackageMappingsLocked() {
+    private void updatePackageMappingsLocked() {
         final long timeNow = System.currentTimeMillis();
-        /*
-         Note (b/142501248): PackageManagerInternal#getInstalledApplications is not lightweight.
-         Once its implementation is updated, or it's replaced with a better alternative, update
-         the call here to use it. For now, using the heavy #getInstalledApplications is okay since
-         this clean-up is only performed once every boot.
-         */
-        final PackageManagerInternal packageManagerInternal =
-                LocalServices.getService(PackageManagerInternal.class);
-        if (packageManagerInternal == null) {
+        final int[] removedTokens = UsageStatsIdleService.fetchRemovedTokens(mContext, mUserId);
+        if (removedTokens == null) {
             return;
         }
-        final List<ApplicationInfo> installedPackages =
-                packageManagerInternal.getInstalledApplications(0, mUserId, Process.SYSTEM_UID);
-        // convert the package list to a set for easy look-ups
-        final HashSet<String> packagesSet = new HashSet<>(installedPackages.size());
-        for (int i = installedPackages.size() - 1; i >= 0; i--) {
-            packagesSet.add(installedPackages.get(i).packageName);
-        }
-        final List<String> removedPackages = new ArrayList<>();
-        // populate list of packages that are found in the mappings but not in the installed list
-        for (int i = mDatabase.mPackagesTokenData.packagesToTokensMap.size() - 1; i >= 0; i--) {
-            if (!packagesSet.contains(mDatabase.mPackagesTokenData.packagesToTokensMap.keyAt(i))) {
-                removedPackages.add(mDatabase.mPackagesTokenData.packagesToTokensMap.keyAt(i));
-            }
-        }
 
-        // remove packages in the mappings that are no longer installed
-        for (int i = removedPackages.size() - 1; i >= 0; i--) {
-            mDatabase.mPackagesTokenData.removePackage(removedPackages.get(i), timeNow);
+        for (int i = removedTokens.length - 1; i >= 0; i--) {
+            final String packageName =
+                    mDatabase.mPackagesTokenData.getPackageString(removedTokens[i]);
+            if (packageName == null) {
+                continue;
+            }
+            /*
+             Note: in most cases, packageName returned will be null since the package mappings file
+             on disk should have been updated when it was last persisted. This is to handle the rare
+             case of system crashing after a package was removed but the package mappings file
+             wasn't persisted to disk.
+             */
+            mDatabase.mPackagesTokenData.removePackage(packageName, timeNow);
         }
     }
 
+    /**
+     * Fetches a map of package names to their install times. This includes all installed packages,
+     * including those packages which have been uninstalled with the DONT_DELETE_DATA flag.
+     * Note: this is supposed be a helper method which is only used on database upgrades - it should
+     * not be called otherwise since it's implementation performs a heavy query to package manager.
+     */
+    private HashMap<String, Long> getInstalledPackages() {
+        final PackageManager packageManager = mContext.getPackageManager();
+        if (packageManager == null) {
+            return null;
+        }
+        final List<PackageInfo> installedPackages = packageManager.getInstalledPackagesAsUser(
+                PackageManager.MATCH_UNINSTALLED_PACKAGES, mUserId);
+        final HashMap<String, Long> packagesMap = new HashMap<>();
+        for (int i = installedPackages.size() - 1; i >= 0; i--) {
+            final PackageInfo packageInfo = installedPackages.get(i);
+            packagesMap.put(packageInfo.packageName, packageInfo.firstInstallTime);
+        }
+        return packagesMap;
+    }
+
+    boolean pruneUninstalledPackagesData() {
+        return mDatabase.pruneUninstalledPackagesData();
+    }
+
     private void onTimeChanged(long oldTime, long newTime) {
         persistActiveStats();
         mDatabase.onTimeChanged(newTime - oldTime);
diff --git a/services/usb/Android.bp b/services/usb/Android.bp
index 20855b7..d2c973a 100644
--- a/services/usb/Android.bp
+++ b/services/usb/Android.bp
@@ -1,6 +1,13 @@
+filegroup {
+    name: "services.usb-sources",
+    srcs: ["java/**/*.java"],
+    path: "java",
+    visibility: ["//frameworks/base/services"],
+}
+
 java_library_static {
     name: "services.usb",
-    srcs: ["java/**/*.java"],
+    srcs: [":services.usb-sources"],
 
     libs: [
         "services.core",
diff --git a/services/voiceinteraction/Android.bp b/services/voiceinteraction/Android.bp
index 390406f..85b96f34 100644
--- a/services/voiceinteraction/Android.bp
+++ b/services/voiceinteraction/Android.bp
@@ -1,5 +1,12 @@
+filegroup {
+    name: "services.voiceinteraction-sources",
+    srcs: ["java/**/*.java"],
+    path: "java",
+    visibility: ["//frameworks/base/services"],
+}
+
 java_library_static {
     name: "services.voiceinteraction",
-    srcs: ["java/**/*.java"],
+    srcs: [":services.voiceinteraction-sources"],
     libs: ["services.core"],
 }
diff --git a/services/wifi/Android.bp b/services/wifi/Android.bp
index 608fc2c..8a7f73f 100644
--- a/services/wifi/Android.bp
+++ b/services/wifi/Android.bp
@@ -1,14 +1,16 @@
-// Interfaces between the core system and the wifi mainline module.
-java_library_static {
-    name: "services.wifi",
+filegroup {
+    name: "services.wifi-sources",
     srcs: [
         "java/**/*.java",
         "java/**/*.aidl",
     ],
-    aidl: {
-        local_include_dirs: ["java"]
-    },
-    libs: [
-        "services.net",
-    ],
+    path: "java",
+    visibility: ["//frameworks/base/services"],
+}
+
+// Interfaces between the core system and the wifi mainline module.
+java_library_static {
+    name: "services.wifi",
+    srcs: [":services.wifi-sources"],
+    libs: ["services.net"],
 }
diff --git a/startop/iorap/Android.bp b/startop/iorap/Android.bp
index 59a80fb..993d1e1 100644
--- a/startop/iorap/Android.bp
+++ b/startop/iorap/Android.bp
@@ -12,19 +12,24 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+filegroup {
+  name: "services.startop.iorap-javasources",
+  srcs: ["src/**/*.java"],
+  path: "src",
+  visibility: ["//visibility:private"],
+}
+
+filegroup {
+  name: "services.startop.iorap-sources",
+  srcs: [
+    ":services.startop.iorap-javasources",
+    ":iorap-aidl",
+  ],
+  visibility: ["//frameworks/base/services:__subpackages__"],
+}
+
 java_library_static {
   name: "services.startop.iorap",
-
-  aidl: {
-    include_dirs: [
-      "system/iorap/binder",
-    ],
-  },
-
+  srcs: [":services.startop.iorap-sources"],
   libs: ["services.core"],
-
-  srcs: [
-      ":iorap-aidl",
-      "**/*.java",
-  ],
 }
diff --git a/telephony/java/android/telephony/TelephonyFrameworkInitializer.java b/telephony/java/android/telephony/TelephonyFrameworkInitializer.java
new file mode 100644
index 0000000..b75d533
--- /dev/null
+++ b/telephony/java/android/telephony/TelephonyFrameworkInitializer.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telephony;
+
+import android.annotation.SystemApi;
+import android.app.SystemServiceRegistry;
+import android.content.Context;
+import android.telephony.euicc.EuiccCardManager;
+import android.telephony.euicc.EuiccManager;
+
+
+/**
+ * Class for performing registration for all telephony services.
+ *
+ * @hide
+ */
+@SystemApi
+public class TelephonyFrameworkInitializer {
+
+    private TelephonyFrameworkInitializer() {
+    }
+
+    /**
+     * Called by {@link SystemServiceRegistry}'s static initializer and registers all telephony
+     * services to {@link Context}, so that {@link Context#getSystemService} can return them.
+     *
+     * @throws IllegalStateException if this is called from anywhere besides
+     * {@link SystemServiceRegistry}
+     */
+    public static void registerServiceWrappers() {
+        SystemServiceRegistry.registerContextAwareService(
+                Context.TELEPHONY_SERVICE,
+                TelephonyManager.class,
+                context -> new TelephonyManager(context)
+        );
+        SystemServiceRegistry.registerContextAwareService(
+                Context.TELEPHONY_SUBSCRIPTION_SERVICE,
+                SubscriptionManager.class,
+                context -> new SubscriptionManager(context)
+        );
+        SystemServiceRegistry.registerContextAwareService(
+                Context.CARRIER_CONFIG_SERVICE,
+                CarrierConfigManager.class,
+                context -> new CarrierConfigManager(context)
+        );
+        SystemServiceRegistry.registerContextAwareService(
+                Context.EUICC_SERVICE,
+                EuiccManager.class,
+                context -> new EuiccManager(context)
+        );
+        SystemServiceRegistry.registerContextAwareService(
+                Context.EUICC_CARD_SERVICE,
+                EuiccCardManager.class,
+                context -> new EuiccCardManager(context)
+        );
+    }
+}
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 60a2cd0..8759a29 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -8988,7 +8988,10 @@
     @Deprecated
     public boolean isTtyModeSupported() {
         try {
-            TelecomManager telecomManager = TelecomManager.from(mContext);
+            TelecomManager telecomManager = null;
+            if (mContext != null) {
+                telecomManager = mContext.getSystemService(TelecomManager.class);
+            }
             if (telecomManager != null) {
                 return telecomManager.isTtySupported();
             }
@@ -11298,7 +11301,9 @@
     @IntDef(prefix = {"SET_OPPORTUNISTIC_SUB"}, value = {
             SET_OPPORTUNISTIC_SUB_SUCCESS,
             SET_OPPORTUNISTIC_SUB_VALIDATION_FAILED,
-            SET_OPPORTUNISTIC_SUB_INACTIVE_SUBSCRIPTION})
+            SET_OPPORTUNISTIC_SUB_INACTIVE_SUBSCRIPTION,
+            SET_OPPORTUNISTIC_SUB_NO_OPPORTUNISTIC_SUB_AVAILABLE,
+            SET_OPPORTUNISTIC_SUB_REMOTE_SERVICE_EXCEPTION})
     public @interface SetOpportunisticSubscriptionResult {}
 
     /**
@@ -11316,6 +11321,17 @@
      */
     public static final int SET_OPPORTUNISTIC_SUB_INACTIVE_SUBSCRIPTION = 2;
 
+    /**
+     * The subscription is not valid. It must be an opportunistic subscription.
+     */
+    public static final int SET_OPPORTUNISTIC_SUB_NO_OPPORTUNISTIC_SUB_AVAILABLE = 3;
+
+    /**
+     * Subscription service happened remote exception.
+     */
+    public static final int SET_OPPORTUNISTIC_SUB_REMOTE_SERVICE_EXCEPTION = 4;
+
+
     /** @hide */
     @Retention(RetentionPolicy.SOURCE)
     @IntDef(prefix = {"UPDATE_AVAILABLE_NETWORKS"}, value = {
@@ -11323,7 +11339,13 @@
             UPDATE_AVAILABLE_NETWORKS_UNKNOWN_FAILURE,
             UPDATE_AVAILABLE_NETWORKS_ABORTED,
             UPDATE_AVAILABLE_NETWORKS_INVALID_ARGUMENTS,
-            UPDATE_AVAILABLE_NETWORKS_NO_CARRIER_PRIVILEGE})
+            UPDATE_AVAILABLE_NETWORKS_NO_CARRIER_PRIVILEGE,
+            UPDATE_AVAILABLE_NETWORKS_DISABLE_MODEM_FAIL,
+            UPDATE_AVAILABLE_NETWORKS_ENABLE_MODEM_FAIL,
+            UPDATE_AVAILABLE_NETWORKS_MULTIPLE_NETWORKS_NOT_SUPPORTED,
+            UPDATE_AVAILABLE_NETWORKS_NO_OPPORTUNISTIC_SUB_AVAILABLE,
+            UPDATE_AVAILABLE_NETWORKS_REMOTE_SERVICE_EXCEPTION,
+            UPDATE_AVAILABLE_NETWORKS_SERVICE_IS_DISABLED})
     public @interface UpdateAvailableNetworksResult {}
 
     /**
@@ -11352,6 +11374,36 @@
     public static final int UPDATE_AVAILABLE_NETWORKS_NO_CARRIER_PRIVILEGE = 4;
 
     /**
+     * Disable modem fail.
+     */
+    public static final int UPDATE_AVAILABLE_NETWORKS_DISABLE_MODEM_FAIL = 5;
+
+    /**
+     * Enable modem fail.
+     */
+    public static final int UPDATE_AVAILABLE_NETWORKS_ENABLE_MODEM_FAIL = 6;
+
+    /**
+     * Carrier app does not support multiple available networks.
+     */
+    public static final int UPDATE_AVAILABLE_NETWORKS_MULTIPLE_NETWORKS_NOT_SUPPORTED = 7;
+
+    /**
+     * The subscription is not valid. It must be an opportunistic subscription.
+     */
+    public static final int UPDATE_AVAILABLE_NETWORKS_NO_OPPORTUNISTIC_SUB_AVAILABLE = 8;
+
+    /**
+     * There is no OpportunisticNetworkService.
+     */
+    public static final int UPDATE_AVAILABLE_NETWORKS_REMOTE_SERVICE_EXCEPTION = 9;
+
+    /**
+     * OpportunisticNetworkService is disabled.
+     */
+    public static final int UPDATE_AVAILABLE_NETWORKS_SERVICE_IS_DISABLED = 10;
+
+    /**
      * Set preferred opportunistic data subscription id.
      *
      * Switch internet data to preferred opportunistic data subscription id. This api
@@ -11381,7 +11433,7 @@
                     return;
                 }
                 Binder.withCleanCallingIdentity(() -> executor.execute(() -> {
-                    callback.accept(SET_OPPORTUNISTIC_SUB_INACTIVE_SUBSCRIPTION);
+                    callback.accept(SET_OPPORTUNISTIC_SUB_REMOTE_SERVICE_EXCEPTION);
                 }));
                 return;
             }
@@ -11467,9 +11519,8 @@
                     return;
                 }
                 if (iOpportunisticNetworkService == null) {
-                    /* Todo<b/130595455> passing unknown due to lack of good error codes */
                     Binder.withCleanCallingIdentity(() -> executor.execute(() -> {
-                        callback.accept(UPDATE_AVAILABLE_NETWORKS_UNKNOWN_FAILURE);
+                        callback.accept(UPDATE_AVAILABLE_NETWORKS_REMOTE_SERVICE_EXCEPTION);
                     }));
                 } else {
                     Binder.withCleanCallingIdentity(() -> executor.execute(() -> {
diff --git a/telephony/java/com/android/internal/telephony/CarrierAppUtils.java b/telephony/java/com/android/internal/telephony/CarrierAppUtils.java
index 0d4fd0f..e6bebbb 100644
--- a/telephony/java/com/android/internal/telephony/CarrierAppUtils.java
+++ b/telephony/java/com/android/internal/telephony/CarrierAppUtils.java
@@ -25,10 +25,10 @@
 import android.os.RemoteException;
 import android.permission.IPermissionManager;
 import android.provider.Settings;
+import android.telephony.Rlog;
 import android.telephony.TelephonyManager;
 import android.util.ArrayMap;
 import android.util.ArraySet;
-import android.util.Slog;
 
 import com.android.internal.R;
 import com.android.internal.annotations.VisibleForTesting;
@@ -78,7 +78,7 @@
             IPackageManager packageManager, IPermissionManager permissionManager,
             TelephonyManager telephonyManager, ContentResolver contentResolver, int userId) {
         if (DEBUG) {
-            Slog.d(TAG, "disableCarrierAppsUntilPrivileged");
+            Rlog.d(TAG, "disableCarrierAppsUntilPrivileged");
         }
         SystemConfig config = SystemConfig.getInstance();
         ArraySet<String> systemCarrierAppsDisabledUntilUsed =
@@ -105,7 +105,7 @@
             IPackageManager packageManager, IPermissionManager permissionManager,
             ContentResolver contentResolver, int userId) {
         if (DEBUG) {
-            Slog.d(TAG, "disableCarrierAppsUntilPrivileged");
+            Rlog.d(TAG, "disableCarrierAppsUntilPrivileged");
         }
         SystemConfig config = SystemConfig.getInstance();
         ArraySet<String> systemCarrierAppsDisabledUntilUsed =
@@ -174,7 +174,7 @@
                             || ai.enabledSetting ==
                             PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED
                             || (ai.flags & ApplicationInfo.FLAG_INSTALLED) == 0)) {
-                        Slog.i(TAG, "Update state(" + packageName + "): ENABLED for user "
+                        Rlog.i(TAG, "Update state(" + packageName + "): ENABLED for user "
                                 + userId);
                         packageManager.setSystemAppInstallState(
                                 packageName,
@@ -197,7 +197,7 @@
                                     PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED
                                     || (associatedApp.flags
                                     & ApplicationInfo.FLAG_INSTALLED) == 0) {
-                                Slog.i(TAG, "Update associated state(" + associatedApp.packageName
+                                Rlog.i(TAG, "Update associated state(" + associatedApp.packageName
                                         + "): ENABLED for user " + userId);
                                 packageManager.setSystemAppInstallState(
                                         associatedApp.packageName,
@@ -222,7 +222,7 @@
                             && ai.enabledSetting ==
                             PackageManager.COMPONENT_ENABLED_STATE_DEFAULT
                             && (ai.flags & ApplicationInfo.FLAG_INSTALLED) != 0) {
-                        Slog.i(TAG, "Update state(" + packageName
+                        Rlog.i(TAG, "Update state(" + packageName
                                 + "): DISABLED_UNTIL_USED for user " + userId);
                         packageManager.setSystemAppInstallState(
                                 packageName,
@@ -240,7 +240,7 @@
                                         == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT
                                         && (associatedApp.flags
                                         & ApplicationInfo.FLAG_INSTALLED) != 0) {
-                                    Slog.i(TAG,
+                                    Rlog.i(TAG,
                                             "Update associated state(" + associatedApp.packageName
                                                     + "): DISABLED_UNTIL_USED for user " + userId);
                                     packageManager.setSystemAppInstallState(
@@ -268,7 +268,7 @@
                 permissionManager.grantDefaultPermissionsToEnabledCarrierApps(packageNames, userId);
             }
         } catch (RemoteException e) {
-            Slog.w(TAG, "Could not reach PackageManager", e);
+            Rlog.w(TAG, "Could not reach PackageManager", e);
         }
     }
 
@@ -390,7 +390,7 @@
                 return ai;
             }
         } catch (RemoteException e) {
-            Slog.w(TAG, "Could not reach PackageManager", e);
+            Rlog.w(TAG, "Could not reach PackageManager", e);
         }
         return null;
     }
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmSmsCbMessage.java b/telephony/java/com/android/internal/telephony/gsm/GsmSmsCbMessage.java
index 5ce42fd..d03419d 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmSmsCbMessage.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmSmsCbMessage.java
@@ -30,10 +30,10 @@
 import android.telephony.CbGeoUtils.Geometry;
 import android.telephony.CbGeoUtils.LatLng;
 import android.telephony.CbGeoUtils.Polygon;
+import android.telephony.Rlog;
 import android.telephony.SmsCbLocation;
 import android.telephony.SmsCbMessage;
 import android.util.Pair;
-import android.util.Slog;
 
 import com.android.internal.R;
 import com.android.internal.telephony.GsmAlphabet;
@@ -131,7 +131,7 @@
                 } catch (Exception ex) {
                     // Catch the exception here, the message will be considered as having no WAC
                     // information which means the message will be broadcasted directly.
-                    Slog.e(TAG, "Can't parse warning area coordinates, ex = " + ex.toString());
+                    Rlog.e(TAG, "Can't parse warning area coordinates, ex = " + ex.toString());
                 }
             }
 
@@ -198,7 +198,7 @@
             }
             return new GeoFencingTriggerMessage(type, cbIdentifiers);
         } catch (Exception ex) {
-            Slog.e(TAG, "create geo-fencing trigger failed, ex = " + ex.toString());
+            Rlog.e(TAG, "create geo-fencing trigger failed, ex = " + ex.toString());
             return null;
         }
     }
diff --git a/tests/ApkVerityTest/block_device_writer/Android.bp b/tests/ApkVerityTest/block_device_writer/Android.bp
index deed3a0..e7a63e4 100644
--- a/tests/ApkVerityTest/block_device_writer/Android.bp
+++ b/tests/ApkVerityTest/block_device_writer/Android.bp
@@ -22,7 +22,13 @@
     stem: "block_device_writer",
 
     srcs: ["block_device_writer.cpp"],
-    cflags: ["-Wall", "-Werror", "-Wextra", "-g"],
+    cflags: [
+        "-D_FILE_OFFSET_BITS=64",
+        "-Wall",
+        "-Werror",
+        "-Wextra",
+        "-g",
+    ],
     shared_libs: ["libbase", "libutils"],
 
     test_suites: ["general-tests"],
diff --git a/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassBase.java b/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassBase.java
index 176c7a0..339df93 100644
--- a/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassBase.java
+++ b/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassBase.java
@@ -32,7 +32,7 @@
 
 
 
-    // Code below generated by codegen v1.0.13.
+    // Code below generated by codegen v1.0.14.
     //
     // DO NOT MODIFY!
     // CHECKSTYLE:OFF Generated code
@@ -98,8 +98,8 @@
     };
 
     @DataClass.Generated(
-            time = 1573006405823L,
-            codegenVersion = "1.0.13",
+            time = 1574122837821L,
+            codegenVersion = "1.0.14",
             sourceFile = "frameworks/base/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassBase.java",
             inputSignatures = "private  int mBaseData\nclass HierrarchicalDataClassBase extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genConstructor=false, genSetters=true)")
     @Deprecated
diff --git a/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassChild.java b/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassChild.java
index e348c77..69e06b2 100644
--- a/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassChild.java
+++ b/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassChild.java
@@ -46,7 +46,7 @@
 
 
 
-    // Code below generated by codegen v1.0.13.
+    // Code below generated by codegen v1.0.14.
     //
     // DO NOT MODIFY!
     // CHECKSTYLE:OFF Generated code
@@ -120,8 +120,8 @@
     };
 
     @DataClass.Generated(
-            time = 1573006406833L,
-            codegenVersion = "1.0.13",
+            time = 1574122838768L,
+            codegenVersion = "1.0.14",
             sourceFile = "frameworks/base/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassChild.java",
             inputSignatures = "private @android.annotation.NonNull java.lang.String mChildData\nclass HierrarchicalDataClassChild extends com.android.codegentest.HierrarchicalDataClassBase implements []\n@com.android.internal.util.DataClass(genParcelable=true, genConstructor=false, genSetters=true)")
     @Deprecated
diff --git a/tests/Codegen/src/com/android/codegentest/ParcelAllTheThingsDataClass.java b/tests/Codegen/src/com/android/codegentest/ParcelAllTheThingsDataClass.java
index 112d3df..ca128be 100644
--- a/tests/Codegen/src/com/android/codegentest/ParcelAllTheThingsDataClass.java
+++ b/tests/Codegen/src/com/android/codegentest/ParcelAllTheThingsDataClass.java
@@ -54,7 +54,7 @@
 
 
 
-    // Code below generated by codegen v1.0.13.
+    // Code below generated by codegen v1.0.14.
     //
     // DO NOT MODIFY!
     // CHECKSTYLE:OFF Generated code
@@ -291,7 +291,7 @@
 
         /** @see #setStringList */
         @DataClass.Generated.Member
-        public @NonNull Builder addStringList(String value) {
+        public @NonNull Builder addStringList(@NonNull String value) {
             // You can refine this method's name by providing item's singular name, e.g.:
             // @DataClass.PluralOf("item")) mItems = ...
 
@@ -310,7 +310,7 @@
 
         /** @see #setMap */
         @DataClass.Generated.Member
-        public @NonNull Builder addMap(String key, SampleWithCustomBuilder value) {
+        public @NonNull Builder addMap(@NonNull String key, @NonNull SampleWithCustomBuilder value) {
             // You can refine this method's name by providing item's singular name, e.g.:
             // @DataClass.PluralOf("item")) mItems = ...
 
@@ -329,7 +329,7 @@
 
         /** @see #setStringMap */
         @DataClass.Generated.Member
-        public @NonNull Builder addStringMap(String key, String value) {
+        public @NonNull Builder addStringMap(@NonNull String key, @NonNull String value) {
             // You can refine this method's name by providing item's singular name, e.g.:
             // @DataClass.PluralOf("item")) mItems = ...
 
@@ -412,8 +412,8 @@
     }
 
     @DataClass.Generated(
-            time = 1573006404728L,
-            codegenVersion = "1.0.13",
+            time = 1574122836960L,
+            codegenVersion = "1.0.14",
             sourceFile = "frameworks/base/tests/Codegen/src/com/android/codegentest/ParcelAllTheThingsDataClass.java",
             inputSignatures = " @android.annotation.NonNull java.lang.String[] mStringArray\n @android.annotation.NonNull int[] mIntArray\n @android.annotation.NonNull java.util.List<java.lang.String> mStringList\n @android.annotation.NonNull java.util.Map<java.lang.String,com.android.codegentest.SampleWithCustomBuilder> mMap\n @android.annotation.NonNull java.util.Map<java.lang.String,java.lang.String> mStringMap\n @android.annotation.NonNull android.util.SparseArray<com.android.codegentest.SampleWithCustomBuilder> mSparseArray\n @android.annotation.NonNull android.util.SparseIntArray mSparseIntArray\n @java.lang.SuppressWarnings({\"WeakerAccess\"}) @android.annotation.Nullable java.lang.Boolean mNullableBoolean\nclass ParcelAllTheThingsDataClass extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genBuilder=true, genAidl=false, genToString=true)")
     @Deprecated
diff --git a/tests/Codegen/src/com/android/codegentest/SampleDataClass.java b/tests/Codegen/src/com/android/codegentest/SampleDataClass.java
index 0fdcf59..c850bf8 100644
--- a/tests/Codegen/src/com/android/codegentest/SampleDataClass.java
+++ b/tests/Codegen/src/com/android/codegentest/SampleDataClass.java
@@ -342,7 +342,7 @@
 
 
 
-    // Code below generated by codegen v1.0.13.
+    // Code below generated by codegen v1.0.14.
     //
     // DO NOT MODIFY!
     // CHECKSTYLE:OFF Generated code
@@ -1636,7 +1636,7 @@
 
         /** @see #setLinkAddresses2 */
         @DataClass.Generated.Member
-        public @NonNull Builder addLinkAddresses2(LinkAddress value) {
+        public @NonNull Builder addLinkAddresses2(@NonNull LinkAddress value) {
             // You can refine this method's name by providing item's singular name, e.g.:
             // @DataClass.PluralOf("item")) mItems = ...
 
@@ -1661,7 +1661,7 @@
 
         /** @see #setLinkAddresses */
         @DataClass.Generated.Member
-        public @NonNull Builder addLinkAddress(LinkAddress value) {
+        public @NonNull Builder addLinkAddress(@NonNull LinkAddress value) {
             if (mLinkAddresses == null) setLinkAddresses(new ArrayList<>());
             mLinkAddresses.add(value);
             return this;
@@ -1872,8 +1872,8 @@
     }
 
     @DataClass.Generated(
-            time = 1573006402566L,
-            codegenVersion = "1.0.13",
+            time = 1574122835009L,
+            codegenVersion = "1.0.14",
             sourceFile = "frameworks/base/tests/Codegen/src/com/android/codegentest/SampleDataClass.java",
             inputSignatures = "public static final  java.lang.String STATE_NAME_UNDEFINED\npublic static final  java.lang.String STATE_NAME_ON\npublic static final  java.lang.String STATE_NAME_OFF\npublic static final  int STATE_UNDEFINED\npublic static final  int STATE_ON\npublic static final  int STATE_OFF\npublic static final @com.android.codegentest.SampleDataClass.RequestFlags int FLAG_MANUAL_REQUEST\npublic static final @com.android.codegentest.SampleDataClass.RequestFlags int FLAG_COMPATIBILITY_MODE_REQUEST\npublic static final @com.android.codegentest.SampleDataClass.RequestFlags int FLAG_AUGMENTED_REQUEST\nprivate  int mNum\nprivate  int mNum2\nprivate  int mNum4\nprivate @android.annotation.Nullable java.lang.String mName\nprivate @android.annotation.NonNull java.lang.String mName2\nprivate @android.annotation.NonNull java.lang.String mName4\nprivate @android.annotation.Nullable android.view.accessibility.AccessibilityNodeInfo mOtherParcelable\nprivate @com.android.internal.util.DataClass.ParcelWith(com.android.codegentest.MyDateParcelling.class) @android.annotation.NonNull java.util.Date mDate\nprivate @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForPattern.class) @android.annotation.NonNull java.util.regex.Pattern mPattern\nprivate @android.annotation.NonNull java.util.List<android.net.LinkAddress> mLinkAddresses2\nprivate @com.android.internal.util.DataClass.PluralOf(\"linkAddress\") @android.annotation.NonNull java.util.ArrayList<android.net.LinkAddress> mLinkAddresses\nprivate @android.annotation.Nullable android.net.LinkAddress[] mLinkAddresses4\nprivate @com.android.codegentest.SampleDataClass.StateName @android.annotation.NonNull java.lang.String mStateName\nprivate @com.android.codegentest.SampleDataClass.RequestFlags int mFlags\nprivate @com.android.codegentest.SampleDataClass.State int mState\npublic @android.annotation.NonNull java.lang.CharSequence charSeq\nprivate final @android.annotation.Nullable android.net.LinkAddress[] mLinkAddresses5\nprivate transient  android.net.LinkAddress[] mLinkAddresses6\ntransient  int[] mTmpStorage\nprivate @android.annotation.StringRes int mStringRes\nprivate @android.annotation.IntRange(from=0L, to=6L) int mDayOfWeek\nprivate @android.annotation.Size(2L) @android.annotation.NonNull @com.android.internal.util.DataClass.Each @android.annotation.FloatRange(from=0.0) float[] mCoords\nprivate static  java.lang.String defaultName4()\nprivate  int[] lazyInitTmpStorage()\npublic  android.net.LinkAddress[] getLinkAddresses4()\nprivate  boolean patternEquals(java.util.regex.Pattern)\nprivate  int patternHashCode()\nprivate  void onConstructed()\npublic  void dump(java.io.PrintWriter)\nclass SampleDataClass extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genBuilder=true, genConstructor=true, genEqualsHashCode=true, genToString=true, genForEachField=true, genSetters=true)")
     @Deprecated
diff --git a/tests/Codegen/src/com/android/codegentest/SampleWithCustomBuilder.java b/tests/Codegen/src/com/android/codegentest/SampleWithCustomBuilder.java
index cab477d..2de848c 100644
--- a/tests/Codegen/src/com/android/codegentest/SampleWithCustomBuilder.java
+++ b/tests/Codegen/src/com/android/codegentest/SampleWithCustomBuilder.java
@@ -85,7 +85,7 @@
 
 
 
-    // Code below generated by codegen v1.0.13.
+    // Code below generated by codegen v1.0.14.
     //
     // DO NOT MODIFY!
     // CHECKSTYLE:OFF Generated code
@@ -253,8 +253,8 @@
     }
 
     @DataClass.Generated(
-            time = 1573006403628L,
-            codegenVersion = "1.0.13",
+            time = 1574122835982L,
+            codegenVersion = "1.0.14",
             sourceFile = "frameworks/base/tests/Codegen/src/com/android/codegentest/SampleWithCustomBuilder.java",
             inputSignatures = "  long delayAmount\n @android.annotation.NonNull java.util.concurrent.TimeUnit delayUnit\n  long creationTimestamp\nprivate static  java.util.concurrent.TimeUnit unparcelDelayUnit(android.os.Parcel)\nprivate  void parcelDelayUnit(android.os.Parcel,int)\nclass SampleWithCustomBuilder extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genBuilder=true, genAidl=false, genToString=true)\nabstract  com.android.codegentest.SampleWithCustomBuilder.Builder setDelayAmount(long)\npublic abstract  com.android.codegentest.SampleWithCustomBuilder.Builder setDelayUnit(java.util.concurrent.TimeUnit)\npublic  com.android.codegentest.SampleWithCustomBuilder.Builder setDelay(long,java.util.concurrent.TimeUnit)\nclass BaseBuilder extends java.lang.Object implements []")
     @Deprecated
diff --git a/tests/Codegen/src/com/android/codegentest/SampleWithNestedDataClasses.java b/tests/Codegen/src/com/android/codegentest/SampleWithNestedDataClasses.java
index 6190085..0deffe4 100644
--- a/tests/Codegen/src/com/android/codegentest/SampleWithNestedDataClasses.java
+++ b/tests/Codegen/src/com/android/codegentest/SampleWithNestedDataClasses.java
@@ -36,7 +36,7 @@
 
 
 
-        // Code below generated by codegen v1.0.13.
+        // Code below generated by codegen v1.0.14.
         //
         // DO NOT MODIFY!
         // CHECKSTYLE:OFF Generated code
@@ -135,8 +135,8 @@
         };
 
         @DataClass.Generated(
-                time = 1573006408903L,
-                codegenVersion = "1.0.13",
+                time = 1574122840588L,
+                codegenVersion = "1.0.14",
                 sourceFile = "frameworks/base/tests/Codegen/src/com/android/codegentest/SampleWithNestedDataClasses.java",
                 inputSignatures = " @android.annotation.NonNull java.lang.String mBar\nclass NestedDataClass extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true)")
         @Deprecated
@@ -160,7 +160,7 @@
 
 
 
-            // Code below generated by codegen v1.0.13.
+            // Code below generated by codegen v1.0.14.
             //
             // DO NOT MODIFY!
             // CHECKSTYLE:OFF Generated code
@@ -259,8 +259,8 @@
             };
 
             @DataClass.Generated(
-                    time = 1573006408912L,
-                    codegenVersion = "1.0.13",
+                    time = 1574122840597L,
+                    codegenVersion = "1.0.14",
                     sourceFile = "frameworks/base/tests/Codegen/src/com/android/codegentest/SampleWithNestedDataClasses.java",
                     inputSignatures = " @android.annotation.NonNull long mBaz2\nclass NestedDataClass3 extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true)")
             @Deprecated
@@ -274,7 +274,7 @@
 
 
 
-        // Code below generated by codegen v1.0.13.
+        // Code below generated by codegen v1.0.14.
         //
         // DO NOT MODIFY!
         // CHECKSTYLE:OFF Generated code
@@ -373,8 +373,8 @@
         };
 
         @DataClass.Generated(
-                time = 1573006408917L,
-                codegenVersion = "1.0.13",
+                time = 1574122840608L,
+                codegenVersion = "1.0.14",
                 sourceFile = "frameworks/base/tests/Codegen/src/com/android/codegentest/SampleWithNestedDataClasses.java",
                 inputSignatures = " @android.annotation.NonNull java.lang.String mBaz\nclass NestedDataClass2 extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true)")
         @Deprecated
diff --git a/tests/Codegen/src/com/android/codegentest/StaleDataclassDetectorFalsePositivesTest.java b/tests/Codegen/src/com/android/codegentest/StaleDataclassDetectorFalsePositivesTest.java
index 5a960d7..712722b 100644
--- a/tests/Codegen/src/com/android/codegentest/StaleDataclassDetectorFalsePositivesTest.java
+++ b/tests/Codegen/src/com/android/codegentest/StaleDataclassDetectorFalsePositivesTest.java
@@ -51,7 +51,7 @@
 
 
 
-    // Code below generated by codegen v1.0.13.
+    // Code below generated by codegen v1.0.14.
     //
     // DO NOT MODIFY!
     // CHECKSTYLE:OFF Generated code
@@ -65,8 +65,8 @@
 
 
     @DataClass.Generated(
-            time = 1573006407900L,
-            codegenVersion = "1.0.13",
+            time = 1574122839646L,
+            codegenVersion = "1.0.14",
             sourceFile = "frameworks/base/tests/Codegen/src/com/android/codegentest/StaleDataclassDetectorFalsePositivesTest.java",
             inputSignatures = "public @android.annotation.NonNull java.lang.String someMethod(int)\nclass StaleDataclassDetectorFalsePositivesTest extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genConstructor=false, genBuilder=false)")
     @Deprecated
diff --git a/tools/codegen/src/com/android/codegen/ClassPrinter.kt b/tools/codegen/src/com/android/codegen/ClassPrinter.kt
index a4fd374..c7c80ba 100644
--- a/tools/codegen/src/com/android/codegen/ClassPrinter.kt
+++ b/tools/codegen/src/com/android/codegen/ClassPrinter.kt
@@ -164,7 +164,13 @@
         getSuppressedMembers(classAst)
     }
     val builderSuppressedMembers by lazy {
-        getSuppressedMembers(customBaseBuilderAst)
+        getSuppressedMembers(customBaseBuilderAst) + suppressedMembers.mapNotNull {
+            if (it.startsWith("$CANONICAL_BUILDER_CLASS.")) {
+                it.removePrefix("$CANONICAL_BUILDER_CLASS.")
+            } else {
+                null
+            }
+        }
     }
 
     private fun getSuppressedMembers(clazz: ClassOrInterfaceDeclaration?): List<String> {
diff --git a/tools/codegen/src/com/android/codegen/Generators.kt b/tools/codegen/src/com/android/codegen/Generators.kt
index dc1f4c5..8fe243f 100644
--- a/tools/codegen/src/com/android/codegen/Generators.kt
+++ b/tools/codegen/src/com/android/codegen/Generators.kt
@@ -270,7 +270,7 @@
 private fun ClassPrinter.generateBuilderMethod(
         defVisibility: String,
         name: String,
-        ParamAnnotations: String? = null,
+        paramAnnotations: String? = null,
         paramTypes: List<String>,
         paramNames: List<String> = listOf("value"),
         genJavadoc: ClassPrinter.() -> Unit,
@@ -292,8 +292,12 @@
         +GENERATED_MEMBER_HEADER
         if (providedMethod?.isAbstract == true) +"@Override"
         if (!Annotations.isNullOrEmpty()) +Annotations
-        "$visibility @$NonNull $ReturnType $name(${if_(!ParamAnnotations.isNullOrEmpty(), "$ParamAnnotations ")}${
-                paramTypes.zip(paramNames).joinToString(", ") { (Type, paramName) -> "$Type $paramName" }
+        val ParamAnnotations = if (!paramAnnotations.isNullOrEmpty()) "$paramAnnotations " else ""
+
+        "$visibility @$NonNull $ReturnType $name(${
+            paramTypes.zip(paramNames).joinToString(", ") { (Type, paramName) ->
+                "$ParamAnnotations$Type $paramName"
+            }
         })" {
             genBody()
         }
@@ -311,7 +315,7 @@
         generateBuilderMethod(
                 name = setterName,
                 defVisibility = visibility,
-                ParamAnnotations = annotationsNoInternal.joinToString(" "),
+                paramAnnotations = annotationsNoInternal.joinToString(" "),
                 paramTypes = listOf(SetterParamType),
                 genJavadoc = { generateFieldJavadoc() }) {
             +"checkNotUsed();"
@@ -333,6 +337,7 @@
             generateBuilderMethod(
                     name = adderName,
                     defVisibility = visibility,
+                    paramAnnotations = "@$NonNull",
                     paramTypes = listOf(FieldInnerType),
                     genJavadoc = { +javadocSeeSetter }) {
 
@@ -347,6 +352,7 @@
             generateBuilderMethod(
                     name = adderName,
                     defVisibility = visibility,
+                    paramAnnotations = "@$NonNull",
                     paramTypes = fieldTypeGenegicArgs,
                     paramNames = listOf("key", "value"),
                     genJavadoc = { +javadocSeeSetter }) {
diff --git a/tools/codegen/src/com/android/codegen/SharedConstants.kt b/tools/codegen/src/com/android/codegen/SharedConstants.kt
index 85c832f..74c86f4 100644
--- a/tools/codegen/src/com/android/codegen/SharedConstants.kt
+++ b/tools/codegen/src/com/android/codegen/SharedConstants.kt
@@ -1,7 +1,7 @@
 package com.android.codegen
 
 const val CODEGEN_NAME = "codegen"
-const val CODEGEN_VERSION = "1.0.13"
+const val CODEGEN_VERSION = "1.0.14"
 
 const val CANONICAL_BUILDER_CLASS = "Builder"
 const val BASE_BUILDER_CLASS = "BaseBuilder"
diff --git a/tools/stats_log_api_gen/main.cpp b/tools/stats_log_api_gen/main.cpp
index f62fef0..18e2da3 100644
--- a/tools/stats_log_api_gen/main.cpp
+++ b/tools/stats_log_api_gen/main.cpp
@@ -1309,7 +1309,7 @@
         fprintf(out, "            write_non_chained(code");
         for (int argIndex = 1; argIndex <= argIndexMax; argIndex++) {
             if (argIndex == attributionArg) {
-                fprintf(out, ", ws.get(i), ws.getName(i)");
+                fprintf(out, ", ws.getUid(i), ws.getPackageName(i)");
             } else {
                fprintf(out, ", arg%d", argIndex);
             }
@@ -1318,7 +1318,7 @@
         fprintf(out, "        }\n"); // close for-loop
 
         // write() component.
-        fprintf(out, "        ArrayList<WorkSource.WorkChain> workChains = ws.getWorkChains();\n");
+        fprintf(out, "        List<WorkSource.WorkChain> workChains = ws.getWorkChains();\n");
         fprintf(out, "        if (workChains != null) {\n");
         fprintf(out, "            for (WorkSource.WorkChain wc : workChains) {\n");
         fprintf(out, "                write(code");
@@ -1407,7 +1407,7 @@
     fprintf(out, "\n");
     fprintf(out, "import android.os.WorkSource;\n");
     fprintf(out, "import android.util.SparseArray;\n");
-    fprintf(out, "import java.util.ArrayList;\n");
+    fprintf(out, "import java.util.List;\n");
     fprintf(out, "\n");
     fprintf(out, "\n");
     fprintf(out, "/**\n");
diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl
index bbb8544..4619372 100644
--- a/wifi/java/android/net/wifi/IWifiManager.aidl
+++ b/wifi/java/android/net/wifi/IWifiManager.aidl
@@ -161,8 +161,6 @@
 
     boolean setWifiApConfiguration(in WifiConfiguration wifiConfig, String packageName);
 
-    void notifyUserOfApBandConversion(String packageName);
-
     void enableTdls(String remoteIPAddress, boolean enable);
 
     void enableTdlsWithMacAddress(String remoteMacAddress, boolean enable);
@@ -242,4 +240,6 @@
     void registerSuggestionConnectionStatusListener(in IBinder binder, in ISuggestionConnectionStatusListener listener, int listenerIdentifier, String packageName, String featureId);
 
     void unregisterSuggestionConnectionStatusListener(int listenerIdentifier, String packageName);
+
+    int calculateSignalLevel(int rssi);
 }
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index f7d2b40..90343d4 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -384,7 +384,12 @@
     public void setSecurityParams(@SecurityType int securityType) {
         // Clear all the bitsets.
         allowedKeyManagement.clear();
+        allowedProtocols.clear();
         allowedAuthAlgorithms.clear();
+        allowedPairwiseCiphers.clear();
+        allowedGroupCiphers.clear();
+        allowedGroupManagementCiphers.clear();
+        allowedSuiteBCiphers.clear();
 
         switch (securityType) {
             case SECURITY_TYPE_OPEN:
@@ -407,9 +412,6 @@
                 requirePMF = true;
                 break;
             case SECURITY_TYPE_EAP_SUITE_B:
-                allowedGroupCiphers.clear();
-                allowedGroupManagementCiphers.clear();
-                allowedSuiteBCiphers.clear();
                 allowedKeyManagement.set(WifiConfiguration.KeyMgmt.SUITE_B_192);
                 allowedGroupCiphers.set(WifiConfiguration.GroupCipher.GCMP_256);
                 allowedGroupManagementCiphers.set(WifiConfiguration.GroupMgmtCipher.BIP_GMAC_256);
@@ -945,12 +947,6 @@
     public int meteredOverride = METERED_OVERRIDE_NONE;
 
     /**
-     * This Wifi configuration is a clone of another network with lower security
-     * @hide
-     */
-    public String clonedNetworkConfigKey;
-
-    /**
      * Blend together all the various opinions to decide if the given network
      * should be considered metered or not.
      *
@@ -1808,7 +1804,6 @@
         shared = true;
         dtimInterval = 0;
         mRandomizedMacAddress = MacAddress.fromString(WifiInfo.DEFAULT_MAC_ADDRESS);
-        clonedNetworkConfigKey = null;
     }
 
     /**
@@ -2376,7 +2371,6 @@
 
     /** copy constructor {@hide} */
     @UnsupportedAppUsage
-
     public WifiConfiguration(WifiConfiguration source) {
         if (source != null) {
             networkId = source.networkId;
@@ -2460,7 +2454,6 @@
             requirePMF = source.requirePMF;
             updateIdentifier = source.updateIdentifier;
             carrierId = source.carrierId;
-            clonedNetworkConfigKey = source.clonedNetworkConfigKey;
         }
     }
 
@@ -2536,7 +2529,6 @@
         dest.writeInt(osu ? 1 : 0);
         dest.writeLong(randomizedMacExpirationTimeMs);
         dest.writeInt(carrierId);
-        dest.writeString(clonedNetworkConfigKey);
     }
 
     /** Implement the Parcelable interface {@hide} */
@@ -2614,7 +2606,6 @@
                 config.osu = in.readInt() != 0;
                 config.randomizedMacExpirationTimeMs = in.readLong();
                 config.carrierId = in.readInt();
-                config.clonedNetworkConfigKey = in.readString();
                 return config;
             }
 
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 56f152e..77666b0 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -1153,8 +1153,6 @@
      * @hide
      */
     @UnsupportedAppUsage
-    // TODO(b/140781184): need to support custom number of RSSI levels, as well as levels that are
-    //  not evenly spaced
     public static final int RSSI_LEVELS = 5;
 
     /**
@@ -2782,11 +2780,13 @@
      * is being shown.
      *
      * @param rssi The power of the signal measured in RSSI.
-     * @param numLevels The number of levels to consider in the calculated
-     *            level.
-     * @return A level of the signal, given in the range of 0 to numLevels-1
-     *         (both inclusive).
+     * @param numLevels The number of levels to consider in the calculated level.
+     * @return A level of the signal, given in the range of 0 to numLevels-1 (both inclusive).
+     * @deprecated Callers should use {@link #calculateSignalLevel(int)} instead to get the
+     * signal level using the system default RSSI thresholds, or otherwise compute the RSSI level
+     * themselves using their own formula.
      */
+    @Deprecated
     public static int calculateSignalLevel(int rssi, int numLevels) {
         if (rssi <= MIN_RSSI) {
             return 0;
@@ -2800,6 +2800,34 @@
     }
 
     /**
+     * Given a raw RSSI, return the RSSI signal quality rating using the system default RSSI
+     * quality rating thresholds.
+     * @param rssi a raw RSSI value, in dBm, usually between -55 and -90
+     * @return the RSSI signal quality rating, in the range
+     * [0, {@link #getMaxSignalLevel()}], where 0 is the lowest (worst signal) RSSI
+     * rating and {@link #getMaxSignalLevel()} is the highest (best signal) RSSI rating.
+     */
+    public int calculateSignalLevel(int rssi) {
+        try {
+            IWifiManager iWifiManager = getIWifiManager();
+            if (iWifiManager == null) {
+                throw new RemoteException("Wifi service is not running");
+            }
+            return iWifiManager.calculateSignalLevel(rssi);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Get the system default maximum signal level.
+     * This is the maximum RSSI level returned by {@link #calculateSignalLevel(int)}.
+     */
+    public int getMaxSignalLevel() {
+        return calculateSignalLevel(Integer.MAX_VALUE);
+    }
+
+    /**
      * Compares two signal strengths.
      *
      * @param rssiA The power of the first signal measured in RSSI.
@@ -3207,27 +3235,6 @@
     }
 
     /**
-     * Method that triggers a notification to the user about a band conversion
-     * (e.g. 5 GHz to 2.4 GHz) to their saved AP config.
-     *
-     * @hide
-     */
-    // TODO(b/144218444): move the notification to Settings instead of making this @SystemApi
-    @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
-    public void notifyUserOfApBandConversion() {
-        Log.d(TAG, "apBand was converted, notify the user");
-        try {
-            IWifiManager iWifiManager = getIWifiManager();
-            if (iWifiManager == null) {
-                throw new RemoteException("Wifi service is not running");
-            }
-            iWifiManager.notifyUserOfApBandConversion(mContext.getOpPackageName());
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    /**
      * Enable/Disable TDLS on a specific local route.
      *
      * <p>
@@ -4327,7 +4334,7 @@
                 if (ws == null) {
                     mWorkSource = null;
                 } else {
-                    ws.clearNames();
+                    ws = ws.withoutNames();
                     if (mWorkSource == null) {
                         changed = mWorkSource != null;
                         mWorkSource = new WorkSource(ws);
diff --git a/wifi/java/com/android/server/wifi/BaseWifiService.java b/wifi/java/com/android/server/wifi/BaseWifiService.java
index cf74ff0..ee03c11 100644
--- a/wifi/java/com/android/server/wifi/BaseWifiService.java
+++ b/wifi/java/com/android/server/wifi/BaseWifiService.java
@@ -42,7 +42,6 @@
 import android.net.wifi.hotspot2.OsuProvider;
 import android.net.wifi.hotspot2.PasspointConfiguration;
 import android.os.IBinder;
-import android.os.Messenger;
 import android.os.RemoteException;
 import android.os.ResultReceiver;
 import android.os.WorkSource;
@@ -325,7 +324,6 @@
         throw new UnsupportedOperationException();
     }
 
-    @Override
     public void notifyUserOfApBandConversion(String packageName) {
         throw new UnsupportedOperationException();
     }
@@ -537,4 +535,9 @@
             String packageName) {
         throw new UnsupportedOperationException();
     }
+
+    @Override
+    public int calculateSignalLevel(int rssi) {
+        throw new UnsupportedOperationException();
+    }
 }
diff --git a/wifi/tests/src/android/net/wifi/WifiManagerTest.java b/wifi/tests/src/android/net/wifi/WifiManagerTest.java
index 06ebc1b..507d502 100644
--- a/wifi/tests/src/android/net/wifi/WifiManagerTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiManagerTest.java
@@ -1899,8 +1899,25 @@
      */
     @Test
     public void testRemoveSuggestionConnectionListener() throws Exception {
-
         mWifiManager.removeSuggestionConnectionStatusListener(mListener);
         verify(mWifiService).unregisterSuggestionConnectionStatusListener(anyInt(), anyString());
     }
+
+    /** Test {@link WifiManager#calculateSignalLevel(int)} */
+    @Test
+    public void testCalculateSignalLevel() throws Exception {
+        when(mWifiService.calculateSignalLevel(anyInt())).thenReturn(3);
+        int actual = mWifiManager.calculateSignalLevel(-60);
+        verify(mWifiService).calculateSignalLevel(-60);
+        assertEquals(3, actual);
+    }
+
+    /** Test {@link WifiManager#getMaxSignalLevel()} */
+    @Test
+    public void testGetMaxSignalLevel() throws Exception {
+        when(mWifiService.calculateSignalLevel(anyInt())).thenReturn(4);
+        int actual = mWifiManager.getMaxSignalLevel();
+        verify(mWifiService).calculateSignalLevel(Integer.MAX_VALUE);
+        assertEquals(4, actual);
+    }
 }