Merge "Rearrange listener logic so it can be overriden"
diff --git a/Android.bp b/Android.bp
index ea14b9d..a082085 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",
@@ -1083,6 +1086,7 @@
         ":core-current-stubs-source",
         ":core_public_api_files",
         ":updatable-media-srcs",
+        ":ike-api-srcs",
     ],
     libs: ["framework-internal-utils"],
     installable: false,
@@ -1405,8 +1409,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/CleanSpec.mk b/CleanSpec.mk
index f7a2858..8fac394 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -255,6 +255,7 @@
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/app/CaptivePortalLogin)
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/framework/ext.jar)
 $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/telephony/java/com/google/android/mms)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/framework/*-service.jar)
 # ******************************************************************
 # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST ABOVE THIS BANNER
 # ******************************************************************
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..2cd7aa0
--- /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: "service-appsearch",
+  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/apex/blobstore/service/Android.bp b/apex/blobstore/service/Android.bp
index 019f989..d8caa5a 100644
--- a/apex/blobstore/service/Android.bp
+++ b/apex/blobstore/service/Android.bp
@@ -13,7 +13,7 @@
 // limitations under the License.
 
 java_library {
-    name: "blobstore-service",
+    name: "service-blobstore",
     installable: true,
 
     srcs: [
@@ -24,4 +24,4 @@
         "framework",
         "services.core",
     ],
-}
\ No newline at end of file
+}
diff --git a/apex/jobscheduler/README_js-mainline.md b/apex/jobscheduler/README_js-mainline.md
index ea20e3e..134ff3d 100644
--- a/apex/jobscheduler/README_js-mainline.md
+++ b/apex/jobscheduler/README_js-mainline.md
@@ -2,14 +2,14 @@
 
 ## Current structure
 
-- JS service side classes are put in `jobscheduler-service.jar`.
+- JS service side classes are put in `service-jobscheduler.jar`.
 It's *not* included in services.jar, and instead it's put in the system server classpath,
 which currently looks like the following:
-`SYSTEMSERVERCLASSPATH=/system/framework/services.jar:/system/framework/ethernet-service.jar:/system/framework/com.android.location.provider.jar:/system/framework/jobscheduler-service.jar`
+`SYSTEMSERVERCLASSPATH=/system/framework/services.jar:/system/framework/ethernet-service.jar:/system/framework/com.android.location.provider.jar:/system/framework/service-jobscheduler.jar`
 
   `SYSTEMSERVERCLASSPATH` is generated from `PRODUCT_SYSTEM_SERVER_JARS`.
 
-- JS framework side classes are put in `jobscheduler-framework.jar`,
+- JS framework side classes are put in `framework-jobscheduler.jar`,
 and the rest of the framework code is put in `framework-minus-apex.jar`,
 as of http://ag/9145619.
 
diff --git a/apex/jobscheduler/framework/Android.bp b/apex/jobscheduler/framework/Android.bp
index 3902aa2..98bbe82 100644
--- a/apex/jobscheduler/framework/Android.bp
+++ b/apex/jobscheduler/framework/Android.bp
@@ -11,7 +11,7 @@
 }
 
 java_library {
-    name: "jobscheduler-framework",
+    name: "framework-jobscheduler",
     installable: false,
     compile_dex: true,
     sdk_version: "core_platform",
diff --git a/apex/jobscheduler/framework/java/android/app/job/JobSchedulerFrameworkInitializer.java b/apex/jobscheduler/framework/java/android/app/job/JobSchedulerFrameworkInitializer.java
index f3ec5e5..3835d93 100644
--- a/apex/jobscheduler/framework/java/android/app/job/JobSchedulerFrameworkInitializer.java
+++ b/apex/jobscheduler/framework/java/android/app/job/JobSchedulerFrameworkInitializer.java
@@ -21,6 +21,7 @@
 import android.content.Context;
 import android.os.DeviceIdleManager;
 import android.os.IDeviceIdleController;
+import android.os.PowerWhitelistManager;
 
 /**
  * Class holding initialization code for the job scheduler module.
@@ -48,5 +49,8 @@
                 Context.DEVICE_IDLE_CONTROLLER, DeviceIdleManager.class,
                 (context, b) -> new DeviceIdleManager(
                         context, IDeviceIdleController.Stub.asInterface(b)));
+        SystemServiceRegistry.registerContextAwareService(
+                Context.POWER_WHITELIST_MANAGER, PowerWhitelistManager.class,
+                PowerWhitelistManager::new);
     }
 }
diff --git a/apex/jobscheduler/framework/java/android/os/PowerWhitelistManager.java b/apex/jobscheduler/framework/java/android/os/PowerWhitelistManager.java
new file mode 100644
index 0000000..06ed52d
--- /dev/null
+++ b/apex/jobscheduler/framework/java/android/os/PowerWhitelistManager.java
@@ -0,0 +1,42 @@
+/*
+ * 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.NonNull;
+import android.annotation.SystemApi;
+import android.annotation.SystemService;
+import android.annotation.TestApi;
+import android.content.Context;
+
+/**
+ * Interface to access and modify the power save whitelist.
+ *
+ * @hide
+ */
+@SystemApi
+@TestApi
+@SystemService(Context.POWER_WHITELIST_MANAGER)
+public class PowerWhitelistManager {
+    private final Context mContext;
+
+    /**
+     * @hide
+     */
+    public PowerWhitelistManager(@NonNull Context context) {
+        mContext = context;
+    }
+}
diff --git a/apex/jobscheduler/service/Android.bp b/apex/jobscheduler/service/Android.bp
index ca6dc45..c9d9d6c 100644
--- a/apex/jobscheduler/service/Android.bp
+++ b/apex/jobscheduler/service/Android.bp
@@ -1,7 +1,7 @@
 // Job Scheduler Service jar, which will eventually be put in the jobscheduler mainline apex.
-// jobscheduler-service needs to be added to PRODUCT_SYSTEM_SERVER_JARS.
+// service-jobscheduler needs to be added to PRODUCT_SYSTEM_SERVER_JARS.
 java_library {
-    name: "jobscheduler-service",
+    name: "service-jobscheduler",
     installable: true,
 
     srcs: [
diff --git a/apex/statsd/service/Android.bp b/apex/statsd/service/Android.bp
index 786e8b0..f71d74f 100644
--- a/apex/statsd/service/Android.bp
+++ b/apex/statsd/service/Android.bp
@@ -1,8 +1,8 @@
 // Statsd Service jar, which will eventually be put in the statsd mainline apex.
-// statsd-service needs to be added to PRODUCT_SYSTEM_SERVER_JARS.
+// service-statsd needs to be added to PRODUCT_SYSTEM_SERVER_JARS.
 // This jar will contain StatsCompanionService
 java_library {
-    name: "statsd-service",
+    name: "service-statsd",
     installable: true,
 
     srcs: [
@@ -13,4 +13,4 @@
         "framework",
         "services.core",
     ],
-}
\ No newline at end of file
+}
diff --git a/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java b/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java
index 8a00c83..a6cc06f 100644
--- a/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java
+++ b/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java
@@ -2076,6 +2076,7 @@
     private void pullDangerousPermissionState(long elapsedNanos, final long wallClockNanos,
             List<StatsLogEventWrapper> pulledData) {
         long token = Binder.clearCallingIdentity();
+        Set<Integer> reportedUids = new HashSet<>();
         try {
             PackageManager pm = mContext.getPackageManager();
 
@@ -2096,6 +2097,12 @@
                         continue;
                     }
 
+                    if (reportedUids.contains(pkg.applicationInfo.uid)) {
+                        // do not report same uid twice
+                        continue;
+                    }
+                    reportedUids.add(pkg.applicationInfo.uid);
+
                     int numPerms = pkg.requestedPermissions.length;
                     for (int permNum  = 0; permNum < numPerms; permNum++) {
                         String permName = pkg.requestedPermissions[permNum];
@@ -2120,7 +2127,7 @@
 
                         e.writeString(permName);
                         e.writeInt(pkg.applicationInfo.uid);
-                        e.writeString(pkg.packageName);
+                        e.writeString(null);
                         e.writeBoolean((pkg.requestedPermissionsFlags[permNum]
                                 & REQUESTED_PERMISSION_GRANTED) != 0);
                         e.writeInt(permissionFlags);
diff --git a/api/current.txt b/api/current.txt
index 1728c53..c2939fd 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -2955,7 +2955,6 @@
     field public static final int FEEDBACK_SPOKEN = 1; // 0x1
     field public static final int FEEDBACK_VISUAL = 8; // 0x8
     field public static final int FLAG_ENABLE_ACCESSIBILITY_VOLUME = 128; // 0x80
-    field public static final int FLAG_HANDLE_SHORTCUT = 2048; // 0x800
     field public static final int FLAG_INCLUDE_NOT_IMPORTANT_VIEWS = 2; // 0x2
     field public static final int FLAG_REPORT_VIEW_IDS = 16; // 0x10
     field public static final int FLAG_REQUEST_ACCESSIBILITY_BUTTON = 256; // 0x100
@@ -4760,18 +4759,18 @@
     field public static final int VISIBILITY_VISIBLE_NOTIFY_ONLY_COMPLETION = 3; // 0x3
   }
 
-  public class ExpandableListActivity extends android.app.Activity implements android.widget.ExpandableListView.OnChildClickListener android.widget.ExpandableListView.OnGroupCollapseListener android.widget.ExpandableListView.OnGroupExpandListener android.view.View.OnCreateContextMenuListener {
-    ctor public ExpandableListActivity();
-    method public android.widget.ExpandableListAdapter getExpandableListAdapter();
-    method public android.widget.ExpandableListView getExpandableListView();
-    method public long getSelectedId();
-    method public long getSelectedPosition();
-    method public boolean onChildClick(android.widget.ExpandableListView, android.view.View, int, int, long);
-    method public void onGroupCollapse(int);
-    method public void onGroupExpand(int);
-    method public void setListAdapter(android.widget.ExpandableListAdapter);
-    method public boolean setSelectedChild(int, int, boolean);
-    method public void setSelectedGroup(int);
+  @Deprecated public class ExpandableListActivity extends android.app.Activity implements android.widget.ExpandableListView.OnChildClickListener android.widget.ExpandableListView.OnGroupCollapseListener android.widget.ExpandableListView.OnGroupExpandListener android.view.View.OnCreateContextMenuListener {
+    ctor @Deprecated public ExpandableListActivity();
+    method @Deprecated public android.widget.ExpandableListAdapter getExpandableListAdapter();
+    method @Deprecated public android.widget.ExpandableListView getExpandableListView();
+    method @Deprecated public long getSelectedId();
+    method @Deprecated public long getSelectedPosition();
+    method @Deprecated public boolean onChildClick(android.widget.ExpandableListView, android.view.View, int, int, long);
+    method @Deprecated public void onGroupCollapse(int);
+    method @Deprecated public void onGroupExpand(int);
+    method @Deprecated public void setListAdapter(android.widget.ExpandableListAdapter);
+    method @Deprecated public boolean setSelectedChild(int, int, boolean);
+    method @Deprecated public void setSelectedGroup(int);
   }
 
   @Deprecated public class Fragment implements android.content.ComponentCallbacks2 android.view.View.OnCreateContextMenuListener {
@@ -5213,40 +5212,40 @@
     method @Deprecated public void onKeyguardExitResult(boolean);
   }
 
-  public abstract class LauncherActivity extends android.app.ListActivity {
-    ctor public LauncherActivity();
-    method protected android.content.Intent getTargetIntent();
-    method protected android.content.Intent intentForPosition(int);
-    method protected android.app.LauncherActivity.ListItem itemForPosition(int);
-    method public java.util.List<android.app.LauncherActivity.ListItem> makeListItems();
-    method protected java.util.List<android.content.pm.ResolveInfo> onQueryPackageManager(android.content.Intent);
-    method protected void onSetContentView();
+  @Deprecated public abstract class LauncherActivity extends android.app.ListActivity {
+    ctor @Deprecated public LauncherActivity();
+    method @Deprecated protected android.content.Intent getTargetIntent();
+    method @Deprecated protected android.content.Intent intentForPosition(int);
+    method @Deprecated protected android.app.LauncherActivity.ListItem itemForPosition(int);
+    method @Deprecated public java.util.List<android.app.LauncherActivity.ListItem> makeListItems();
+    method @Deprecated protected java.util.List<android.content.pm.ResolveInfo> onQueryPackageManager(android.content.Intent);
+    method @Deprecated protected void onSetContentView();
   }
 
-  public class LauncherActivity.IconResizer {
-    ctor public LauncherActivity.IconResizer();
-    method public android.graphics.drawable.Drawable createIconThumbnail(android.graphics.drawable.Drawable);
+  @Deprecated public class LauncherActivity.IconResizer {
+    ctor @Deprecated public LauncherActivity.IconResizer();
+    method @Deprecated public android.graphics.drawable.Drawable createIconThumbnail(android.graphics.drawable.Drawable);
   }
 
-  public static class LauncherActivity.ListItem {
-    ctor public LauncherActivity.ListItem();
-    field public String className;
-    field public android.os.Bundle extras;
-    field public android.graphics.drawable.Drawable icon;
-    field public CharSequence label;
-    field public String packageName;
-    field public android.content.pm.ResolveInfo resolveInfo;
+  @Deprecated public static class LauncherActivity.ListItem {
+    ctor @Deprecated public LauncherActivity.ListItem();
+    field @Deprecated public String className;
+    field @Deprecated public android.os.Bundle extras;
+    field @Deprecated public android.graphics.drawable.Drawable icon;
+    field @Deprecated public CharSequence label;
+    field @Deprecated public String packageName;
+    field @Deprecated public android.content.pm.ResolveInfo resolveInfo;
   }
 
-  public class ListActivity extends android.app.Activity {
-    ctor public ListActivity();
-    method public android.widget.ListAdapter getListAdapter();
-    method public android.widget.ListView getListView();
-    method public long getSelectedItemId();
-    method public int getSelectedItemPosition();
-    method protected void onListItemClick(android.widget.ListView, android.view.View, int, long);
-    method public void setListAdapter(android.widget.ListAdapter);
-    method public void setSelection(int);
+  @Deprecated public class ListActivity extends android.app.Activity {
+    ctor @Deprecated public ListActivity();
+    method @Deprecated public android.widget.ListAdapter getListAdapter();
+    method @Deprecated public android.widget.ListView getListView();
+    method @Deprecated public long getSelectedItemId();
+    method @Deprecated public int getSelectedItemPosition();
+    method @Deprecated protected void onListItemClick(android.widget.ListView, android.view.View, int, long);
+    method @Deprecated public void setListAdapter(android.widget.ListAdapter);
+    method @Deprecated public void setSelection(int);
   }
 
   @Deprecated public class ListFragment extends android.app.Fragment {
@@ -5616,6 +5615,7 @@
     method @Deprecated public android.app.Notification.Builder setDefaults(int);
     method @NonNull public android.app.Notification.Builder setDeleteIntent(android.app.PendingIntent);
     method @NonNull public android.app.Notification.Builder setExtras(android.os.Bundle);
+    method @NonNull public android.app.Notification.Builder setFlag(int, boolean);
     method @NonNull public android.app.Notification.Builder setFullScreenIntent(android.app.PendingIntent, boolean);
     method @NonNull public android.app.Notification.Builder setGroup(String);
     method @NonNull public android.app.Notification.Builder setGroupAlertBehavior(int);
@@ -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
@@ -29164,14 +29165,17 @@
   }
 
   public class ProxyInfo implements android.os.Parcelable {
+    ctor public ProxyInfo(@Nullable android.net.ProxyInfo);
     method public static android.net.ProxyInfo buildDirectProxy(String, int);
     method public static android.net.ProxyInfo buildDirectProxy(String, int, java.util.List<java.lang.String>);
     method public static android.net.ProxyInfo buildPacProxy(android.net.Uri);
+    method @NonNull public static android.net.ProxyInfo buildPacProxy(@NonNull android.net.Uri, int);
     method public int describeContents();
     method public String[] getExclusionList();
     method public String getHost();
     method public android.net.Uri getPacFileUrl();
     method public int getPort();
+    method public boolean isValid();
     method public void writeToParcel(android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.net.ProxyInfo> CREATOR;
   }
@@ -30060,7 +30064,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 +30078,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();
@@ -34823,8 +34829,8 @@
   }
 
   public final class FileUtils {
-    method public static void closeQuietly(@Nullable AutoCloseable);
-    method public static void closeQuietly(@Nullable java.io.FileDescriptor);
+    method @Deprecated public static void closeQuietly(@Nullable AutoCloseable);
+    method @Deprecated public static void closeQuietly(@Nullable java.io.FileDescriptor);
     method public static long copy(@NonNull java.io.InputStream, @NonNull java.io.OutputStream) throws java.io.IOException;
     method public static long copy(@NonNull java.io.InputStream, @NonNull java.io.OutputStream, @Nullable android.os.CancellationSignal, @Nullable java.util.concurrent.Executor, @Nullable android.os.FileUtils.ProgressListener) throws java.io.IOException;
     method public static long copy(@NonNull java.io.FileDescriptor, @NonNull java.io.FileDescriptor) throws java.io.IOException;
@@ -34961,7 +34967,7 @@
     method @Nullable public static android.os.Looper myLooper();
     method @NonNull public static android.os.MessageQueue myQueue();
     method public static void prepare();
-    method public static void prepareMainLooper();
+    method @Deprecated public static void prepareMainLooper();
     method public void quit();
     method public void quitSafely();
     method public void setMessageLogging(@Nullable android.util.Printer);
@@ -35908,6 +35914,7 @@
     method public boolean isAllocationSupported(@NonNull java.io.FileDescriptor);
     method public boolean isCacheBehaviorGroup(java.io.File) throws java.io.IOException;
     method public boolean isCacheBehaviorTombstone(java.io.File) throws java.io.IOException;
+    method public boolean isCheckpointSupported();
     method public boolean isEncrypted(java.io.File);
     method public boolean isObbMounted(String);
     method public boolean mountObb(String, String, android.os.storage.OnObbStateChangeListener);
@@ -48897,12 +48904,12 @@
     method @Nullable public static java.util.List<java.lang.String> getTimeZoneIdsForCountryCode(@NonNull String);
   }
 
-  public class TimingLogger {
-    ctor public TimingLogger(String, String);
-    method public void addSplit(String);
-    method public void dumpToLog();
-    method public void reset(String, String);
-    method public void reset();
+  @Deprecated public class TimingLogger {
+    ctor @Deprecated public TimingLogger(String, String);
+    method @Deprecated public void addSplit(String);
+    method @Deprecated public void dumpToLog();
+    method @Deprecated public void reset(String, String);
+    method @Deprecated public void reset();
   }
 
   public class TypedValue {
@@ -50815,7 +50822,7 @@
     method public final int getScrollY();
     method @android.view.ViewDebug.ExportedProperty(category="drawing") @ColorInt public int getSolidColor();
     method @LayoutRes public int getSourceLayoutResId();
-    method @android.view.ViewDebug.ExportedProperty(category="accessibility") @Nullable public CharSequence getStateDescription();
+    method @android.view.ViewDebug.ExportedProperty(category="accessibility") @Nullable public final CharSequence getStateDescription();
     method public android.animation.StateListAnimator getStateListAnimator();
     method protected int getSuggestedMinimumHeight();
     method protected int getSuggestedMinimumWidth();
@@ -53448,6 +53455,23 @@
 
 }
 
+package android.view.inline {
+
+  public final class InlinePresentationSpec implements android.os.Parcelable {
+    method public int describeContents();
+    method @NonNull public android.util.Size getMaxSize();
+    method @NonNull public android.util.Size getMinSize();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.view.inline.InlinePresentationSpec> CREATOR;
+  }
+
+  public static final class InlinePresentationSpec.Builder {
+    ctor public InlinePresentationSpec.Builder(@NonNull android.util.Size, @NonNull android.util.Size);
+    method @NonNull public android.view.inline.InlinePresentationSpec build();
+  }
+
+}
+
 package android.view.inputmethod {
 
   public class BaseInputConnection implements android.view.inputmethod.InputConnection {
@@ -53611,6 +53635,48 @@
     field public int token;
   }
 
+  public final class InlineSuggestion implements android.os.Parcelable {
+    method public int describeContents();
+    method @NonNull public android.view.inputmethod.InlineSuggestionInfo getInfo();
+    method public void inflate(@NonNull android.content.Context, @NonNull android.util.Size, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.view.View>);
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.view.inputmethod.InlineSuggestion> CREATOR;
+  }
+
+  public final class InlineSuggestionInfo implements android.os.Parcelable {
+    method public int describeContents();
+    method @Nullable public String[] getAutofillHints();
+    method @NonNull public android.view.inline.InlinePresentationSpec getPresentationSpec();
+    method @NonNull public String getSource();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.view.inputmethod.InlineSuggestionInfo> CREATOR;
+    field public static final String SOURCE_AUTOFILL = "android:autofill";
+    field public static final String SOURCE_PLATFORM = "android:platform";
+  }
+
+  public final class InlineSuggestionsRequest implements android.os.Parcelable {
+    method public int describeContents();
+    method public int getMaxSuggestionCount();
+    method @NonNull public java.util.List<android.view.inline.InlinePresentationSpec> getPresentationSpecs();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.view.inputmethod.InlineSuggestionsRequest> CREATOR;
+    field public static final int SUGGESTION_COUNT_UNLIMITED = 2147483647; // 0x7fffffff
+  }
+
+  public static final class InlineSuggestionsRequest.Builder {
+    ctor public InlineSuggestionsRequest.Builder(@NonNull java.util.List<android.view.inline.InlinePresentationSpec>);
+    method @NonNull public android.view.inputmethod.InlineSuggestionsRequest.Builder addPresentationSpecs(@NonNull android.view.inline.InlinePresentationSpec);
+    method @NonNull public android.view.inputmethod.InlineSuggestionsRequest build();
+    method @NonNull public android.view.inputmethod.InlineSuggestionsRequest.Builder setMaxSuggestionCount(int);
+  }
+
+  public final class InlineSuggestionsResponse implements android.os.Parcelable {
+    method public int describeContents();
+    method @NonNull public java.util.List<android.view.inputmethod.InlineSuggestion> getInlineSuggestions();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.view.inputmethod.InlineSuggestionsResponse> CREATOR;
+  }
+
   public final class InputBinding implements android.os.Parcelable {
     ctor public InputBinding(android.view.inputmethod.InputConnection, android.os.IBinder, int, int);
     ctor public InputBinding(android.view.inputmethod.InputConnection, android.view.inputmethod.InputBinding);
@@ -57052,7 +57118,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 f74b743..b306c0f 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -604,6 +604,10 @@
     method public void setNotificationAssistantAccessGranted(@Nullable android.content.ComponentName, boolean);
   }
 
+  public class SearchManager implements android.content.DialogInterface.OnCancelListener android.content.DialogInterface.OnDismissListener {
+    method public void launchAssist(@Nullable android.os.Bundle);
+  }
+
   public final class StatsManager {
     method @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public void addConfig(long, byte[]) throws android.app.StatsManager.StatsUnavailableException;
     method @Deprecated @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public boolean addConfiguration(long, byte[]);
@@ -1356,7 +1360,23 @@
     method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public boolean setPriority(android.bluetooth.BluetoothDevice, int);
   }
 
+  public final class BluetoothPan implements android.bluetooth.BluetoothProfile {
+    method protected void finalize();
+    method @NonNull public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices();
+    method public int getConnectionState(@Nullable android.bluetooth.BluetoothDevice);
+    method public boolean isTetheringOn();
+    method public void setBluetoothTethering(boolean);
+    field public static final String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.pan.profile.action.CONNECTION_STATE_CHANGED";
+    field public static final String EXTRA_LOCAL_ROLE = "android.bluetooth.pan.extra.LOCAL_ROLE";
+    field public static final int LOCAL_NAP_ROLE = 1; // 0x1
+    field public static final int LOCAL_PANU_ROLE = 2; // 0x2
+    field public static final int PAN_ROLE_NONE = 0; // 0x0
+    field public static final int REMOTE_NAP_ROLE = 1; // 0x1
+    field public static final int REMOTE_PANU_ROLE = 2; // 0x2
+  }
+
   public interface BluetoothProfile {
+    field public static final int PAN = 5; // 0x5
     field public static final int PRIORITY_OFF = 0; // 0x0
     field public static final int PRIORITY_ON = 100; // 0x64
   }
@@ -4183,6 +4203,33 @@
     method public void onUpstreamChanged(@Nullable android.net.Network);
   }
 
+  public final class IpConfiguration implements android.os.Parcelable {
+    ctor public IpConfiguration();
+    ctor public IpConfiguration(@NonNull android.net.IpConfiguration);
+    method @Nullable public android.net.ProxyInfo getHttpProxy();
+    method @NonNull public android.net.IpConfiguration.IpAssignment getIpAssignment();
+    method @NonNull public android.net.IpConfiguration.ProxySettings getProxySettings();
+    method @Nullable public android.net.StaticIpConfiguration getStaticIpConfiguration();
+    method public void setHttpProxy(@Nullable android.net.ProxyInfo);
+    method public void setIpAssignment(@NonNull android.net.IpConfiguration.IpAssignment);
+    method public void setProxySettings(@NonNull android.net.IpConfiguration.ProxySettings);
+    method public void setStaticIpConfiguration(@Nullable android.net.StaticIpConfiguration);
+    field @NonNull public static final android.os.Parcelable.Creator<android.net.IpConfiguration> CREATOR;
+  }
+
+  public enum IpConfiguration.IpAssignment {
+    enum_constant public static final android.net.IpConfiguration.IpAssignment DHCP;
+    enum_constant public static final android.net.IpConfiguration.IpAssignment STATIC;
+    enum_constant public static final android.net.IpConfiguration.IpAssignment UNASSIGNED;
+  }
+
+  public enum IpConfiguration.ProxySettings {
+    enum_constant public static final android.net.IpConfiguration.ProxySettings NONE;
+    enum_constant public static final android.net.IpConfiguration.ProxySettings PAC;
+    enum_constant public static final android.net.IpConfiguration.ProxySettings STATIC;
+    enum_constant public static final android.net.IpConfiguration.ProxySettings UNASSIGNED;
+  }
+
   public final class IpPrefix implements android.os.Parcelable {
     ctor public IpPrefix(@NonNull java.net.InetAddress, @IntRange(from=0, to=128) int);
     ctor public IpPrefix(@NonNull String);
@@ -4255,6 +4302,7 @@
 
   public class NetworkKey implements android.os.Parcelable {
     ctor public NetworkKey(android.net.WifiKey);
+    method @Nullable public static android.net.NetworkKey createFromScanResult(@Nullable android.net.wifi.ScanResult);
     method public int describeContents();
     method public void writeToParcel(android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.net.NetworkKey> CREATOR;
@@ -4277,16 +4325,23 @@
     method @RequiresPermission(anyOf={android.Manifest.permission.SCORE_NETWORKS, "android.permission.REQUEST_NETWORK_SCORES"}) public boolean clearScores() throws java.lang.SecurityException;
     method @RequiresPermission(anyOf={android.Manifest.permission.SCORE_NETWORKS, "android.permission.REQUEST_NETWORK_SCORES"}) public void disableScoring() throws java.lang.SecurityException;
     method @RequiresPermission(anyOf={android.Manifest.permission.SCORE_NETWORKS, "android.permission.REQUEST_NETWORK_SCORES"}) public String getActiveScorerPackage();
+    method @RequiresPermission("android.permission.REQUEST_NETWORK_SCORES") public void registerNetworkScoreCallback(int, int, @NonNull java.util.concurrent.Executor, @NonNull android.net.NetworkScoreManager.NetworkScoreCallback) throws java.lang.SecurityException;
+    method @RequiresPermission("android.permission.REQUEST_NETWORK_SCORES") public boolean requestScores(@NonNull android.net.NetworkKey[]) throws java.lang.SecurityException;
     method @RequiresPermission(anyOf={android.Manifest.permission.SCORE_NETWORKS, "android.permission.REQUEST_NETWORK_SCORES"}) public boolean setActiveScorer(String) throws java.lang.SecurityException;
-    method @RequiresPermission(android.Manifest.permission.SCORE_NETWORKS) public boolean updateScores(android.net.ScoredNetwork[]) throws java.lang.SecurityException;
-    field public static final String ACTION_CHANGE_ACTIVE = "android.net.scoring.CHANGE_ACTIVE";
+    method @RequiresPermission(android.Manifest.permission.SCORE_NETWORKS) public boolean updateScores(@NonNull android.net.ScoredNetwork[]) throws java.lang.SecurityException;
+    field @Deprecated public static final String ACTION_CHANGE_ACTIVE = "android.net.scoring.CHANGE_ACTIVE";
     field public static final String ACTION_CUSTOM_ENABLE = "android.net.scoring.CUSTOM_ENABLE";
     field public static final String ACTION_RECOMMEND_NETWORKS = "android.net.action.RECOMMEND_NETWORKS";
     field public static final String ACTION_SCORER_CHANGED = "android.net.scoring.SCORER_CHANGED";
-    field public static final String ACTION_SCORE_NETWORKS = "android.net.scoring.SCORE_NETWORKS";
-    field public static final String EXTRA_NETWORKS_TO_SCORE = "networksToScore";
+    field @Deprecated public static final String ACTION_SCORE_NETWORKS = "android.net.scoring.SCORE_NETWORKS";
+    field @Deprecated public static final String EXTRA_NETWORKS_TO_SCORE = "networksToScore";
     field public static final String EXTRA_NEW_SCORER = "newScorer";
-    field public static final String EXTRA_PACKAGE_NAME = "packageName";
+    field @Deprecated public static final String EXTRA_PACKAGE_NAME = "packageName";
+  }
+
+  public static interface NetworkScoreManager.NetworkScoreCallback {
+    method public void clearScores();
+    method public void updateScores(@NonNull java.util.List<android.net.ScoredNetwork>);
   }
 
   public class NetworkStack {
@@ -4408,6 +4463,258 @@
 
 }
 
+package android.net.eap {
+
+  public final class EapSessionConfig {
+  }
+
+  public static final class EapSessionConfig.Builder {
+    ctor public EapSessionConfig.Builder();
+    method @NonNull public android.net.eap.EapSessionConfig build();
+    method @NonNull public android.net.eap.EapSessionConfig.Builder setEapAkaConfig(int, int);
+    method @NonNull public android.net.eap.EapSessionConfig.Builder setEapAkaPrimeConfig(int, int, @NonNull String, boolean);
+    method @NonNull public android.net.eap.EapSessionConfig.Builder setEapIdentity(@NonNull byte[]);
+    method @NonNull public android.net.eap.EapSessionConfig.Builder setEapMsChapV2Config(@NonNull String, @NonNull String);
+    method @NonNull public android.net.eap.EapSessionConfig.Builder setEapSimConfig(int, int);
+  }
+
+  public static class EapSessionConfig.EapAkaConfig extends android.net.eap.EapSessionConfig.EapUiccConfig {
+  }
+
+  public static class EapSessionConfig.EapAkaPrimeConfig extends android.net.eap.EapSessionConfig.EapAkaConfig {
+    method public boolean allowsMismatchedNetworkNames();
+    method @NonNull public String getNetworkName();
+  }
+
+  public abstract static class EapSessionConfig.EapMethodConfig {
+    method public int getMethodType();
+  }
+
+  public static class EapSessionConfig.EapMsChapV2Config extends android.net.eap.EapSessionConfig.EapMethodConfig {
+    method @NonNull public String getPassword();
+    method @NonNull public String getUsername();
+  }
+
+  public static class EapSessionConfig.EapSimConfig extends android.net.eap.EapSessionConfig.EapUiccConfig {
+  }
+
+  public abstract static class EapSessionConfig.EapUiccConfig extends android.net.eap.EapSessionConfig.EapMethodConfig {
+    method public int getAppType();
+    method public int getSubId();
+  }
+
+}
+
+package android.net.ipsec.ike {
+
+  public final class ChildSaProposal extends android.net.ipsec.ike.SaProposal {
+  }
+
+  public static final class ChildSaProposal.Builder {
+    ctor public ChildSaProposal.Builder();
+    method @NonNull public android.net.ipsec.ike.ChildSaProposal.Builder addDhGroup(int);
+    method @NonNull public android.net.ipsec.ike.ChildSaProposal.Builder addEncryptionAlgorithm(int, int);
+    method @NonNull public android.net.ipsec.ike.ChildSaProposal.Builder addIntegrityAlgorithm(int);
+    method @NonNull public android.net.ipsec.ike.ChildSaProposal build();
+  }
+
+  public interface ChildSessionCallback {
+    method public void onClosed();
+    method public void onClosedExceptionally(@NonNull android.net.ipsec.ike.exceptions.IkeException);
+    method public void onIpSecTransformCreated(@NonNull android.net.IpSecTransform, int);
+    method public void onIpSecTransformDeleted(@NonNull android.net.IpSecTransform, int);
+    method public void onOpened(@NonNull android.net.ipsec.ike.ChildSessionConfiguration);
+  }
+
+  public final class ChildSessionConfiguration {
+    method @NonNull public java.util.List<android.net.ipsec.ike.IkeTrafficSelector> getInboundTrafficSelectors();
+    method @NonNull public java.util.List<android.net.LinkAddress> getInternalAddresses();
+    method @NonNull public java.util.List<java.net.InetAddress> getInternalDhcpServers();
+    method @NonNull public java.util.List<java.net.InetAddress> getInternalDnsServers();
+    method @NonNull public java.util.List<android.net.LinkAddress> getInternalSubnets();
+    method @NonNull public java.util.List<android.net.ipsec.ike.IkeTrafficSelector> getOutboundTrafficSelectors();
+  }
+
+  public abstract class ChildSessionOptions {
+  }
+
+  public class IkeFqdnIdentification extends android.net.ipsec.ike.IkeIdentification {
+    ctor public IkeFqdnIdentification(@NonNull String);
+    field @NonNull public final String fqdn;
+  }
+
+  public abstract class IkeIdentification {
+  }
+
+  public final class IkeIpv4AddrIdentification extends android.net.ipsec.ike.IkeIdentification {
+    ctor public IkeIpv4AddrIdentification(@NonNull java.net.Inet4Address);
+    field @NonNull public final java.net.Inet4Address ipv4Address;
+  }
+
+  public class IkeIpv6AddrIdentification extends android.net.ipsec.ike.IkeIdentification {
+    ctor public IkeIpv6AddrIdentification(@NonNull java.net.Inet6Address);
+    field @NonNull public final java.net.Inet6Address ipv6Address;
+  }
+
+  public final class IkeKeyIdIdentification extends android.net.ipsec.ike.IkeIdentification {
+    ctor public IkeKeyIdIdentification(@NonNull byte[]);
+    field @NonNull public final byte[] keyId;
+  }
+
+  public final class IkeRfc822AddrIdentification extends android.net.ipsec.ike.IkeIdentification {
+    ctor public IkeRfc822AddrIdentification(@NonNull String);
+    field @NonNull public final String rfc822Name;
+  }
+
+  public final class IkeSaProposal extends android.net.ipsec.ike.SaProposal {
+    method @NonNull public java.util.List<java.lang.Integer> getPseudorandomFunctions();
+  }
+
+  public static final class IkeSaProposal.Builder {
+    ctor public IkeSaProposal.Builder();
+    method @NonNull public android.net.ipsec.ike.IkeSaProposal.Builder addDhGroup(int);
+    method @NonNull public android.net.ipsec.ike.IkeSaProposal.Builder addEncryptionAlgorithm(int, int);
+    method @NonNull public android.net.ipsec.ike.IkeSaProposal.Builder addIntegrityAlgorithm(int);
+    method @NonNull public android.net.ipsec.ike.IkeSaProposal.Builder addPseudorandomFunction(int);
+    method @NonNull public android.net.ipsec.ike.IkeSaProposal build();
+  }
+
+  public final class IkeSession implements java.lang.AutoCloseable {
+    ctor public IkeSession(@NonNull android.content.Context, @NonNull android.net.ipsec.ike.IkeSessionOptions, @NonNull android.net.ipsec.ike.ChildSessionOptions, @NonNull java.util.concurrent.Executor, @NonNull android.net.ipsec.ike.IkeSessionCallback, @NonNull android.net.ipsec.ike.ChildSessionCallback);
+    method public void close();
+    method public void closeChildSession(@NonNull android.net.ipsec.ike.ChildSessionCallback);
+    method public void kill();
+    method public void openChildSession(@NonNull android.net.ipsec.ike.ChildSessionOptions, @NonNull android.net.ipsec.ike.ChildSessionCallback);
+  }
+
+  public interface IkeSessionCallback {
+    method public void onClosed();
+    method public void onClosedExceptionally(@NonNull android.net.ipsec.ike.exceptions.IkeException);
+    method public void onError(@NonNull android.net.ipsec.ike.exceptions.IkeProtocolException);
+    method public void onOpened(@NonNull android.net.ipsec.ike.IkeSessionConfiguration);
+  }
+
+  public final class IkeSessionConfiguration {
+    ctor public IkeSessionConfiguration();
+    method @NonNull public String getRemoteApplicationVersion();
+    method public boolean isIkeExtensionEnabled(int);
+    field public static final int EXTENSION_TYPE_FRAGMENTATION = 1; // 0x1
+    field public static final int EXTENSION_TYPE_MOBIKE = 2; // 0x2
+  }
+
+  public final class IkeSessionOptions {
+  }
+
+  public static final class IkeSessionOptions.Builder {
+    ctor public IkeSessionOptions.Builder();
+    method @NonNull public android.net.ipsec.ike.IkeSessionOptions.Builder addSaProposal(@NonNull android.net.ipsec.ike.IkeSaProposal);
+    method @NonNull public android.net.ipsec.ike.IkeSessionOptions build();
+    method @NonNull public android.net.ipsec.ike.IkeSessionOptions.Builder setAuthDigitalSignature(@NonNull java.security.cert.X509Certificate, @NonNull java.security.cert.X509Certificate, @NonNull java.security.PrivateKey);
+    method @NonNull public android.net.ipsec.ike.IkeSessionOptions.Builder setAuthDigitalSignature(@NonNull java.security.cert.X509Certificate, @NonNull java.security.cert.X509Certificate, @NonNull java.util.List<java.security.cert.X509Certificate>, @NonNull java.security.PrivateKey);
+    method @NonNull public android.net.ipsec.ike.IkeSessionOptions.Builder setAuthEap(@NonNull java.security.cert.X509Certificate, @NonNull android.net.eap.EapSessionConfig);
+    method @NonNull public android.net.ipsec.ike.IkeSessionOptions.Builder setAuthPsk(@NonNull byte[]);
+    method @NonNull public android.net.ipsec.ike.IkeSessionOptions.Builder setLocalIdentification(@NonNull android.net.ipsec.ike.IkeIdentification);
+    method @NonNull public android.net.ipsec.ike.IkeSessionOptions.Builder setRemoteIdentification(@NonNull android.net.ipsec.ike.IkeIdentification);
+    method @NonNull public android.net.ipsec.ike.IkeSessionOptions.Builder setServerAddress(@NonNull java.net.InetAddress);
+    method @NonNull public android.net.ipsec.ike.IkeSessionOptions.Builder setUdpEncapsulationSocket(@NonNull android.net.IpSecManager.UdpEncapsulationSocket);
+  }
+
+  public final class IkeTrafficSelector {
+    ctor public IkeTrafficSelector(int, int, @NonNull java.net.InetAddress, @NonNull java.net.InetAddress);
+    field public final int endPort;
+    field @NonNull public final java.net.InetAddress endingAddress;
+    field public final int startPort;
+    field @NonNull public final java.net.InetAddress startingAddress;
+  }
+
+  public abstract class SaProposal {
+    method @NonNull public java.util.List<java.lang.Integer> getDhGroups();
+    method @NonNull public java.util.List<android.util.Pair<java.lang.Integer,java.lang.Integer>> getEncryptionAlgorithms();
+    method @NonNull public java.util.List<java.lang.Integer> getIntegrityAlgorithms();
+    field public static final int DH_GROUP_1024_BIT_MODP = 2; // 0x2
+    field public static final int DH_GROUP_2048_BIT_MODP = 14; // 0xe
+    field public static final int DH_GROUP_NONE = 0; // 0x0
+    field public static final int ENCRYPTION_ALGORITHM_3DES = 3; // 0x3
+    field public static final int ENCRYPTION_ALGORITHM_AES_CBC = 12; // 0xc
+    field public static final int ENCRYPTION_ALGORITHM_AES_GCM_12 = 19; // 0x13
+    field public static final int ENCRYPTION_ALGORITHM_AES_GCM_16 = 20; // 0x14
+    field public static final int ENCRYPTION_ALGORITHM_AES_GCM_8 = 18; // 0x12
+    field public static final int INTEGRITY_ALGORITHM_AES_XCBC_96 = 5; // 0x5
+    field public static final int INTEGRITY_ALGORITHM_HMAC_SHA1_96 = 2; // 0x2
+    field public static final int INTEGRITY_ALGORITHM_HMAC_SHA2_256_128 = 12; // 0xc
+    field public static final int INTEGRITY_ALGORITHM_HMAC_SHA2_384_192 = 13; // 0xd
+    field public static final int INTEGRITY_ALGORITHM_HMAC_SHA2_512_256 = 14; // 0xe
+    field public static final int INTEGRITY_ALGORITHM_NONE = 0; // 0x0
+    field public static final int KEY_LEN_AES_128 = 128; // 0x80
+    field public static final int KEY_LEN_AES_192 = 192; // 0xc0
+    field public static final int KEY_LEN_AES_256 = 256; // 0x100
+    field public static final int KEY_LEN_UNUSED = 0; // 0x0
+    field public static final int PSEUDORANDOM_FUNCTION_AES128_XCBC = 4; // 0x4
+    field public static final int PSEUDORANDOM_FUNCTION_HMAC_SHA1 = 2; // 0x2
+  }
+
+  public final class TransportModeChildSessionOptions extends android.net.ipsec.ike.ChildSessionOptions {
+  }
+
+  public static final class TransportModeChildSessionOptions.Builder {
+    ctor public TransportModeChildSessionOptions.Builder();
+    method @NonNull public android.net.ipsec.ike.TransportModeChildSessionOptions.Builder addInboundTrafficSelectors(@NonNull android.net.ipsec.ike.IkeTrafficSelector);
+    method @NonNull public android.net.ipsec.ike.TransportModeChildSessionOptions.Builder addOutboundTrafficSelectors(@NonNull android.net.ipsec.ike.IkeTrafficSelector);
+    method @NonNull public android.net.ipsec.ike.TransportModeChildSessionOptions.Builder addSaProposal(@NonNull android.net.ipsec.ike.ChildSaProposal);
+    method @NonNull public android.net.ipsec.ike.TransportModeChildSessionOptions build();
+  }
+
+  public final class TunnelModeChildSessionOptions extends android.net.ipsec.ike.ChildSessionOptions {
+  }
+
+  public static final class TunnelModeChildSessionOptions.Builder {
+    ctor public TunnelModeChildSessionOptions.Builder();
+    method @NonNull public android.net.ipsec.ike.TunnelModeChildSessionOptions.Builder addInboundTrafficSelectors(@NonNull android.net.ipsec.ike.IkeTrafficSelector);
+    method @NonNull public android.net.ipsec.ike.TunnelModeChildSessionOptions.Builder addInternalAddressRequest(int);
+    method @NonNull public android.net.ipsec.ike.TunnelModeChildSessionOptions.Builder addInternalAddressRequest(@NonNull java.net.InetAddress, int);
+    method @NonNull public android.net.ipsec.ike.TunnelModeChildSessionOptions.Builder addInternalDhcpServerRequest(int);
+    method @NonNull public android.net.ipsec.ike.TunnelModeChildSessionOptions.Builder addInternalDhcpServerRequest(@NonNull java.net.InetAddress);
+    method @NonNull public android.net.ipsec.ike.TunnelModeChildSessionOptions.Builder addInternalDnsServerRequest(int);
+    method @NonNull public android.net.ipsec.ike.TunnelModeChildSessionOptions.Builder addInternalDnsServerRequest(@NonNull java.net.InetAddress);
+    method @NonNull public android.net.ipsec.ike.TunnelModeChildSessionOptions.Builder addInternalSubnetRequest(int);
+    method @NonNull public android.net.ipsec.ike.TunnelModeChildSessionOptions.Builder addOutboundTrafficSelectors(@NonNull android.net.ipsec.ike.IkeTrafficSelector);
+    method @NonNull public android.net.ipsec.ike.TunnelModeChildSessionOptions.Builder addSaProposal(@NonNull android.net.ipsec.ike.ChildSaProposal);
+    method @NonNull public android.net.ipsec.ike.TunnelModeChildSessionOptions build();
+  }
+
+}
+
+package android.net.ipsec.ike.exceptions {
+
+  public abstract class IkeException extends java.lang.Exception {
+  }
+
+  public final class IkeInternalException extends android.net.ipsec.ike.exceptions.IkeException {
+  }
+
+  public abstract class IkeProtocolException extends android.net.ipsec.ike.exceptions.IkeException {
+    method @Nullable public byte[] getErrorData();
+    method public int getErrorType();
+    field public static final int ERROR_TYPE_AUTHENTICATION_FAILED = 24; // 0x18
+    field public static final int ERROR_TYPE_CHILD_SA_NOT_FOUND = 44; // 0x2c
+    field public static final int ERROR_TYPE_FAILED_CP_REQUIRED = 37; // 0x25
+    field public static final int ERROR_TYPE_INTERNAL_ADDRESS_FAILURE = 36; // 0x24
+    field public static final int ERROR_TYPE_INVALID_IKE_SPI = 4; // 0x4
+    field public static final int ERROR_TYPE_INVALID_KE_PAYLOAD = 17; // 0x11
+    field public static final int ERROR_TYPE_INVALID_MAJOR_VERSION = 5; // 0x5
+    field public static final int ERROR_TYPE_INVALID_MESSAGE_ID = 9; // 0x9
+    field public static final int ERROR_TYPE_INVALID_SELECTORS = 39; // 0x27
+    field public static final int ERROR_TYPE_INVALID_SYNTAX = 7; // 0x7
+    field public static final int ERROR_TYPE_NO_ADDITIONAL_SAS = 35; // 0x23
+    field public static final int ERROR_TYPE_NO_PROPOSAL_CHOSEN = 14; // 0xe
+    field public static final int ERROR_TYPE_SINGLE_PAIR_REQUIRED = 34; // 0x22
+    field public static final int ERROR_TYPE_TEMPORARY_FAILURE = 43; // 0x2b
+    field public static final int ERROR_TYPE_TS_UNACCEPTABLE = 38; // 0x26
+    field public static final int ERROR_TYPE_UNSUPPORTED_CRITICAL_PAYLOAD = 1; // 0x1
+  }
+
+}
+
 package android.net.metrics {
 
   public final class ApfProgramEvent implements android.net.metrics.IpConnectivityLog.Event {
@@ -4853,6 +5160,10 @@
     field @Deprecated public static final int WPA2_PSK = 4; // 0x4
   }
 
+  public class WifiFrameworkInitializer {
+    method public static void registerServiceWrappers();
+  }
+
   public class WifiInfo implements android.os.Parcelable {
     method @Nullable public String getAppPackageName();
     method public double getRxSuccessRate();
@@ -5024,6 +5335,7 @@
     method @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public java.util.List<java.lang.Integer> getAvailableChannels(int);
     method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public boolean getScanResults();
     method @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public java.util.List<android.net.wifi.ScanResult> getSingleScanResults();
+    method @RequiresPermission(android.Manifest.permission.NETWORK_STACK) public void setScanningEnabled(boolean);
     method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void startBackgroundScan(android.net.wifi.WifiScanner.ScanSettings, android.net.wifi.WifiScanner.ScanListener);
     method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void startBackgroundScan(android.net.wifi.WifiScanner.ScanSettings, android.net.wifi.WifiScanner.ScanListener, android.os.WorkSource);
     method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void startScan(android.net.wifi.WifiScanner.ScanSettings, android.net.wifi.WifiScanner.ScanListener);
@@ -5489,6 +5801,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 +5842,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 +5857,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 +5886,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 +5915,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);
@@ -5712,6 +6040,9 @@
     field public static final int USER_ACTIVITY_FLAG_NO_CHANGE_LIGHTS = 1; // 0x1
   }
 
+  public class PowerWhitelistManager {
+  }
+
   public class RecoverySystem {
     method @RequiresPermission(android.Manifest.permission.RECOVERY) public static void cancelScheduledUpdate(android.content.Context) throws java.io.IOException;
     method @RequiresPermission(android.Manifest.permission.RECOVERY) public static void installPackage(android.content.Context, java.io.File, boolean) throws java.io.IOException;
@@ -6214,6 +6545,7 @@
     method @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public static String getString(@NonNull String, @NonNull String, @Nullable String);
     method public static void removeOnPropertiesChangedListener(@NonNull android.provider.DeviceConfig.OnPropertiesChangedListener);
     method @RequiresPermission(android.Manifest.permission.WRITE_DEVICE_CONFIG) public static void resetToDefaults(int, @Nullable String);
+    method @RequiresPermission(android.Manifest.permission.WRITE_DEVICE_CONFIG) public static boolean setProperties(@NonNull android.provider.DeviceConfig.Properties);
     method @RequiresPermission(android.Manifest.permission.WRITE_DEVICE_CONFIG) public static boolean setProperty(@NonNull String, @NonNull String, @Nullable String, boolean);
     field public static final String NAMESPACE_ACTIVITY_MANAGER = "activity_manager";
     field public static final String NAMESPACE_ACTIVITY_MANAGER_NATIVE_BOOT = "activity_manager_native_boot";
@@ -6420,7 +6752,7 @@
   public static final class Settings.Secure extends android.provider.Settings.NameValueTable {
     method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public static boolean putString(@NonNull android.content.ContentResolver, @NonNull String, @Nullable String, @Nullable String, boolean);
     method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public static void resetToDefaults(@NonNull android.content.ContentResolver, @Nullable String);
-    field public static final String ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED = "accessibility_display_magnification_navbar_enabled";
+    field @Deprecated public static final String ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED = "accessibility_display_magnification_navbar_enabled";
     field public static final String ASSIST_GESTURE_SETUP_COMPLETE = "assist_gesture_setup_complete";
     field public static final String AUTOFILL_FEATURE_FIELD_CLASSIFICATION = "autofill_field_classification";
     field public static final String AUTOFILL_USER_DATA_MAX_CATEGORY_COUNT = "autofill_user_data_max_category_count";
@@ -6524,6 +6856,7 @@
     field public static final String SERIAL_NUMBER = "serial_number";
     field public static final String SERVICE_CATEGORY = "service_category";
     field public static final String SLOT_INDEX = "slot_index";
+    field public static final String SUB_ID = "sub_id";
   }
 
   public static final class Telephony.Sms.Intents {
@@ -8583,7 +8916,7 @@
   }
 
   public final class SmsCbMessage implements android.os.Parcelable {
-    ctor public SmsCbMessage(int, int, int, @NonNull android.telephony.SmsCbLocation, int, @Nullable String, @Nullable String, int, @Nullable android.telephony.SmsCbEtwsInfo, @Nullable android.telephony.SmsCbCmasInfo, int, @Nullable java.util.List<android.telephony.CbGeoUtils.Geometry>, long, int);
+    ctor public SmsCbMessage(int, int, int, @NonNull android.telephony.SmsCbLocation, int, @Nullable String, @Nullable String, int, @Nullable android.telephony.SmsCbEtwsInfo, @Nullable android.telephony.SmsCbCmasInfo, int, @Nullable java.util.List<android.telephony.CbGeoUtils.Geometry>, long, int, int);
     method @NonNull public static android.telephony.SmsCbMessage createFromCursor(@NonNull android.database.Cursor);
     method public int describeContents();
     method @Nullable public android.telephony.SmsCbCmasInfo getCmasWarningInfo();
@@ -8600,6 +8933,7 @@
     method public int getSerialNumber();
     method public int getServiceCategory();
     method public int getSlotIndex();
+    method public int getSubscriptionId();
     method public boolean isCmasMessage();
     method public boolean isEmergencyMessage();
     method public boolean isEtwsMessage();
@@ -8719,6 +9053,7 @@
     method @NonNull public static String getDefaultSimCountryIso();
     method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getDeviceSoftwareVersion(int);
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean getEmergencyCallbackMode();
+    method public int getEmergencyNumberDbVersion();
     method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getIsimDomain();
     method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getIsimIst();
     method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.Map<java.lang.Integer,java.lang.Integer> getLogicalToPhysicalSlotMapping();
@@ -8758,6 +9093,7 @@
     method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isVideoCallingEnabled();
     method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public boolean isVisualVoicemailEnabled(android.telecom.PhoneAccountHandle);
     method public boolean needsOtaServiceProvisioning();
+    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void notifyOtaEmergencyNumberDbInstalled();
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean rebootRadio();
     method @RequiresPermission(allOf={android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.MODIFY_PHONE_STATE}) public void requestCellInfoUpdate(@NonNull android.os.WorkSource, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyManager.CellInfoCallback);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void requestNumberVerification(@NonNull android.telephony.PhoneNumberRange, long, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.NumberVerificationCallback);
@@ -8786,8 +9122,8 @@
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean switchSlots(int[]);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void toggleRadioOnOff();
     method public void updateServiceLocation();
+    method @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public void updateTestOtaEmergencyNumberDbFilePath(@NonNull String);
     field @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static final String ACTION_ANOMALY_REPORTED = "android.telephony.action.ANOMALY_REPORTED";
-    field @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static final String ACTION_OTA_EMERGENCY_NUMBER_DB_INSTALLED = "android.telephony.action.OTA_EMERGENCY_NUMBER_DB_INSTALLED";
     field public static final String ACTION_SIM_APPLICATION_STATE_CHANGED = "android.telephony.action.SIM_APPLICATION_STATE_CHANGED";
     field public static final String ACTION_SIM_CARD_STATE_CHANGED = "android.telephony.action.SIM_CARD_STATE_CHANGED";
     field public static final String ACTION_SIM_SLOT_STATUS_CHANGED = "android.telephony.action.SIM_SLOT_STATUS_CHANGED";
@@ -8800,6 +9136,7 @@
     field public static final String EXTRA_SIM_STATE = "android.telephony.extra.SIM_STATE";
     field public static final String EXTRA_VISUAL_VOICEMAIL_ENABLED_BY_USER_BOOL = "android.telephony.extra.VISUAL_VOICEMAIL_ENABLED_BY_USER_BOOL";
     field public static final String EXTRA_VOICEMAIL_SCRAMBLED_PIN_STRING = "android.telephony.extra.VOICEMAIL_SCRAMBLED_PIN_STRING";
+    field public static final int INVALID_EMERGENCY_NUMBER_DB_VERSION = -1; // 0xffffffff
     field public static final int KEY_TYPE_EPDG = 1; // 0x1
     field public static final int KEY_TYPE_WLAN = 2; // 0x2
     field public static final long NETWORK_TYPE_BITMASK_1xRTT = 64L; // 0x40L
diff --git a/api/test-current.txt b/api/test-current.txt
index 95b0cae..dacc5d6 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -707,6 +707,7 @@
     field public static final String CONTENT_CAPTURE_MANAGER_SERVICE = "content_capture";
     field public static final String DEVICE_IDLE_CONTROLLER = "deviceidle";
     field public static final String PERMISSION_SERVICE = "permission";
+    field public static final String POWER_WHITELIST_MANAGER = "power_whitelist";
     field public static final String ROLLBACK_SERVICE = "rollback";
     field public static final String STATUS_BAR_SERVICE = "statusbar";
     field public static final String TEST_NETWORK_SERVICE = "test_network";
@@ -1808,6 +1809,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 +1843,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 +1858,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 +1887,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 +1916,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);
@@ -2026,6 +2043,9 @@
     field public static final int POWER_SAVE_MODE_TRIGGER_PERCENTAGE = 0; // 0x0
   }
 
+  public class PowerWhitelistManager {
+  }
+
   public class Process {
     method public static final int getThreadScheduler(int) throws java.lang.IllegalArgumentException;
     field public static final int FIRST_APP_ZYGOTE_ISOLATED_UID = 90000; // 0x15f90
@@ -2449,6 +2469,7 @@
     field public static final String DYNAMIC_POWER_SAVINGS_DISABLE_THRESHOLD = "dynamic_power_savings_disable_threshold";
     field public static final String DYNAMIC_POWER_SAVINGS_ENABLED = "dynamic_power_savings_enabled";
     field public static final String HIDDEN_API_BLACKLIST_EXEMPTIONS = "hidden_api_blacklist_exemptions";
+    field public static final String HIDE_ERROR_DIALOGS = "hide_error_dialogs";
     field public static final String LOCATION_GLOBAL_KILL_SWITCH = "location_global_kill_switch";
     field public static final String LOCATION_IGNORE_SETTINGS_PACKAGE_WHITELIST = "location_ignore_settings_package_whitelist";
     field public static final String LOW_POWER_MODE = "low_power";
@@ -2510,6 +2531,7 @@
     field public static final String SERIAL_NUMBER = "serial_number";
     field public static final String SERVICE_CATEGORY = "service_category";
     field public static final String SLOT_INDEX = "slot_index";
+    field public static final String SUB_ID = "sub_id";
   }
 
   public static final class Telephony.Sms.Intents {
@@ -3135,16 +3157,19 @@
     method public int getCarrierIdListVersion();
     method public java.util.List<java.lang.String> getCarrierPackageNamesForIntent(android.content.Intent);
     method @Nullable public static android.content.ComponentName getDefaultRespondViaMessageApplication(@NonNull android.content.Context, boolean);
+    method public int getEmergencyNumberDbVersion();
     method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public String getLine1AlphaTag();
     method @NonNull @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public String getNetworkCountryIso(int);
     method public android.util.Pair<java.lang.Integer,java.lang.Integer> getRadioHalVersion();
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void refreshUiccProfile();
     method @Deprecated public void setCarrierTestOverride(String, String, String, String, String, String, String);
     method public void setCarrierTestOverride(String, String, String, String, String, String, String, String, String);
+    method @RequiresPermission("android.permission.READ_ACTIVE_EMERGENCY_SESSION") public void updateTestOtaEmergencyNumberDbFilePath(@NonNull String);
     field public static final int CARRIER_PRIVILEGE_STATUS_ERROR_LOADING_RULES = -2; // 0xfffffffe
     field public static final int CARRIER_PRIVILEGE_STATUS_HAS_ACCESS = 1; // 0x1
     field public static final int CARRIER_PRIVILEGE_STATUS_NO_ACCESS = 0; // 0x0
     field public static final int CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED = -1; // 0xffffffff
+    field public static final int INVALID_EMERGENCY_NUMBER_DB_VERSION = -1; // 0xffffffff
     field public static final int UNKNOWN_CARRIER_ID_LIST_VERSION = -1; // 0xffffffff
   }
 
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index b0570fd..49cc3c4 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -164,7 +164,7 @@
         BiometricAcquired biometric_acquired = 87;
         BiometricAuthenticated biometric_authenticated = 88;
         BiometricErrorOccurred biometric_error_occurred = 89;
-        // Atom number 90 is available for use.
+        UiEventReported ui_event_reported = 90;
         BatteryHealthSnapshot battery_health_snapshot = 91;
         SlowIo slow_io = 92;
         BatteryCausedShutdown battery_caused_shutdown = 93;
@@ -340,6 +340,8 @@
         PerfettoUploaded perfetto_uploaded =
             229 [(log_from_module) = "perfetto"];
         VmsClientConnectionStateChanged vms_client_connection_state_changed = 230;
+        GpsLocationStatusReported gps_location_status_reported = 231;
+        GpsTimeToFirstFixReported gps_time_to_first_fix_reported = 232;
     }
 
     // Pulled events will start at field 10000.
@@ -734,6 +736,27 @@
     optional android.server.location.GpsSignalQualityEnum level = 1;
 }
 
+/**
+ * Gps location status report
+ *
+ * Logged from:
+ *   /frameworks/base/location/java/com/android/internal/location/gnssmetrics/GnssMetrics.java
+ */
+message GpsLocationStatusReported {
+    // Boolean stating if location was acquired
+    optional bool location_success = 1;
+}
+
+/**
+ * Gps log time to first fix report
+ *
+ * Logged from:
+ *   /frameworks/base/location/java/com/android/internal/location/gnssmetrics/GnssMetrics.java
+ */
+message GpsTimeToFirstFixReported {
+    // int32 reporting the time to first fix in milliseconds
+    optional int32 time_to_first_fix_millis = 1;
+}
 
 /**
  * Logs when a sync manager sync state changes.
@@ -3266,6 +3289,21 @@
 }
 
 /**
+ * Atom for simple logging of user interaction and impression events, such as "the user touched
+ * this button" or "this dialog was displayed".
+ * Keep the UI event stream clean: don't use for system or background events.
+ * Log using the UiEventLogger wrapper - don't write with the StatsLog API directly.
+ */
+message UiEventReported {
+    // The event_id.
+    optional int32 event_id = 1;
+    // The event's source or target uid and package, if applicable.
+    // For example, the package posting a notification, or the destination package of a share.
+    optional int32 uid = 2 [(is_uid) = true];
+    optional string package_name = 3;
+}
+
+/**
  * Logs when a biometric acquire event occurs.
  *
  * Logged from:
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/cmds/svc/src/com/android/commands/svc/Svc.java b/cmds/svc/src/com/android/commands/svc/Svc.java
index 68fb8e6..e602e2a 100644
--- a/cmds/svc/src/com/android/commands/svc/Svc.java
+++ b/cmds/svc/src/com/android/commands/svc/Svc.java
@@ -94,7 +94,7 @@
             COMMAND_HELP,
             new PowerCommand(),
             new DataCommand(),
-            new WifiCommand(),
+            // `svc wifi` has been migrated to WifiShellCommand
             new UsbCommand(),
             new NfcCommand(),
             new BluetoothCommand(),
diff --git a/cmds/svc/src/com/android/commands/svc/WifiCommand.java b/cmds/svc/src/com/android/commands/svc/WifiCommand.java
deleted file mode 100644
index e31cb53..0000000
--- a/cmds/svc/src/com/android/commands/svc/WifiCommand.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.commands.svc;
-
-import android.os.ServiceManager;
-import android.os.RemoteException;
-import android.net.wifi.IWifiManager;
-import android.content.Context;
-
-public class WifiCommand extends Svc.Command {
-    public WifiCommand() {
-        super("wifi");
-    }
-
-    public String shortHelp() {
-        return "Control the Wi-Fi manager";
-    }
-
-    public String longHelp() {
-        return shortHelp() + "\n"
-                + "\n"
-                + "usage: svc wifi [enable|disable]\n"
-                + "         Turn Wi-Fi on or off.\n\n";
-    }
-
-    public void run(String[] args) {
-        boolean validCommand = false;
-        if (args.length >= 2) {
-            boolean flag = false;
-            if ("enable".equals(args[1])) {
-                flag = true;
-                validCommand = true;
-            } else if ("disable".equals(args[1])) {
-                flag = false;
-                validCommand = true;
-            }
-            if (validCommand) {
-                IWifiManager wifiMgr
-                        = IWifiManager.Stub.asInterface(ServiceManager.getService(Context.WIFI_SERVICE));
-                if (wifiMgr == null) {
-                    System.err.println("Wi-Fi service is not ready");
-                    return;
-                }
-                try {
-                    wifiMgr.setWifiEnabled("com.android.shell", flag);
-                }
-                catch (RemoteException e) {
-                    System.err.println("Wi-Fi operation failed: " + e);
-                }
-                return;
-            }
-        }
-        System.err.println(longHelp());
-    }
-}
diff --git a/cmds/svc/svc b/cmds/svc/svc
index c122e98..60c95c7 100755
--- a/cmds/svc/svc
+++ b/cmds/svc/svc
@@ -1,3 +1,24 @@
 #!/system/bin/sh
+
+# `svc wifi` has been migrated to WifiShellCommand,
+# simply perform translation to `cmd wifi set-wifi-enabled` here.
+if [ "x$1" == "xwifi" ]; then
+    # `cmd wifi` by convention uses enabled/disabled
+    # instead of enable/disable
+    if [ "x$2" == "xenable" ]; then
+        exec cmd wifi set-wifi-enabled enabled
+    elif [ "x$2" == "xdisable" ]; then
+        exec cmd wifi set-wifi-enabled disabled
+    else
+        echo "Control the Wi-Fi manager"
+        echo ""
+        echo "usage: svc wifi [enable|disable]"
+        echo "         Turn Wi-Fi on or off."
+        echo ""
+    fi
+    exit 1
+fi
+
 export CLASSPATH=/system/framework/svc.jar
 exec app_process /system/bin com.android.commands.svc.Svc "$@"
+
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/accessibilityservice/AccessibilityServiceInfo.java b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
index 61c5dac..3db0b26 100644
--- a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
+++ b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
@@ -18,7 +18,6 @@
 
 import static android.content.pm.PackageManager.FEATURE_FINGERPRINT;
 
-import android.accessibilityservice.AccessibilityButtonController.AccessibilityButtonCallback;
 import android.annotation.IntDef;
 import android.annotation.IntRange;
 import android.annotation.UnsupportedAppUsage;
@@ -333,14 +332,6 @@
      */
     public static final int FLAG_REQUEST_SHORTCUT_WARNING_DIALOG_SPOKEN_FEEDBACK = 0x00000400;
 
-    /**
-     * This flag indicates that the accessibility service will handle the shortcut action itself.
-     * A callback {@link AccessibilityButtonCallback#onClicked(AccessibilityButtonController)} is
-     * called when the user presses the accessibility shortcut. Otherwise, the service is enabled
-     * or disabled by the system instead.
-     */
-    public static final int FLAG_HANDLE_SHORTCUT = 0x00000800;
-
     /** {@hide} */
     public static final int FLAG_FORCE_DIRECT_BOOT_AWARE = 0x00010000;
 
@@ -448,7 +439,6 @@
      * @see #FLAG_ENABLE_ACCESSIBILITY_VOLUME
      * @see #FLAG_REQUEST_ACCESSIBILITY_BUTTON
      * @see #FLAG_REQUEST_SHORTCUT_WARNING_DIALOG_SPOKEN_FEEDBACK
-     * @see #FLAG_HANDLE_SHORTCUT
      */
     public int flags;
 
@@ -680,9 +670,8 @@
         }
         try {
             if (platformCompat != null) {
-                return platformCompat.isChangeEnabledByPackageName(
-                        REQUEST_ACCESSIBILITY_BUTTON_CHANGE, mResolveInfo.serviceInfo.packageName,
-                        mResolveInfo.serviceInfo.applicationInfo.uid);
+                return platformCompat.isChangeEnabled(REQUEST_ACCESSIBILITY_BUTTON_CHANGE,
+                        mResolveInfo.serviceInfo.applicationInfo);
             }
         } catch (RemoteException ignore) {
         }
@@ -1163,8 +1152,6 @@
                 return "FLAG_REQUEST_FINGERPRINT_GESTURES";
             case FLAG_REQUEST_SHORTCUT_WARNING_DIALOG_SPOKEN_FEEDBACK:
                 return "FLAG_REQUEST_SHORTCUT_WARNING_DIALOG_SPOKEN_FEEDBACK";
-            case FLAG_HANDLE_SHORTCUT:
-                return "FLAG_HANDLE_SHORTCUT";
             default:
                 return null;
         }
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index afb7871..5032f77 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -1213,7 +1213,6 @@
             OP_START_FOREGROUND,
             OP_SMS_FINANCIAL_TRANSACTIONS,
             OP_MANAGE_IPSEC_TUNNELS,
-            OP_GET_USAGE_STATS,
             OP_INSTANT_APP_START_FOREGROUND
     };
 
diff --git a/core/java/android/app/ExpandableListActivity.java b/core/java/android/app/ExpandableListActivity.java
index e08f25a..22de878 100644
--- a/core/java/android/app/ExpandableListActivity.java
+++ b/core/java/android/app/ExpandableListActivity.java
@@ -150,7 +150,11 @@
  * 
  * @see #setListAdapter
  * @see android.widget.ExpandableListView
+ *
+ * @deprecated Use {@link androidx.recyclerview.widget.RecyclerView} or use
+ *   {@link android.widget.ExpandableListView} directly
  */
+@Deprecated
 public class ExpandableListActivity extends Activity implements
         OnCreateContextMenuListener,
         ExpandableListView.OnChildClickListener, ExpandableListView.OnGroupCollapseListener,
diff --git a/core/java/android/app/ISearchManager.aidl b/core/java/android/app/ISearchManager.aidl
index 53f1a46..0119707 100644
--- a/core/java/android/app/ISearchManager.aidl
+++ b/core/java/android/app/ISearchManager.aidl
@@ -31,6 +31,5 @@
    @UnsupportedAppUsage
    ComponentName getGlobalSearchActivity();
    ComponentName getWebSearchActivity();
-   void launchAssist(in Bundle args);
-   boolean launchLegacyAssist(String hint, int userHandle, in Bundle args);
+   void launchAssist(int userHandle, in Bundle args);
 }
diff --git a/core/java/android/app/LauncherActivity.java b/core/java/android/app/LauncherActivity.java
index 88e2356..b495b3c 100644
--- a/core/java/android/app/LauncherActivity.java
+++ b/core/java/android/app/LauncherActivity.java
@@ -53,7 +53,11 @@
  * Displays a list of all activities which can be performed
  * for a given intent. Launches when clicked.
  *
+ * @deprecated Applications can implement this UI themselves using
+ *   {@link androidx.recyclerview.widget.RecyclerView} and
+ *   {@link android.content.pm.PackageManager#queryIntentActivities(Intent, int)}
  */
+@Deprecated
 public abstract class LauncherActivity extends ListActivity {
     Intent mIntent;
     PackageManager mPackageManager;
diff --git a/core/java/android/app/ListActivity.java b/core/java/android/app/ListActivity.java
index 2162521..810cca2 100644
--- a/core/java/android/app/ListActivity.java
+++ b/core/java/android/app/ListActivity.java
@@ -171,7 +171,11 @@
  *
  * @see #setListAdapter
  * @see android.widget.ListView
+ *
+ * @deprecated Use {@link androidx.fragment.app.ListFragment} or
+ *   {@link androidx.recyclerview.widget.RecyclerView} to implement your Activity instead.
  */
+@Deprecated
 public class ListActivity extends Activity {
     /**
      * This field should be made private, so it is hidden from the SDK.
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index fce7449..b37cc26 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -627,6 +627,13 @@
      */
     public static final int FLAG_BUBBLE = 0x00001000;
 
+    /** @hide */
+    @IntDef({FLAG_SHOW_LIGHTS, FLAG_ONGOING_EVENT, FLAG_INSISTENT, FLAG_ONLY_ALERT_ONCE,
+            FLAG_AUTO_CANCEL, FLAG_NO_CLEAR, FLAG_FOREGROUND_SERVICE, FLAG_HIGH_PRIORITY,
+            FLAG_LOCAL_ONLY, FLAG_GROUP_SUMMARY, FLAG_AUTOGROUP_SUMMARY, FLAG_BUBBLE})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface NotificationFlags{};
+
     public int flags;
 
     /** @hide */
@@ -4545,10 +4552,15 @@
         }
 
         /**
-         * @hide
+         * Set the value for a notification flag
+         *
+         * @param mask Bit mask of the flag
+         * @param value Status (on/off) of the flag
+         *
+         * @return The same Builder.
          */
         @NonNull
-        public Builder setFlag(int mask, boolean value) {
+        public Builder setFlag(@NotificationFlags int mask, boolean value) {
             if (value) {
                 mN.flags |= mask;
             } else {
@@ -10410,6 +10422,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/SearchManager.java b/core/java/android/app/SearchManager.java
index acca6fc..b10c3e2 100644
--- a/core/java/android/app/SearchManager.java
+++ b/core/java/android/app/SearchManager.java
@@ -16,6 +16,8 @@
 
 package android.app;
 
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
 import android.annotation.SystemService;
 import android.annotation.UnsupportedAppUsage;
 import android.content.ActivityNotFoundException;
@@ -973,37 +975,22 @@
     }
 
     /**
-     * Starts the assistant.
+     * Starts the {@link android.provider.Settings.Secure#ASSISTANT assistant}.
      *
-     * @param args the args to pass to the assistant
+     * @param args a {@code Bundle} that will be passed to the assistant's
+     *         {@link android.service.voice.VoiceInteractionSession#onShow VoiceInteractionSession}
+     *         (or as {@link Intent#getExtras() extras} along
+     *         {@link Intent#ACTION_ASSIST ACTION_ASSIST} for legacy assistants)
      *
      * @hide
      */
-    @UnsupportedAppUsage
-    public void launchAssist(Bundle args) {
+    @SystemApi
+    public void launchAssist(@Nullable Bundle args) {
         try {
             if (mService == null) {
                 return;
             }
-            mService.launchAssist(args);
-        } catch (RemoteException re) {
-            throw re.rethrowFromSystemServer();
-        }
-    }
-
-    /**
-     * Starts the legacy assistant (i.e. the {@link Intent#ACTION_ASSIST}).
-     *
-     * @param args the args to pass to the assistant
-     *
-     * @hide
-     */
-    public boolean launchLegacyAssist(String hint, int userHandle, Bundle args) {
-        try {
-            if (mService == null) {
-                return false;
-            }
-            return mService.launchLegacyAssist(hint, userHandle, args);
+            mService.launchAssist(mContext.getUserId(), args);
         } catch (RemoteException re) {
             throw re.rethrowFromSystemServer();
         }
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index d40261f..0bfd2c6 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;
@@ -115,16 +116,7 @@
 import android.net.lowpan.LowpanManager;
 import android.net.nsd.INsdManager;
 import android.net.nsd.NsdManager;
-import android.net.wifi.IWifiScanner;
-import android.net.wifi.RttManager;
-import android.net.wifi.WifiManager;
-import android.net.wifi.WifiScanner;
-import android.net.wifi.aware.IWifiAwareManager;
-import android.net.wifi.aware.WifiAwareManager;
-import android.net.wifi.p2p.IWifiP2pManager;
-import android.net.wifi.p2p.WifiP2pManager;
-import android.net.wifi.rtt.IWifiRttManager;
-import android.net.wifi.rtt.WifiRttManager;
+import android.net.wifi.WifiFrameworkInitializer;
 import android.nfc.NfcManager;
 import android.os.BatteryManager;
 import android.os.BatteryStats;
@@ -690,66 +682,6 @@
                         ConnectivityThread.getInstanceLooper());
             }});
 
-        registerService(Context.WIFI_SERVICE, WifiManager.class,
-                new CachedServiceFetcher<WifiManager>() {
-            @Override
-            public WifiManager createService(ContextImpl ctx) {
-                return new WifiManager(ctx.getOuterContext(),
-                        ConnectivityThread.getInstanceLooper());
-            }});
-
-        registerService(Context.WIFI_P2P_SERVICE, WifiP2pManager.class,
-                new StaticServiceFetcher<WifiP2pManager>() {
-            @Override
-            public WifiP2pManager createService() throws ServiceNotFoundException {
-                IBinder b = ServiceManager.getServiceOrThrow(Context.WIFI_P2P_SERVICE);
-                IWifiP2pManager service = IWifiP2pManager.Stub.asInterface(b);
-                return new WifiP2pManager(service);
-            }});
-
-        registerService(Context.WIFI_AWARE_SERVICE, WifiAwareManager.class,
-                new CachedServiceFetcher<WifiAwareManager>() {
-            @Override
-            public WifiAwareManager createService(ContextImpl ctx) throws ServiceNotFoundException {
-                IBinder b = ServiceManager.getServiceOrThrow(Context.WIFI_AWARE_SERVICE);
-                IWifiAwareManager service = IWifiAwareManager.Stub.asInterface(b);
-                if (service == null) {
-                    return null;
-                }
-                return new WifiAwareManager(ctx.getOuterContext(), service);
-            }});
-
-        registerService(Context.WIFI_SCANNING_SERVICE, WifiScanner.class,
-                new CachedServiceFetcher<WifiScanner>() {
-            @Override
-            public WifiScanner createService(ContextImpl ctx) throws ServiceNotFoundException {
-                IBinder b = ServiceManager.getServiceOrThrow(Context.WIFI_SCANNING_SERVICE);
-                IWifiScanner service = IWifiScanner.Stub.asInterface(b);
-                return new WifiScanner(ctx.getOuterContext(), service,
-                        ConnectivityThread.getInstanceLooper());
-            }});
-
-        registerService(Context.WIFI_RTT_SERVICE, RttManager.class,
-                new CachedServiceFetcher<RttManager>() {
-                @Override
-                public RttManager createService(ContextImpl ctx) throws ServiceNotFoundException {
-                    IBinder b = ServiceManager.getServiceOrThrow(Context.WIFI_RTT_RANGING_SERVICE);
-                    IWifiRttManager service = IWifiRttManager.Stub.asInterface(b);
-                    return new RttManager(ctx.getOuterContext(),
-                            new WifiRttManager(ctx.getOuterContext(), service));
-                }});
-
-        registerService(Context.WIFI_RTT_RANGING_SERVICE, WifiRttManager.class,
-                new CachedServiceFetcher<WifiRttManager>() {
-                    @Override
-                    public WifiRttManager createService(ContextImpl ctx)
-                            throws ServiceNotFoundException {
-                        IBinder b = ServiceManager.getServiceOrThrow(
-                                Context.WIFI_RTT_RANGING_SERVICE);
-                        IWifiRttManager service = IWifiRttManager.Stub.asInterface(b);
-                        return new WifiRttManager(ctx.getOuterContext(), service);
-                    }});
-
         registerService(Context.ETHERNET_SERVICE, EthernetManager.class,
                 new CachedServiceFetcher<EthernetManager>() {
             @Override
@@ -1263,6 +1195,8 @@
             JobSchedulerFrameworkInitializer.registerServiceWrappers();
             BlobStoreManagerFrameworkInitializer.initialize();
             TelephonyFrameworkInitializer.registerServiceWrappers();
+            AppSearchManagerFrameworkInitializer.initialize();
+            WifiFrameworkInitializer.registerServiceWrappers();
         } 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/bluetooth/BluetoothPan.java b/core/java/android/bluetooth/BluetoothPan.java
index cfb363a08..4e97627 100644
--- a/core/java/android/bluetooth/BluetoothPan.java
+++ b/core/java/android/bluetooth/BluetoothPan.java
@@ -16,8 +16,13 @@
 
 package android.bluetooth;
 
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
+import android.annotation.SuppressLint;
+import android.annotation.SystemApi;
 import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.os.Binder;
@@ -25,6 +30,8 @@
 import android.os.RemoteException;
 import android.util.Log;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -40,6 +47,7 @@
  *
  * @hide
  */
+@SystemApi
 public final class BluetoothPan implements BluetoothProfile {
     private static final String TAG = "BluetoothPan";
     private static final boolean DBG = true;
@@ -67,6 +75,7 @@
      * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to
      * receive.
      */
+    @SuppressLint("ActionValue")
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String ACTION_CONNECTION_STATE_CHANGED =
             "android.bluetooth.pan.profile.action.CONNECTION_STATE_CHANGED";
@@ -76,19 +85,32 @@
      * The local role of the PAN profile that the remote device is bound to.
      * It can be one of {@link #LOCAL_NAP_ROLE} or {@link #LOCAL_PANU_ROLE}.
      */
+    @SuppressLint("ActionValue")
     public static final String EXTRA_LOCAL_ROLE = "android.bluetooth.pan.extra.LOCAL_ROLE";
 
+    /** @hide */
+    @IntDef({PAN_ROLE_NONE, LOCAL_NAP_ROLE, LOCAL_PANU_ROLE})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface LocalPanRole {}
+
     public static final int PAN_ROLE_NONE = 0;
     /**
      * The local device is acting as a Network Access Point.
      */
     public static final int LOCAL_NAP_ROLE = 1;
-    public static final int REMOTE_NAP_ROLE = 1;
 
     /**
      * The local device is acting as a PAN User.
      */
     public static final int LOCAL_PANU_ROLE = 2;
+
+    /** @hide */
+    @IntDef({PAN_ROLE_NONE, REMOTE_NAP_ROLE, REMOTE_PANU_ROLE})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface RemotePanRole {}
+
+    public static final int REMOTE_NAP_ROLE = 1;
+
     public static final int REMOTE_PANU_ROLE = 2;
 
     /**
@@ -134,6 +156,8 @@
     /**
      * Create a BluetoothPan proxy object for interacting with the local
      * Bluetooth Service which handles the Pan profile
+     *
+     * @hide
      */
     @UnsupportedAppUsage
     /*package*/ BluetoothPan(Context context, ServiceListener listener) {
@@ -235,7 +259,7 @@
      * {@inheritDoc}
      */
     @Override
-    public List<BluetoothDevice> getConnectedDevices() {
+    public @NonNull List<BluetoothDevice> getConnectedDevices() {
         if (VDBG) log("getConnectedDevices()");
         final IBluetoothPan service = getService();
         if (service != null && isEnabled()) {
@@ -252,6 +276,7 @@
 
     /**
      * {@inheritDoc}
+     * @hide
      */
     @Override
     public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
@@ -273,7 +298,7 @@
      * {@inheritDoc}
      */
     @Override
-    public int getConnectionState(BluetoothDevice device) {
+    public int getConnectionState(@Nullable BluetoothDevice device) {
         if (VDBG) log("getState(" + device + ")");
         final IBluetoothPan service = getService();
         if (service != null && isEnabled() && isValidDevice(device)) {
@@ -288,7 +313,11 @@
         return BluetoothProfile.STATE_DISCONNECTED;
     }
 
-    @UnsupportedAppUsage
+    /**
+     * Turns on/off bluetooth tethering
+     *
+     * @param value is whether to enable or disable bluetooth tethering
+     */
     public void setBluetoothTethering(boolean value) {
         String pkgName = mContext.getOpPackageName();
         if (DBG) log("setBluetoothTethering(" + value + "), calling package:" + pkgName);
@@ -302,7 +331,11 @@
         }
     }
 
-    @UnsupportedAppUsage
+    /**
+     * Determines whether tethering is enabled
+     *
+     * @return true if tethering is on, false if not or some error occurred
+     */
     public boolean isTetheringOn() {
         if (VDBG) log("isTetheringOn()");
         final IBluetoothPan service = getService();
diff --git a/core/java/android/bluetooth/BluetoothProfile.java b/core/java/android/bluetooth/BluetoothProfile.java
index f5aa014..f1ac765 100644
--- a/core/java/android/bluetooth/BluetoothProfile.java
+++ b/core/java/android/bluetooth/BluetoothProfile.java
@@ -20,9 +20,9 @@
 import android.Manifest;
 import android.annotation.IntDef;
 import android.annotation.RequiresPermission;
+import android.annotation.SuppressLint;
 import android.annotation.SystemApi;
 import android.annotation.UnsupportedAppUsage;
-import android.os.Build;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -43,6 +43,7 @@
      * This extra represents the current connection state of the profile of the
      * Bluetooth device.
      */
+    @SuppressLint("ActionValue")
     String EXTRA_STATE = "android.bluetooth.profile.extra.STATE";
 
     /**
@@ -51,6 +52,7 @@
      * This extra represents the previous connection state of the profile of the
      * Bluetooth device.
      */
+    @SuppressLint("ActionValue")
     String EXTRA_PREVIOUS_STATE =
             "android.bluetooth.profile.extra.PREVIOUS_STATE";
 
@@ -106,7 +108,7 @@
      *
      * @hide
      */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
+    @SystemApi
     int PAN = 5;
 
     /**
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 7703e08..0fdb513 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -3335,6 +3335,7 @@
             ROLLBACK_SERVICE,
             DROPBOX_SERVICE,
             //@hide: DEVICE_IDLE_CONTROLLER,
+            //@hide: POWER_WHITELIST_MANAGER,
             DEVICE_POLICY_SERVICE,
             UI_MODE_SERVICE,
             DOWNLOAD_SERVICE,
@@ -4345,6 +4346,15 @@
     public static final String DEVICE_IDLE_CONTROLLER = "deviceidle";
 
     /**
+     * System service name for the PowerWhitelistManager.
+     *
+     * @see #getSystemService(String)
+     * @hide
+     */
+    @TestApi
+    public static final String POWER_WHITELIST_MANAGER = "power_whitelist";
+
+    /**
      * Use with {@link #getSystemService(String)} to retrieve a
      * {@link android.app.admin.DevicePolicyManager} for working with global
      * device policy management.
@@ -4898,6 +4908,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/res/AssetManager.java b/core/java/android/content/res/AssetManager.java
index 2d9ca67..168eae6 100644
--- a/core/java/android/content/res/AssetManager.java
+++ b/core/java/android/content/res/AssetManager.java
@@ -206,7 +206,7 @@
     @VisibleForTesting
     public static void createSystemAssetsInZygoteLocked(boolean reinitialize,
             String frameworkPath) {
-        if (sSystem != null || reinitialize) {
+        if (sSystem != null && !reinitialize) {
             return;
         }
 
@@ -225,7 +225,9 @@
 
             sSystemApkAssetsSet = new ArraySet<>(apkAssets);
             sSystemApkAssets = apkAssets.toArray(new ApkAssets[apkAssets.size()]);
-            sSystem = new AssetManager(true /*sentinel*/);
+            if (sSystem == null) {
+                sSystem = new AssetManager(true /*sentinel*/);
+            }
             sSystem.setApkAssets(sSystemApkAssets, false /*invalidateCaches*/);
         } catch (IOException e) {
             throw new IllegalStateException("Failed to create system AssetManager", e);
diff --git a/core/java/android/net/IpConfiguration.java b/core/java/android/net/IpConfiguration.java
index 2af82d7..143467b 100644
--- a/core/java/android/net/IpConfiguration.java
+++ b/core/java/android/net/IpConfiguration.java
@@ -16,6 +16,10 @@
 
 package android.net;
 
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SuppressLint;
+import android.annotation.SystemApi;
 import android.annotation.UnsupportedAppUsage;
 import android.net.StaticIpConfiguration;
 import android.os.Parcel;
@@ -27,13 +31,17 @@
  * A class representing a configured network.
  * @hide
  */
-public class IpConfiguration implements Parcelable {
+@SystemApi
+public final class IpConfiguration implements Parcelable {
     private static final String TAG = "IpConfiguration";
 
+    // This enum has been used by apps through reflection for many releases.
+    // Therefore they can't just be removed. Duplicating these constants to
+    // give an alternate SystemApi is a worse option than exposing them.
+    @SuppressLint("Enum")
     public enum IpAssignment {
         /* Use statically configured IP settings. Configuration can be accessed
          * with staticIpConfiguration */
-        @UnsupportedAppUsage
         STATIC,
         /* Use dynamically configured IP settings */
         DHCP,
@@ -42,14 +50,19 @@
         UNASSIGNED
     }
 
+    /** @hide */
     public IpAssignment ipAssignment;
 
+    /** @hide */
     public StaticIpConfiguration staticIpConfiguration;
 
+    // This enum has been used by apps through reflection for many releases.
+    // Therefore they can't just be removed. Duplicating these constants to
+    // give an alternate SystemApi is a worse option than exposing them.
+    @SuppressLint("Enum")
     public enum ProxySettings {
         /* No proxy is to be used. Any existing proxy settings
          * should be cleared. */
-        @UnsupportedAppUsage
         NONE,
         /* Use statically configured proxy. Configuration can be accessed
          * with httpProxy. */
@@ -62,8 +75,10 @@
         PAC
     }
 
+    /** @hide */
     public ProxySettings proxySettings;
 
+    /** @hide */
     @UnsupportedAppUsage
     public ProxyInfo httpProxy;
 
@@ -83,6 +98,7 @@
         init(IpAssignment.UNASSIGNED, ProxySettings.UNASSIGNED, null, null);
     }
 
+    /** @hide */
     @UnsupportedAppUsage
     public IpConfiguration(IpAssignment ipAssignment,
                            ProxySettings proxySettings,
@@ -91,7 +107,7 @@
         init(ipAssignment, proxySettings, staticIpConfiguration, httpProxy);
     }
 
-    public IpConfiguration(IpConfiguration source) {
+    public IpConfiguration(@NonNull IpConfiguration source) {
         this();
         if (source != null) {
             init(source.ipAssignment, source.proxySettings,
@@ -99,35 +115,35 @@
         }
     }
 
-    public IpAssignment getIpAssignment() {
+    public @NonNull IpAssignment getIpAssignment() {
         return ipAssignment;
     }
 
-    public void setIpAssignment(IpAssignment ipAssignment) {
+    public void setIpAssignment(@NonNull IpAssignment ipAssignment) {
         this.ipAssignment = ipAssignment;
     }
 
-    public StaticIpConfiguration getStaticIpConfiguration() {
+    public @Nullable StaticIpConfiguration getStaticIpConfiguration() {
         return staticIpConfiguration;
     }
 
-    public void setStaticIpConfiguration(StaticIpConfiguration staticIpConfiguration) {
+    public void setStaticIpConfiguration(@Nullable StaticIpConfiguration staticIpConfiguration) {
         this.staticIpConfiguration = staticIpConfiguration;
     }
 
-    public ProxySettings getProxySettings() {
+    public @NonNull ProxySettings getProxySettings() {
         return proxySettings;
     }
 
-    public void setProxySettings(ProxySettings proxySettings) {
+    public void setProxySettings(@NonNull ProxySettings proxySettings) {
         this.proxySettings = proxySettings;
     }
 
-    public ProxyInfo getHttpProxy() {
+    public @Nullable ProxyInfo getHttpProxy() {
         return httpProxy;
     }
 
-    public void setHttpProxy(ProxyInfo httpProxy) {
+    public void setHttpProxy(@Nullable ProxyInfo httpProxy) {
         this.httpProxy = httpProxy;
     }
 
@@ -175,13 +191,19 @@
                83 * httpProxy.hashCode();
     }
 
-    /** Implement the Parcelable interface */
+    /**
+     * Implement the Parcelable interface
+     * @hide
+     */
     public int describeContents() {
         return 0;
     }
 
-    /** Implement the Parcelable interface  */
-    public void writeToParcel(Parcel dest, int flags) {
+    /**
+     * Implement the Parcelable interface
+     * @hide
+     */
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
         dest.writeString(ipAssignment.name());
         dest.writeString(proxySettings.name());
         dest.writeParcelable(staticIpConfiguration, flags);
@@ -189,7 +211,7 @@
     }
 
     /** Implement the Parcelable interface */
-    public static final @android.annotation.NonNull Creator<IpConfiguration> CREATOR =
+    public static final @NonNull Creator<IpConfiguration> CREATOR =
         new Creator<IpConfiguration>() {
             public IpConfiguration createFromParcel(Parcel in) {
                 IpConfiguration config = new IpConfiguration();
diff --git a/core/java/android/net/NetworkKey.java b/core/java/android/net/NetworkKey.java
index 4254240..47c08a4 100644
--- a/core/java/android/net/NetworkKey.java
+++ b/core/java/android/net/NetworkKey.java
@@ -16,6 +16,7 @@
 
 package android.net;
 
+import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
@@ -27,6 +28,8 @@
 import android.text.TextUtils;
 import android.util.Log;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.Objects;
 
 /**
@@ -48,6 +51,13 @@
     /** A wifi network, for which {@link #wifiKey} will be populated. */
     public static final int TYPE_WIFI = 1;
 
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = {"TYPE_"}, value = {
+            TYPE_WIFI
+    })
+    public @interface NetworkType {}
+
     /**
      * The type of this network.
      * @see #TYPE_WIFI
@@ -65,7 +75,6 @@
      *
      * @return  A new {@link NetworkKey} instance or <code>null</code> if the given
      *          {@link ScanResult} instance is malformed.
-     * @hide
      */
     @Nullable
     public static NetworkKey createFromScanResult(@Nullable ScanResult result) {
diff --git a/core/java/android/net/NetworkScore.java b/core/java/android/net/NetworkScore.java
index 1ab6335..13f2994 100644
--- a/core/java/android/net/NetworkScore.java
+++ b/core/java/android/net/NetworkScore.java
@@ -154,4 +154,9 @@
         }
         return true;
     }
+
+    /** Convert to a string */
+    public String toString() {
+        return "NetworkScore[" + mExtensions.toString() + "]";
+    }
 }
diff --git a/core/java/android/net/NetworkScoreManager.java b/core/java/android/net/NetworkScoreManager.java
index 50dd468..f6dc525 100644
--- a/core/java/android/net/NetworkScoreManager.java
+++ b/core/java/android/net/NetworkScoreManager.java
@@ -17,7 +17,9 @@
 package android.net;
 
 import android.Manifest.permission;
+import android.annotation.CallbackExecutor;
 import android.annotation.IntDef;
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
 import android.annotation.SdkConstant;
@@ -25,13 +27,16 @@
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
 import android.content.Context;
+import android.os.Binder;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.ServiceManager.ServiceNotFoundException;
+import android.util.Log;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.List;
+import java.util.concurrent.Executor;
 
 /**
  * Class that manages communication between network subsystems and a network scorer.
@@ -50,19 +55,25 @@
 @SystemApi
 @SystemService(Context.NETWORK_SCORE_SERVICE)
 public class NetworkScoreManager {
+    private static final String TAG = "NetworkScoreManager";
+
     /**
      * Activity action: ask the user to change the active network scorer. This will show a dialog
      * that asks the user whether they want to replace the current active scorer with the one
      * specified in {@link #EXTRA_PACKAGE_NAME}. The activity will finish with RESULT_OK if the
      * active scorer was changed or RESULT_CANCELED if it failed for any reason.
+     * @deprecated No longer sent.
      */
+    @Deprecated
     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
     public static final String ACTION_CHANGE_ACTIVE = "android.net.scoring.CHANGE_ACTIVE";
 
     /**
      * Extra used with {@link #ACTION_CHANGE_ACTIVE} to specify the new scorer package. Set with
      * {@link android.content.Intent#putExtra(String, String)}.
+     * @deprecated No longer sent.
      */
+    @Deprecated
     public static final String EXTRA_PACKAGE_NAME = "packageName";
 
     /**
@@ -73,7 +84,9 @@
      * configured by the user as well as any open networks.
      *
      * <p class="note">This is a protected intent that can only be sent by the system.
+     * @deprecated Use {@link #ACTION_RECOMMEND_NETWORKS} to bind scorer app instead.
      */
+    @Deprecated
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String ACTION_SCORE_NETWORKS = "android.net.scoring.SCORE_NETWORKS";
 
@@ -81,7 +94,9 @@
      * Extra used with {@link #ACTION_SCORE_NETWORKS} to specify the networks to be scored, as an
      * array of {@link NetworkKey}s. Can be obtained with
      * {@link android.content.Intent#getParcelableArrayExtra(String)}}.
+     * @deprecated Use {@link #ACTION_RECOMMEND_NETWORKS} to bind scorer app instead.
      */
+    @Deprecated
     public static final String EXTRA_NETWORKS_TO_SCORE = "networksToScore";
 
     /**
@@ -285,7 +300,7 @@
      * @throws SecurityException if the caller is not the active scorer.
      */
     @RequiresPermission(android.Manifest.permission.SCORE_NETWORKS)
-    public boolean updateScores(ScoredNetwork[] networks) throws SecurityException {
+    public boolean updateScores(@NonNull ScoredNetwork[] networks) throws SecurityException {
         try {
             return mService.updateScores(networks);
         } catch (RemoteException e) {
@@ -359,13 +374,21 @@
     /**
      * Request scoring for networks.
      *
-     * @return true if the broadcast was sent, or false if there is no active scorer.
+     * <p>
+     * Note: The results (i.e scores) for these networks, when available will be provided via the
+     * callback registered with {@link #registerNetworkScoreCallback(int, int, Executor,
+     * NetworkScoreCallback)}. The calling module is responsible for registering a callback to
+     * receive the results before requesting new scores via this API.
+     *
+     * @return true if the request was successfully sent, or false if there is no active scorer.
      * @throws SecurityException if the caller does not hold the
      *         {@link permission#REQUEST_NETWORK_SCORES} permission.
+     *
      * @hide
      */
+    @SystemApi
     @RequiresPermission(android.Manifest.permission.REQUEST_NETWORK_SCORES)
-    public boolean requestScores(NetworkKey[] networks) throws SecurityException {
+    public boolean requestScores(@NonNull NetworkKey[] networks) throws SecurityException {
         try {
             return mService.requestScores(networks);
         } catch (RemoteException e) {
@@ -431,6 +454,88 @@
     }
 
     /**
+     * Base class for network score cache callback. Should be extended by applications and set
+     * when calling {@link #registerNetworkScoreCallback(int, int, NetworkScoreCallback,
+     * Executor)}
+     *
+     * @hide
+     */
+    @SystemApi
+    public interface NetworkScoreCallback {
+        /**
+         * Called when a new set of network scores are available.
+         * This is triggered in response when the client invokes
+         * {@link #requestScores(NetworkKey[])} to score a new set of networks.
+         *
+         * @param networks List of {@link ScoredNetwork} containing updated scores.
+         */
+        void updateScores(@NonNull List<ScoredNetwork> networks);
+
+        /**
+         * Invokes when all the previously provided scores are no longer valid.
+         */
+        void clearScores();
+    }
+
+    /**
+     * Callback proxy for {@link NetworkScoreCallback} objects.
+     */
+    private class NetworkScoreCallbackProxy extends INetworkScoreCache.Stub {
+        private final Executor mExecutor;
+        private final NetworkScoreCallback mCallback;
+
+        NetworkScoreCallbackProxy(Executor executor, NetworkScoreCallback callback) {
+            mExecutor = executor;
+            mCallback = callback;
+        }
+
+        @Override
+        public void updateScores(@NonNull List<ScoredNetwork> networks) {
+            Binder.clearCallingIdentity();
+            mExecutor.execute(() -> {
+                mCallback.updateScores(networks);
+            });
+        }
+
+        @Override
+        public void clearScores() {
+            Binder.clearCallingIdentity();
+            mExecutor.execute(() -> {
+                mCallback.clearScores();
+            });
+        }
+    }
+
+    /**
+     * Register a network score callback.
+     *
+     * @param networkType the type of network this cache can handle. See {@link NetworkKey#type}
+     * @param filterType the {@link CacheUpdateFilter} to apply
+     * @param callback implementation of {@link NetworkScoreCallback} that will be invoked when the
+     *                 scores change.
+     * @param executor The executor on which to execute the callbacks.
+     * @throws SecurityException if the caller does not hold the
+     *         {@link permission#REQUEST_NETWORK_SCORES} permission.
+     * @throws IllegalArgumentException if a callback is already registered for this type.
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.REQUEST_NETWORK_SCORES)
+    public void registerNetworkScoreCallback(@NetworkKey.NetworkType int networkType,
+            @CacheUpdateFilter int filterType,
+            @NonNull @CallbackExecutor Executor executor,
+            @NonNull NetworkScoreCallback callback) throws SecurityException {
+        if (callback == null || executor == null) {
+            throw new IllegalArgumentException("callback / executor cannot be null");
+        }
+        Log.v(TAG, "registerNetworkScoreCallback: callback=" + callback + ", executor="
+                + executor);
+        // Use the @hide method.
+        registerNetworkScoreCache(
+                networkType, new NetworkScoreCallbackProxy(executor, callback), filterType);
+    }
+
+    /**
      * Determine whether the application with the given UID is the enabled scorer.
      *
      * @param callingUid the UID to check
diff --git a/core/java/android/net/ProxyInfo.java b/core/java/android/net/ProxyInfo.java
index 807c467..9d92db4 100644
--- a/core/java/android/net/ProxyInfo.java
+++ b/core/java/android/net/ProxyInfo.java
@@ -16,7 +16,8 @@
 
 package android.net;
 
-
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -89,6 +90,15 @@
     }
 
     /**
+     * Construct a {@link ProxyInfo} object that will download and run the PAC script at the
+     * specified URL and port.
+     */
+    @NonNull
+    public static ProxyInfo buildPacProxy(@NonNull Uri pacUrl, int port) {
+        return new ProxyInfo(pacUrl, port);
+    }
+
+    /**
      * Create a ProxyProperties that points at a HTTP Proxy.
      * @hide
      */
@@ -105,7 +115,7 @@
      * Create a ProxyProperties that points at a PAC URL.
      * @hide
      */
-    public ProxyInfo(Uri pacFileUrl) {
+    public ProxyInfo(@NonNull Uri pacFileUrl) {
         mHost = LOCAL_HOST;
         mPort = LOCAL_PORT;
         mExclusionList = LOCAL_EXCL_LIST;
@@ -132,7 +142,7 @@
      * Only used in PacManager after Local Proxy is bound.
      * @hide
      */
-    public ProxyInfo(Uri pacFileUrl, int localProxyPort) {
+    public ProxyInfo(@NonNull Uri pacFileUrl, int localProxyPort) {
         mHost = LOCAL_HOST;
         mPort = localProxyPort;
         mExclusionList = LOCAL_EXCL_LIST;
@@ -159,11 +169,10 @@
         mPacFileUrl = Uri.EMPTY;
     }
 
-    // copy constructor instead of clone
     /**
-     * @hide
+     * A copy constructor to hold proxy properties.
      */
-    public ProxyInfo(ProxyInfo source) {
+    public ProxyInfo(@Nullable ProxyInfo source) {
         if (source != null) {
             mHost = source.getHost();
             mPort = source.getPort();
@@ -226,12 +235,13 @@
      * comma separated
      * @hide
      */
+    @Nullable
     public String getExclusionListAsString() {
         return mExclusionList;
     }
 
     /**
-     * @hide
+     * Return true if the pattern of proxy is valid, otherwise return false.
      */
     public boolean isValid() {
         if (!Uri.EMPTY.equals(mPacFileUrl)) return true;
diff --git a/core/java/android/os/FileUtils.java b/core/java/android/os/FileUtils.java
index f789b72..2ac3def 100644
--- a/core/java/android/os/FileUtils.java
+++ b/core/java/android/os/FileUtils.java
@@ -1275,7 +1275,13 @@
     /**
      * Closes the given object quietly, ignoring any checked exceptions. Does
      * nothing if the given object is {@code null}.
+     *
+     * @deprecated This method may suppress potentially significant exceptions, particularly when
+     *   closing writable resources. With a writable resource, a failure thrown from {@code close()}
+     *   should be considered as significant as a failure thrown from a write method because it may
+     *   indicate a failure to flush bytes to the underlying resource.
      */
+    @Deprecated
     public static void closeQuietly(@Nullable AutoCloseable closeable) {
         IoUtils.closeQuietly(closeable);
     }
@@ -1283,7 +1289,13 @@
     /**
      * Closes the given object quietly, ignoring any checked exceptions. Does
      * nothing if the given object is {@code null}.
+     *
+     * @deprecated This method may suppress potentially significant exceptions, particularly when
+     *   closing writable resources. With a writable resource, a failure thrown from {@code close()}
+     *   should be considered as significant as a failure thrown from a write method because it may
+     *   indicate a failure to flush bytes to the underlying resource.
      */
+    @Deprecated
     public static void closeQuietly(@Nullable FileDescriptor fd) {
         IoUtils.closeQuietly(fd);
     }
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..b08822dd
--- /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/Looper.java b/core/java/android/os/Looper.java
index 3222fc4..d468972 100644
--- a/core/java/android/os/Looper.java
+++ b/core/java/android/os/Looper.java
@@ -112,10 +112,12 @@
 
     /**
      * Initialize the current thread as a looper, marking it as an
-     * application's main looper. The main looper for your application
-     * is created by the Android environment, so you should never need
-     * to call this function yourself.  See also: {@link #prepare()}
+     * application's main looper. See also: {@link #prepare()}
+     *
+     * @deprecated The main looper for your application is created by the Android environment,
+     *   so you should never need to call this function yourself.
      */
+    @Deprecated
     public static void prepareMainLooper() {
         prepare(false);
         synchronized (Looper.class) {
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java
index deeeddc..2d70986d 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -2362,6 +2362,19 @@
         }
     }
 
+    /**
+     * Check whether the device supports filesystem checkpoint.
+     *
+     * @return true if the device supports filesystem checkpoint, false otherwise.
+     */
+    public boolean isCheckpointSupported() {
+        try {
+            return mStorageManager.supportsCheckpoint();
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
     private final Object mFuseAppLoopLock = new Object();
 
     @GuardedBy("mFuseAppLoopLock")
diff --git a/core/java/android/provider/DeviceConfig.java b/core/java/android/provider/DeviceConfig.java
index 1d7e338..abf34ca 100644
--- a/core/java/android/provider/DeviceConfig.java
+++ b/core/java/android/provider/DeviceConfig.java
@@ -391,8 +391,9 @@
      * Look up the values of multiple properties for a particular namespace. The lookup is atomic,
      * such that the values of these properties cannot change between the time when the first is
      * fetched and the time when the last is fetched.
-     *
-     * TODO: reference setProperties when it is added.
+     * <p>
+     * Each call to {@link #setProperties(Properties)} is also atomic and ensures that either none
+     * or all of the change is picked up here, but never only part of it.
      *
      * @param namespace The namespace containing the properties to look up.
      * @param names     The names of properties to look up, or empty to fetch all properties for the
@@ -560,6 +561,27 @@
     }
 
     /**
+     * Set all of the properties for a specific namespace. Pre-existing properties will be updated
+     * and new properties will be added if necessary. Any pre-existing properties for the specific
+     * namespace which are not part of the provided {@link Properties} object will be deleted from
+     * the namespace. These changes are all applied atomically, such that no calls to read or reset
+     * these properties can happen in the middle of this update.
+     * <p>
+     * Each call to {@link #getProperties(String, String...)} is also atomic and ensures that either
+     * none or all of this update is picked up, but never only part of it.
+     *
+     * @param properties the complete set of properties to set for a specific namespace.
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(WRITE_DEVICE_CONFIG)
+    public static boolean setProperties(@NonNull Properties properties) {
+        ContentResolver contentResolver = ActivityThread.currentApplication().getContentResolver();
+        return Settings.Config.setStrings(contentResolver, properties.getNamespace(),
+                properties.mMap);
+    }
+
+    /**
      * Reset properties to their default values.
      * <p>
      * The method accepts an optional namespace parameter. If provided, only properties set within
@@ -703,23 +725,26 @@
         List<String> pathSegments = uri.getPathSegments();
         // pathSegments(0) is "config"
         final String namespace = pathSegments.get(1);
-        final String name = pathSegments.get(2);
-        final String value;
+        Map<String, String> propertyMap = new ArrayMap<>();
         try {
-            value = getProperty(namespace, name);
+            Properties allProperties = getProperties(namespace);
+            for (int i = 2; i < pathSegments.size(); ++i) {
+                String key = pathSegments.get(i);
+                propertyMap.put(key, allProperties.getString(key, null));
+            }
         } catch (SecurityException e) {
             // Silently failing to not crash binder or listener threads.
             Log.e(TAG, "OnPropertyChangedListener update failed: permission violation.");
             return;
         }
+        Properties properties = new Properties(namespace, propertyMap);
+
         synchronized (sLock) {
             for (int i = 0; i < sListeners.size(); i++) {
                 if (namespace.equals(sListeners.valueAt(i).first)) {
                     final OnPropertiesChangedListener listener = sListeners.keyAt(i);
                     sListeners.valueAt(i).second.execute(() -> {
-                        Map<String, String> propertyMap = new ArrayMap<>(1);
-                        propertyMap.put(name, value);
-                        listener.onPropertiesChanged(new Properties(namespace, propertyMap));
+                        listener.onPropertiesChanged(properties);
                     });
                 }
             }
@@ -741,7 +766,11 @@
     }
 
     /**
-     * Interface for monitoring changes to properties.
+     * Interface for monitoring changes to properties. Implementations will receive callbacks when
+     * properties change, including a {@link Properties} object which contains a single namespace
+     * and all of the properties which changed for that namespace. This includes properties which
+     * were added, updated, or deleted. This is not necessarily a complete list of all properties
+     * belonging to the namespace, as properties which don't change are omitted.
      * <p>
      * Override {@link #onPropertiesChanged(Properties)} to handle callbacks for changes.
      *
@@ -751,10 +780,13 @@
     @TestApi
     public interface OnPropertiesChangedListener {
         /**
-         * Called when one or more properties have changed.
+         * Called when one or more properties have changed, providing a Properties object with all
+         * of the changed properties. This object will contain only properties which have changed,
+         * not the complete set of all properties belonging to the namespace.
          *
          * @param properties Contains the complete collection of properties which have changed for a
-         *                   single namespace.
+         *                   single namespace. This includes only those which were added, updated,
+         *                   or deleted.
          */
         void onPropertiesChanged(@NonNull Properties properties);
     }
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 3ac7deb..0af2c36 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -1960,6 +1960,11 @@
      */
     public static final String CALL_METHOD_PREFIX_KEY = "_prefix";
 
+    /**
+     * @hide - String argument extra to the fast-path call()-based requests
+     */
+    public static final String CALL_METHOD_FLAGS_KEY = "_flags";
+
     /** @hide - Private call() method to write to 'system' table */
     public static final String CALL_METHOD_PUT_SYSTEM = "PUT_system";
 
@@ -1972,6 +1977,9 @@
     /** @hide - Private call() method to write to 'configuration' table */
     public static final String CALL_METHOD_PUT_CONFIG = "PUT_config";
 
+    /** @hide - Private call() method to write to and delete from the 'configuration' table */
+    public static final String CALL_METHOD_SET_ALL_CONFIG = "SET_ALL_config";
+
     /** @hide - Private call() method to delete from the 'system' table */
     public static final String CALL_METHOD_DELETE_SYSTEM = "DELETE_system";
 
@@ -2304,21 +2312,23 @@
         private final String mCallGetCommand;
         private final String mCallSetCommand;
         private final String mCallListCommand;
+        private final String mCallSetAllCommand;
 
         @GuardedBy("this")
         private GenerationTracker mGenerationTracker;
 
         public NameValueCache(Uri uri, String getCommand, String setCommand,
                 ContentProviderHolder providerHolder) {
-            this(uri, getCommand, setCommand, null, providerHolder);
+            this(uri, getCommand, setCommand, null, null, providerHolder);
         }
 
         NameValueCache(Uri uri, String getCommand, String setCommand, String listCommand,
-                ContentProviderHolder providerHolder) {
+                String setAllCommand, ContentProviderHolder providerHolder) {
             mUri = uri;
             mCallGetCommand = getCommand;
             mCallSetCommand = setCommand;
             mCallListCommand = listCommand;
+            mCallSetAllCommand = setAllCommand;
             mProviderHolder = providerHolder;
         }
 
@@ -2344,6 +2354,26 @@
             return true;
         }
 
+        public boolean setStringsForPrefix(ContentResolver cr, String prefix,
+                HashMap<String, String> keyValues) {
+            if (mCallSetAllCommand == null) {
+                // This NameValueCache does not support atomically setting multiple flags
+                return false;
+            }
+            try {
+                Bundle args = new Bundle();
+                args.putString(CALL_METHOD_PREFIX_KEY, prefix);
+                args.putSerializable(CALL_METHOD_FLAGS_KEY, keyValues);
+                IContentProvider cp = mProviderHolder.getProvider(cr);
+                cp.call(cr.getPackageName(), cr.getFeatureId(), mProviderHolder.mUri.getAuthority(),
+                        mCallSetAllCommand, null, args);
+            } catch (RemoteException e) {
+                // Not supported by the remote side
+                return false;
+            }
+            return true;
+        }
+
         @UnsupportedAppUsage
         public String getStringForUser(ContentResolver cr, String name, final int userHandle) {
             final boolean isSelf = (userHandle == UserHandle.myUserId());
@@ -6161,8 +6191,12 @@
                 "accessibility_shortcut_dialog_shown";
 
         /**
-         * Setting specifying the accessibility service to be toggled via the accessibility
-         * shortcut. Must be its flattened {@link ComponentName}.
+         * Setting specifying the accessibility services, accessibility shortcut targets,
+         * or features to be toggled via the accessibility shortcut.
+         *
+         * <p> This is a colon-separated string list which contains the flattened
+         * {@link ComponentName} and the class name of a system class implementing a supported
+         * accessibility feature.
          * @hide
          */
         @UnsupportedAppUsage
@@ -6171,9 +6205,11 @@
                 "accessibility_shortcut_target_service";
 
         /**
-         * Setting specifying the accessibility service or feature to be toggled via the
-         * accessibility button in the navigation bar. This is either a flattened
-         * {@link ComponentName} or the class name of a system class implementing a supported
+         * Setting specifying the accessibility services, accessibility shortcut targets,
+         * or features to be toggled via the accessibility button in the navigation bar.
+         *
+         * <p> This is a colon-separated string list which contains the flattened
+         * {@link ComponentName} and the class name of a system class implementing a supported
          * accessibility feature.
          * @hide
          */
@@ -6334,6 +6370,9 @@
          * zoom in the display content and is targeted to low vision users. The current
          * magnification scale is controlled by {@link #ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE}.
          *
+         * @deprecated Use {@link #ACCESSIBILITY_BUTTON_TARGET_COMPONENT} instead.
+         * {@link #ACCESSIBILITY_BUTTON_TARGET_COMPONENT} holds the magnification system class name
+         * when navigation bar magnification is enabled.
          * @hide
          */
         @SystemApi
@@ -7140,16 +7179,6 @@
         public static final String VOICE_RECOGNITION_SERVICE = "voice_recognition_service";
 
         /**
-         * Stores whether an user has consented to have apps verified through PAM.
-         * The value is boolean (1 or 0).
-         *
-         * @hide
-         */
-        @UnsupportedAppUsage
-        public static final String PACKAGE_VERIFIER_USER_CONSENT =
-            "package_verifier_user_consent";
-
-        /**
          * The {@link ComponentName} string of the selected spell checker service which is
          * one of the services managed by the text service manager.
          *
@@ -11889,6 +11918,7 @@
          * as if they had been accepted by the user.
          * @hide
          */
+        @TestApi
         public static final String HIDE_ERROR_DIALOGS = "hide_error_dialogs";
 
         /**
@@ -13718,6 +13748,7 @@
                 CALL_METHOD_GET_CONFIG,
                 CALL_METHOD_PUT_CONFIG,
                 CALL_METHOD_LIST_CONFIG,
+                CALL_METHOD_SET_ALL_CONFIG,
                 sProviderHolder);
 
         /**
@@ -13792,6 +13823,29 @@
         }
 
         /**
+         * Clear all name/value pairs for the provided namespace and save new name/value pairs in
+         * their place.
+         *
+         * @param resolver to access the database with.
+         * @param namespace to which the names should be set.
+         * @param keyValues map of key names (without the prefix) to values.
+         * @return
+         *
+         * @hide
+         */
+        @RequiresPermission(Manifest.permission.WRITE_DEVICE_CONFIG)
+        static boolean setStrings(@NonNull ContentResolver resolver, @NonNull String namespace,
+                @NonNull Map<String, String> keyValues) {
+            HashMap<String, String> compositeKeyValueMap = new HashMap<>(keyValues.keySet().size());
+            for (Map.Entry<String, String> entry : keyValues.entrySet()) {
+                compositeKeyValueMap.put(
+                        createCompositeName(namespace, entry.getKey()), entry.getValue());
+            }
+            return sNameValueCache.setStringsForPrefix(resolver, createPrefix(namespace),
+                    compositeKeyValueMap);
+        }
+
+        /**
          * Reset the values to their defaults.
          * <p>
          * The method accepts an optional prefix parameter. If provided, only pairs with a name that
diff --git a/core/java/android/util/StatsEvent.java b/core/java/android/util/StatsEvent.java
index 10c9d87..d7ec30c 100644
--- a/core/java/android/util/StatsEvent.java
+++ b/core/java/android/util/StatsEvent.java
@@ -45,6 +45,166 @@
  * @hide
  **/
 public final class StatsEvent implements Parcelable {
+    // Type Ids.
+    /**
+     * @hide
+     **/
+    @VisibleForTesting
+    public static final byte TYPE_INT = 0x00;
+
+    /**
+     * @hide
+     **/
+    @VisibleForTesting
+    public static final byte TYPE_LONG = 0x01;
+
+    /**
+     * @hide
+     **/
+    @VisibleForTesting
+    public static final byte TYPE_STRING = 0x02;
+
+    /**
+     * @hide
+     **/
+    @VisibleForTesting
+    public static final byte TYPE_LIST = 0x03;
+
+    /**
+     * @hide
+     **/
+    @VisibleForTesting
+    public static final byte TYPE_FLOAT = 0x04;
+
+    /**
+     * @hide
+     **/
+    @VisibleForTesting
+    public static final byte TYPE_BOOLEAN = 0x05;
+
+    /**
+     * @hide
+     **/
+    @VisibleForTesting
+    public static final byte TYPE_BYTE_ARRAY = 0x06;
+
+    /**
+     * @hide
+     **/
+    @VisibleForTesting
+    public static final byte TYPE_OBJECT = 0x07;
+
+    /**
+     * @hide
+     **/
+    @VisibleForTesting
+    public static final byte TYPE_KEY_VALUE_PAIRS = 0x08;
+
+    /**
+     * @hide
+     **/
+    @VisibleForTesting
+    public static final byte TYPE_ATTRIBUTION_CHAIN = 0x09;
+
+    /**
+     * @hide
+     **/
+    @VisibleForTesting
+    public static final byte TYPE_ERRORS = 0x0F;
+
+    // Error flags.
+    /**
+     * @hide
+     **/
+    @VisibleForTesting
+    public static final int ERROR_NO_TIMESTAMP = 0x1;
+
+    /**
+     * @hide
+     **/
+    @VisibleForTesting
+    public static final int ERROR_NO_ATOM_ID = 0x2;
+
+    /**
+     * @hide
+     **/
+    @VisibleForTesting
+    public static final int ERROR_OVERFLOW = 0x4;
+
+    /**
+     * @hide
+     **/
+    @VisibleForTesting
+    public static final int ERROR_ATTRIBUTION_CHAIN_TOO_LONG = 0x8;
+
+    /**
+     * @hide
+     **/
+    @VisibleForTesting
+    public static final int ERROR_TOO_MANY_KEY_VALUE_PAIRS = 0x10;
+
+    /**
+     * @hide
+     **/
+    @VisibleForTesting
+    public static final int ERROR_ANNOTATION_DOES_NOT_FOLLOW_FIELD = 0x20;
+
+    /**
+     * @hide
+     **/
+    @VisibleForTesting
+    public static final int ERROR_INVALID_ANNOTATION_ID = 0x40;
+
+    /**
+     * @hide
+     **/
+    @VisibleForTesting
+    public static final int ERROR_ANNOTATION_ID_TOO_LARGE = 0x80;
+
+    /**
+     * @hide
+     **/
+    @VisibleForTesting
+    public static final int ERROR_TOO_MANY_ANNOTATIONS = 0x100;
+
+    /**
+     * @hide
+     **/
+    @VisibleForTesting
+    public static final int ERROR_TOO_MANY_FIELDS = 0x200;
+
+    /**
+     * @hide
+     **/
+    @VisibleForTesting
+    public static final int ERROR_ATTRIBUTION_UIDS_TAGS_SIZES_NOT_EQUAL = 0x400;
+
+    // Size limits.
+
+    /**
+     * @hide
+     **/
+    @VisibleForTesting
+    public static final int MAX_ANNOTATION_COUNT = 15;
+
+    /**
+     * @hide
+     **/
+    @VisibleForTesting
+    public static final int MAX_ATTRIBUTION_NODES = 127;
+
+    /**
+     * @hide
+     **/
+    @VisibleForTesting
+    public static final int MAX_NUM_ELEMENTS = 127;
+
+    /**
+     * @hide
+     **/
+    @VisibleForTesting
+    public static final int MAX_KEY_VALUE_PAIRS = 127;
+
     private static final int LOGGER_ENTRY_MAX_PAYLOAD = 4068;
 
     // Max payload size is 4 bytes less as 4 bytes are reserved for statsEventTag.
@@ -69,24 +229,75 @@
         return new StatsEvent.Builder(Buffer.obtain());
     }
 
-    int getAtomId() {
+    /**
+     * Get the atom Id of the atom encoded in this StatsEvent object.
+     *
+     * @hide
+     **/
+    public int getAtomId() {
         return mAtomId;
     }
 
+    /**
+     * Get the byte array that contains the encoded payload that can be sent to statsd.
+     *
+     * @hide
+     **/
     @NonNull
-    byte[] getBytes() {
+    public byte[] getBytes() {
         return mBuffer.getBytes();
     }
 
-    int getNumBytes() {
+    /**
+     * Get the number of bytes used to encode the StatsEvent payload.
+     *
+     * @hide
+     **/
+    public int getNumBytes() {
         return mNumBytes;
     }
 
-    void release() {
+    /**
+     * Recycle this StatsEvent object.
+     **/
+    public void release() {
         mBuffer.release();
     }
 
     /**
+     * Boilerplate for Parcel.
+     */
+    public static final @NonNull Parcelable.Creator<StatsEvent> CREATOR =
+            new Parcelable.Creator<StatsEvent>() {
+                public StatsEvent createFromParcel(Parcel in) {
+                    // Purposefully leaving this method not implemented.
+                    throw new RuntimeException("Not implemented");
+                }
+
+                public StatsEvent[] newArray(int size) {
+                    // Purposefully leaving this method not implemented.
+                    throw new RuntimeException("Not implemented");
+                }
+            };
+
+    /**
+     * Boilerplate for Parcel.
+     */
+    public void writeToParcel(Parcel out, int flags) {
+        out.writeInt(mAtomId);
+        out.writeInt(getNumBytes());
+        out.writeByteArray(getBytes());
+    }
+
+    /**
+     * Boilerplate for Parcel.
+     */
+    public int describeContents() {
+        return 0;
+    }
+
+
+    /**
      * Builder for constructing a StatsEvent object.
      *
      * <p>This class defines and encapsulates the socket encoding for the buffer.
@@ -114,41 +325,8 @@
      *         .addBooleanAnnotation(annotation1Id, true)
      *         .build();
      * </pre>
-     * @hide
      **/
     public static final class Builder {
-        // Type Ids.
-        private static final byte TYPE_INT = 0x00;
-        private static final byte TYPE_LONG = 0x01;
-        private static final byte TYPE_STRING = 0x02;
-        private static final byte TYPE_LIST = 0x03;
-        private static final byte TYPE_FLOAT = 0x04;
-        private static final byte TYPE_BOOLEAN = 0x05;
-        private static final byte TYPE_BYTE_ARRAY = 0x06;
-        private static final byte TYPE_OBJECT = 0x07;
-        private static final byte TYPE_KEY_VALUE_PAIRS = 0x08;
-        private static final byte TYPE_ATTRIBUTION_CHAIN = 0x09;
-        private static final byte TYPE_ERRORS = 0x0F;
-
-        // Error flags.
-        private static final int ERROR_NO_TIMESTAMP = 0x1;
-        private static final int ERROR_NO_ATOM_ID = 0x2;
-        private static final int ERROR_OVERFLOW = 0x4;
-        private static final int ERROR_ATTRIBUTION_CHAIN_TOO_LONG = 0x8;
-        private static final int ERROR_TOO_MANY_KEY_VALUE_PAIRS = 0x10;
-        private static final int ERROR_ANNOTATION_DOES_NOT_FOLLOW_FIELD = 0x20;
-        private static final int ERROR_INVALID_ANNOTATION_ID = 0x40;
-        private static final int ERROR_ANNOTATION_ID_TOO_LARGE = 0x80;
-        private static final int ERROR_TOO_MANY_ANNOTATIONS = 0x100;
-        private static final int ERROR_TOO_MANY_FIELDS = 0x200;
-        private static final int ERROR_ATTRIBUTION_UIDS_TAGS_SIZES_NOT_EQUAL = 0x400;
-
-        // Size limits.
-        private static final int MAX_ANNOTATION_COUNT = 15;
-        private static final int MAX_ATTRIBUTION_NODES = 127;
-        private static final int MAX_NUM_ELEMENTS = 127;
-        private static final int MAX_KEY_VALUE_PAIRS = 127;
-
         // Fixed positions.
         private static final int POS_NUM_ELEMENTS = 1;
         private static final int POS_TIMESTAMP_NS = POS_NUM_ELEMENTS + Byte.BYTES;
@@ -290,7 +468,7 @@
          * @param tags array of tags in the attribution nodes.
          **/
         @NonNull
-        public Builder writeAttributionNode(
+        public Builder writeAttributionChain(
                 @NonNull final int[] uids, @NonNull final String[] tags) {
             final byte numUids = (byte) uids.length;
             final byte numTags = (byte) tags.length;
@@ -633,39 +811,4 @@
             return 0;
         }
     }
-
-    /**
-     * Boilerplate for Parcel.
-     *
-     * @hide
-     */
-    public static final @NonNull Parcelable.Creator<StatsEvent> CREATOR =
-            new Parcelable.Creator<StatsEvent>() {
-                public StatsEvent createFromParcel(Parcel in) {
-                    // Purposefully leaving this method not implemented.
-                    throw new RuntimeException("Not implemented");
-                }
-
-                public StatsEvent[] newArray(int size) {
-                    // Purposefully leaving this method not implemented.
-                    throw new RuntimeException("Not implemented");
-                }
-            };
-
-    /**
-     * @hide
-     */
-    public void writeToParcel(Parcel out, int flags) {
-        out.writeInt(mAtomId);
-        out.writeInt(getNumBytes());
-        out.writeByteArray(getBytes());
-    }
-
-    /**
-     * Boilerplate for Parcel.
-     */
-    public int describeContents() {
-        return 0;
-    }
-
 }
diff --git a/core/java/android/util/TimingLogger.java b/core/java/android/util/TimingLogger.java
index be442da..5a4a512 100644
--- a/core/java/android/util/TimingLogger.java
+++ b/core/java/android/util/TimingLogger.java
@@ -44,7 +44,14 @@
  *     D/TAG     ( 3459): methodA:      6 ms, work C
  *     D/TAG     ( 3459): methodA: end, 16 ms
  * </pre>
+ *
+ * @deprecated Use {@link android.os.Trace}, or
+ *   <a href="https://developer.android.com/studio/profile/benchmark">Android Studio</a>. In
+ *   general, milliseconds is the wrong granularity for method-level tracing. Rounding errors
+ *   can overemphasize cheap operations, or underemphasize repeated operations. This timing
+ *   system also does not take CPU scheduling or frequency into account.
  */
+@Deprecated
 public class TimingLogger {
 
     /**
diff --git a/core/java/android/view/IDisplayWindowListener.aidl b/core/java/android/view/IDisplayWindowListener.aidl
index 725cd6f..973a208 100644
--- a/core/java/android/view/IDisplayWindowListener.aidl
+++ b/core/java/android/view/IDisplayWindowListener.aidl
@@ -16,12 +16,16 @@
 
 package android.view;
 
+import android.content.res.Configuration;
+
 /**
  * Interface to listen for changes to display window-containers.
  *
- * This differs from DisplayManager's DisplayListener:
+ * This differs from DisplayManager's DisplayListener in a couple ways:
  *  - onDisplayAdded is always called after the display is actually added to the WM hierarchy.
  *    This corresponds to the DisplayContent and not the raw Dislay from DisplayManager.
+ *  - onDisplayConfigurationChanged is called for all configuration changes, not just changes
+ *    to displayinfo (eg. windowing-mode).
  *
  * @hide
  */
@@ -33,6 +37,11 @@
     void onDisplayAdded(int displayId);
 
     /**
+     * Called when a display's window-container configuration has changed.
+     */
+    void onDisplayConfigurationChanged(int displayId, in Configuration newConfig);
+
+    /**
      * Called when a display is removed from the hierarchy.
      */
     void onDisplayRemoved(int displayId);
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index db76b71..9d4f3878 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -8732,7 +8732,7 @@
             structure.setContextClickable(true);
         }
         structure.setClassName(getAccessibilityClassName().toString());
-        structure.setContentDescription(mContentDescription);
+        structure.setContentDescription(getContentDescription());
     }
 
     /**
@@ -9939,8 +9939,8 @@
         info.setImportantForAccessibility(isImportantForAccessibility());
         info.setPackageName(mContext.getPackageName());
         info.setClassName(getAccessibilityClassName());
-        info.setStateDescription(mStateDescription);
-        info.setContentDescription(mContentDescription);
+        info.setStateDescription(getStateDescription());
+        info.setContentDescription(getContentDescription());
 
         info.setEnabled(isEnabled());
         info.setClickable(isClickable());
@@ -10323,7 +10323,7 @@
      * @see #setStateDescription(CharSequence)
      */
     @ViewDebug.ExportedProperty(category = "accessibility")
-    public @Nullable CharSequence getStateDescription() {
+    public final @Nullable CharSequence getStateDescription() {
         return mStateDescription;
     }
 
@@ -13717,7 +13717,7 @@
      */
     @UnsupportedAppUsage
     public CharSequence getIterableTextForAccessibility() {
-        return mContentDescription;
+        return getContentDescription();
     }
 
     /**
@@ -29498,10 +29498,9 @@
         stream.addProperty("text:textAlignment", getTextAlignment());
 
         // accessibility
+        CharSequence contentDescription = getContentDescription();
         stream.addProperty("accessibility:contentDescription",
-                mContentDescription == null ? "" : mContentDescription.toString());
-        stream.addProperty("accessibility:stateDescription",
-                mStateDescription == null ? "" : mStateDescription.toString());
+                contentDescription == null ? "" : contentDescription.toString());
         stream.addProperty("accessibility:labelFor", getLabelFor());
         stream.addProperty("accessibility:importantForAccessibility", getImportantForAccessibility());
     }
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/view/inline/InlineContentView.java b/core/java/android/view/inline/InlineContentView.java
new file mode 100644
index 0000000..4bc2176
--- /dev/null
+++ b/core/java/android/view/inline/InlineContentView.java
@@ -0,0 +1,57 @@
+/*
+ * 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.view.inline;
+
+import android.annotation.NonNull;
+import android.content.Context;
+import android.graphics.PixelFormat;
+import android.view.SurfaceControl;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+
+/**
+ * This class represents a view that can hold an opaque content that may be from a different source.
+ *
+ * @hide
+ */
+public class InlineContentView extends SurfaceView {
+    public InlineContentView(@NonNull Context context,
+            @NonNull SurfaceControl surfaceControl) {
+        super(context);
+        setZOrderOnTop(true);
+        getHolder().addCallback(new SurfaceHolder.Callback() {
+            @Override
+            public void surfaceCreated(SurfaceHolder holder) {
+                holder.setFormat(PixelFormat.TRANSPARENT);
+                new SurfaceControl.Transaction()
+                        .reparent(surfaceControl, getSurfaceControl())
+                        .setVisibility(surfaceControl, /* visible */ true)
+                        .apply();
+            }
+
+            @Override
+            public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
+                // TODO(b/137800469): implement this.
+            }
+
+            @Override
+            public void surfaceDestroyed(SurfaceHolder holder) {
+                // TODO(b/137800469): implement this.
+            }
+        });
+    }
+}
diff --git a/core/java/android/view/inline/InlinePresentationSpec.aidl b/core/java/android/view/inline/InlinePresentationSpec.aidl
new file mode 100644
index 0000000..efa46c8
--- /dev/null
+++ b/core/java/android/view/inline/InlinePresentationSpec.aidl
@@ -0,0 +1,19 @@
+/*
+ * 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.view.inline;
+
+parcelable InlinePresentationSpec;
diff --git a/core/java/android/view/inline/InlinePresentationSpec.java b/core/java/android/view/inline/InlinePresentationSpec.java
new file mode 100644
index 0000000..1eddef5
--- /dev/null
+++ b/core/java/android/view/inline/InlinePresentationSpec.java
@@ -0,0 +1,244 @@
+/*
+ * 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.view.inline;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.Parcelable;
+import android.util.Size;
+
+import com.android.internal.util.DataClass;
+
+/**
+ * This class represents the presentation specification by which an inline suggestion
+ * should abide when constructing its UI. Since suggestions are inlined in a
+ * host application while provided by another source, they need to be consistent
+ * with the host's look at feel to allow building smooth and integrated UIs.
+ */
+@DataClass(genEqualsHashCode = true, genToString = true, genBuilder = true)
+public final class InlinePresentationSpec implements Parcelable {
+    /** The minimal size of the suggestion. */
+    @NonNull
+    private final Size mMinSize;
+    /** The maximal size of the suggestion. */
+    @NonNull
+    private final Size mMaxSize;
+
+    // TODO(b/137800469): add more attributes, such as text appearance info.
+
+    /** @hide */
+    @DataClass.Suppress({"setMaxSize", "setMinSize"})
+    abstract static class BaseBuilder {
+    }
+
+
+
+    // Code below generated by codegen v1.0.14.
+    //
+    // DO NOT MODIFY!
+    // CHECKSTYLE:OFF Generated code
+    //
+    // To regenerate run:
+    // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/view/inline/InlinePresentationSpec.java
+    //
+    // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
+    //   Settings > Editor > Code Style > Formatter Control
+    //@formatter:off
+
+
+    @DataClass.Generated.Member
+    /* package-private */ InlinePresentationSpec(
+            @NonNull Size minSize,
+            @NonNull Size maxSize) {
+        this.mMinSize = minSize;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mMinSize);
+        this.mMaxSize = maxSize;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mMaxSize);
+
+        // onConstructed(); // You can define this method to get a callback
+    }
+
+    /**
+     * The minimal size of the suggestion.
+     */
+    @DataClass.Generated.Member
+    public @NonNull Size getMinSize() {
+        return mMinSize;
+    }
+
+    /**
+     * The maximal size of the suggestion.
+     */
+    @DataClass.Generated.Member
+    public @NonNull Size getMaxSize() {
+        return mMaxSize;
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public String toString() {
+        // You can override field toString logic by defining methods like:
+        // String fieldNameToString() { ... }
+
+        return "InlinePresentationSpec { " +
+                "minSize = " + mMinSize + ", " +
+                "maxSize = " + mMaxSize +
+        " }";
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public boolean equals(@Nullable Object o) {
+        // You can override field equality logic by defining either of the methods like:
+        // boolean fieldNameEquals(InlinePresentationSpec other) { ... }
+        // boolean fieldNameEquals(FieldType otherValue) { ... }
+
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        @SuppressWarnings("unchecked")
+        InlinePresentationSpec that = (InlinePresentationSpec) o;
+        //noinspection PointlessBooleanExpression
+        return true
+                && java.util.Objects.equals(mMinSize, that.mMinSize)
+                && java.util.Objects.equals(mMaxSize, that.mMaxSize);
+    }
+
+    @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 + java.util.Objects.hashCode(mMinSize);
+        _hash = 31 * _hash + java.util.Objects.hashCode(mMaxSize);
+        return _hash;
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public void writeToParcel(@NonNull android.os.Parcel dest, int flags) {
+        // You can override field parcelling by defining methods like:
+        // void parcelFieldName(Parcel dest, int flags) { ... }
+
+        dest.writeSize(mMinSize);
+        dest.writeSize(mMaxSize);
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public int describeContents() { return 0; }
+
+    /** @hide */
+    @SuppressWarnings({"unchecked", "RedundantCast"})
+    @DataClass.Generated.Member
+    /* package-private */ InlinePresentationSpec(@NonNull android.os.Parcel in) {
+        // You can override field unparcelling by defining methods like:
+        // static FieldType unparcelFieldName(Parcel in) { ... }
+
+        Size minSize = (Size) in.readSize();
+        Size maxSize = (Size) in.readSize();
+
+        this.mMinSize = minSize;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mMinSize);
+        this.mMaxSize = maxSize;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mMaxSize);
+
+        // onConstructed(); // You can define this method to get a callback
+    }
+
+    @DataClass.Generated.Member
+    public static final @NonNull Parcelable.Creator<InlinePresentationSpec> CREATOR
+            = new Parcelable.Creator<InlinePresentationSpec>() {
+        @Override
+        public InlinePresentationSpec[] newArray(int size) {
+            return new InlinePresentationSpec[size];
+        }
+
+        @Override
+        public InlinePresentationSpec createFromParcel(@NonNull android.os.Parcel in) {
+            return new InlinePresentationSpec(in);
+        }
+    };
+
+    /**
+     * A builder for {@link InlinePresentationSpec}
+     */
+    @SuppressWarnings("WeakerAccess")
+    @DataClass.Generated.Member
+    public static final class Builder extends BaseBuilder {
+
+        private @NonNull Size mMinSize;
+        private @NonNull Size mMaxSize;
+
+        private long mBuilderFieldsSet = 0L;
+
+        /**
+         * Creates a new Builder.
+         *
+         * @param minSize
+         *   The minimal size of the suggestion.
+         * @param maxSize
+         *   The maximal size of the suggestion.
+         */
+        public Builder(
+                @NonNull Size minSize,
+                @NonNull Size maxSize) {
+            mMinSize = minSize;
+            com.android.internal.util.AnnotationValidations.validate(
+                    NonNull.class, null, mMinSize);
+            mMaxSize = maxSize;
+            com.android.internal.util.AnnotationValidations.validate(
+                    NonNull.class, null, mMaxSize);
+        }
+
+        /** Builds the instance. This builder should not be touched after calling this! */
+        public @NonNull InlinePresentationSpec build() {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x4; // Mark builder used
+
+            InlinePresentationSpec o = new InlinePresentationSpec(
+                    mMinSize,
+                    mMaxSize);
+            return o;
+        }
+
+        private void checkNotUsed() {
+            if ((mBuilderFieldsSet & 0x4) != 0) {
+                throw new IllegalStateException(
+                        "This Builder should not be reused. Use a new Builder instance instead");
+            }
+        }
+    }
+
+    @DataClass.Generated(
+            time = 1574406062532L,
+            codegenVersion = "1.0.14",
+            sourceFile = "frameworks/base/core/java/android/view/inline/InlinePresentationSpec.java",
+            inputSignatures = "private final @android.annotation.NonNull android.util.Size mMinSize\nprivate final @android.annotation.NonNull android.util.Size mMaxSize\nclass InlinePresentationSpec extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genToString=true, genBuilder=true)\nclass BaseBuilder extends java.lang.Object implements []")
+    @Deprecated
+    private void __metadata() {}
+
+
+    //@formatter:on
+    // End of generated code
+
+}
diff --git a/core/java/android/view/inputmethod/InlineSuggestion.aidl b/core/java/android/view/inputmethod/InlineSuggestion.aidl
new file mode 100644
index 0000000..208d964
--- /dev/null
+++ b/core/java/android/view/inputmethod/InlineSuggestion.aidl
@@ -0,0 +1,19 @@
+/*
+ * 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.view.inputmethod;
+
+parcelable InlineSuggestion;
diff --git a/core/java/android/view/inputmethod/InlineSuggestion.java b/core/java/android/view/inputmethod/InlineSuggestion.java
new file mode 100644
index 0000000..25e34d3
--- /dev/null
+++ b/core/java/android/view/inputmethod/InlineSuggestion.java
@@ -0,0 +1,285 @@
+/*
+ * 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.view.inputmethod;
+
+import android.annotation.CallbackExecutor;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.os.AsyncTask;
+import android.os.Parcelable;
+import android.os.RemoteException;
+import android.util.Size;
+import android.util.Slog;
+import android.view.SurfaceControl;
+import android.view.View;
+import android.view.inline.InlineContentView;
+import android.view.inline.InlinePresentationSpec;
+
+import com.android.internal.util.DataClass;
+import com.android.internal.view.inline.IInlineContentCallback;
+import com.android.internal.view.inline.IInlineContentProvider;
+
+import java.lang.ref.WeakReference;
+import java.util.concurrent.Executor;
+import java.util.function.Consumer;
+
+/**
+ * This class represents an inline suggestion which is made by one app
+ * and can be embedded into the UI of another. Suggestions may contain
+ * sensitive information not known to the host app which needs to be
+ * protected from spoofing. To address that the suggestion view inflated
+ * on demand for embedding is created in such a way that the hosting app
+ * cannot introspect its content and cannot interact with it.
+ */
+@DataClass(
+        genEqualsHashCode = true,
+        genToString = true,
+        genHiddenConstDefs = true,
+        genHiddenConstructor = true)
+@DataClass.Suppress({"getContentProvider"})
+public final class InlineSuggestion implements Parcelable {
+
+    private static final String TAG = "InlineSuggestion";
+
+    private final @NonNull InlineSuggestionInfo mInfo;
+
+    private final @Nullable IInlineContentProvider mContentProvider;
+
+    /**
+     * Inflates a view with the content of this suggestion at a specific size.
+     * The size must be between the {@link InlinePresentationSpec#getMinSize() min size}
+     * and the {@link InlinePresentationSpec#getMaxSize() max size} of the presentation
+     * spec returned by {@link InlineSuggestionInfo#getPresentationSpec()}. If an invalid
+     * argument is passed an exception is thrown.
+     *
+     * @param context Context in which to inflate the view.
+     * @param size The size at which to inflate the suggestion.
+     * @param callback Callback for receiving the inflated view.
+     */
+    public void inflate(@NonNull Context context, @NonNull Size size,
+            @NonNull @CallbackExecutor Executor callbackExecutor,
+            @NonNull Consumer<View> callback) {
+        final Size minSize = mInfo.getPresentationSpec().getMinSize();
+        final Size maxSize = mInfo.getPresentationSpec().getMaxSize();
+        if (size.getHeight() < minSize.getHeight() || size.getHeight() > maxSize.getHeight()
+                || size.getWidth() < minSize.getWidth() || size.getWidth() > maxSize.getWidth()) {
+            throw new IllegalArgumentException("size not between min:"
+                    + minSize + " and max:" + maxSize);
+        }
+        AsyncTask.THREAD_POOL_EXECUTOR.execute(() -> {
+            if (mContentProvider == null) {
+                callback.accept(/* view */ null);
+                return;
+            }
+            // TODO(b/137800469): keep a strong reference to the contentCallback so it doesn't
+            //  get GC'd. Also add a isInflated() method and make sure the view can only be
+            //  inflated once.
+            try {
+                InlineContentCallbackImpl contentCallback = new InlineContentCallbackImpl(context,
+                        callbackExecutor, callback);
+                mContentProvider.provideContent(size.getWidth(), size.getHeight(),
+                        new InlineContentCallbackWrapper(contentCallback));
+            } catch (RemoteException e) {
+                Slog.w(TAG, "Error creating suggestion content surface: " + e);
+                callback.accept(/* view */ null);
+            }
+        });
+    }
+
+    private static final class InlineContentCallbackWrapper extends IInlineContentCallback.Stub {
+
+        private final WeakReference<InlineContentCallbackImpl> mCallbackImpl;
+
+        InlineContentCallbackWrapper(InlineContentCallbackImpl callbackImpl) {
+            mCallbackImpl = new WeakReference<>(callbackImpl);
+        }
+
+        @Override
+        public void onContent(SurfaceControl content) {
+            final InlineContentCallbackImpl callbackImpl = mCallbackImpl.get();
+            if (callbackImpl != null) {
+                callbackImpl.onContent(content);
+            }
+        }
+    }
+
+    private static final class InlineContentCallbackImpl {
+
+        private final @NonNull Context mContext;
+        private final @NonNull Executor mCallbackExecutor;
+        private final @NonNull Consumer<View> mCallback;
+
+        InlineContentCallbackImpl(@NonNull Context context,
+                @NonNull @CallbackExecutor Executor callbackExecutor,
+                @NonNull Consumer<View> callback) {
+            mContext = context;
+            mCallbackExecutor = callbackExecutor;
+            mCallback = callback;
+        }
+
+        public void onContent(SurfaceControl content) {
+            if (content == null) {
+                mCallbackExecutor.execute(() -> mCallback.accept(/* view */null));
+            } else {
+                mCallbackExecutor.execute(
+                        () -> mCallback.accept(new InlineContentView(mContext, content)));
+            }
+        }
+    }
+
+
+
+    // Code below generated by codegen v1.0.14.
+    //
+    // DO NOT MODIFY!
+    // CHECKSTYLE:OFF Generated code
+    //
+    // To regenerate run:
+    // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/view/inputmethod/InlineSuggestion.java
+    //
+    // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
+    //   Settings > Editor > Code Style > Formatter Control
+    //@formatter:off
+
+
+    /**
+     * Creates a new InlineSuggestion.
+     *
+     * @hide
+     */
+    @DataClass.Generated.Member
+    public InlineSuggestion(
+            @NonNull InlineSuggestionInfo info,
+            @Nullable IInlineContentProvider contentProvider) {
+        this.mInfo = info;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mInfo);
+        this.mContentProvider = contentProvider;
+
+        // onConstructed(); // You can define this method to get a callback
+    }
+
+    @DataClass.Generated.Member
+    public @NonNull InlineSuggestionInfo getInfo() {
+        return mInfo;
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public String toString() {
+        // You can override field toString logic by defining methods like:
+        // String fieldNameToString() { ... }
+
+        return "InlineSuggestion { " +
+                "info = " + mInfo + ", " +
+                "contentProvider = " + mContentProvider +
+        " }";
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public boolean equals(@Nullable Object o) {
+        // You can override field equality logic by defining either of the methods like:
+        // boolean fieldNameEquals(InlineSuggestion other) { ... }
+        // boolean fieldNameEquals(FieldType otherValue) { ... }
+
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        @SuppressWarnings("unchecked")
+        InlineSuggestion that = (InlineSuggestion) o;
+        //noinspection PointlessBooleanExpression
+        return true
+                && java.util.Objects.equals(mInfo, that.mInfo)
+                && java.util.Objects.equals(mContentProvider, that.mContentProvider);
+    }
+
+    @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 + java.util.Objects.hashCode(mInfo);
+        _hash = 31 * _hash + java.util.Objects.hashCode(mContentProvider);
+        return _hash;
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public void writeToParcel(@NonNull android.os.Parcel dest, int flags) {
+        // You can override field parcelling by defining methods like:
+        // void parcelFieldName(Parcel dest, int flags) { ... }
+
+        byte flg = 0;
+        if (mContentProvider != null) flg |= 0x2;
+        dest.writeByte(flg);
+        dest.writeTypedObject(mInfo, flags);
+        if (mContentProvider != null) dest.writeStrongInterface(mContentProvider);
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public int describeContents() { return 0; }
+
+    /** @hide */
+    @SuppressWarnings({"unchecked", "RedundantCast"})
+    @DataClass.Generated.Member
+    /* package-private */ InlineSuggestion(@NonNull android.os.Parcel in) {
+        // You can override field unparcelling by defining methods like:
+        // static FieldType unparcelFieldName(Parcel in) { ... }
+
+        byte flg = in.readByte();
+        InlineSuggestionInfo info = (InlineSuggestionInfo) in.readTypedObject(InlineSuggestionInfo.CREATOR);
+        IInlineContentProvider contentProvider = (flg & 0x2) == 0 ? null : IInlineContentProvider.Stub.asInterface(in.readStrongBinder());
+
+        this.mInfo = info;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mInfo);
+        this.mContentProvider = contentProvider;
+
+        // onConstructed(); // You can define this method to get a callback
+    }
+
+    @DataClass.Generated.Member
+    public static final @NonNull Parcelable.Creator<InlineSuggestion> CREATOR
+            = new Parcelable.Creator<InlineSuggestion>() {
+        @Override
+        public InlineSuggestion[] newArray(int size) {
+            return new InlineSuggestion[size];
+        }
+
+        @Override
+        public InlineSuggestion createFromParcel(@NonNull android.os.Parcel in) {
+            return new InlineSuggestion(in);
+        }
+    };
+
+    @DataClass.Generated(
+            time = 1574446220398L,
+            codegenVersion = "1.0.14",
+            sourceFile = "frameworks/base/core/java/android/view/inputmethod/InlineSuggestion.java",
+            inputSignatures = "private static final  java.lang.String TAG\nprivate final @android.annotation.NonNull android.view.inputmethod.InlineSuggestionInfo mInfo\nprivate final @android.annotation.Nullable com.android.internal.view.inline.IInlineContentProvider mContentProvider\npublic  void inflate(android.content.Context,android.util.Size,java.util.concurrent.Executor,java.util.function.Consumer<android.view.View>)\nclass InlineSuggestion extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genToString=true, genHiddenConstDefs=true, genHiddenConstructor=true)")
+    @Deprecated
+    private void __metadata() {}
+
+
+    //@formatter:on
+    // End of generated code
+
+}
diff --git a/core/java/android/view/inputmethod/InlineSuggestionInfo.aidl b/core/java/android/view/inputmethod/InlineSuggestionInfo.aidl
new file mode 100644
index 0000000..168bd0b
--- /dev/null
+++ b/core/java/android/view/inputmethod/InlineSuggestionInfo.aidl
@@ -0,0 +1,19 @@
+/*
+ * 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.view.inputmethod;
+
+parcelable InlineSuggestionInfo;
diff --git a/core/java/android/view/inputmethod/InlineSuggestionInfo.java b/core/java/android/view/inputmethod/InlineSuggestionInfo.java
new file mode 100644
index 0000000..07fce31
--- /dev/null
+++ b/core/java/android/view/inputmethod/InlineSuggestionInfo.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 android.view.inputmethod;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.Parcelable;
+import android.view.inline.InlinePresentationSpec;
+
+import com.android.internal.util.DataClass;
+
+/**
+ * This class represents the description of an inline suggestion. It contains information to help
+ * the IME to decide where and when to show the suggestions. See {@link InlineSuggestion} for more
+ * information.
+ */
+@DataClass(
+        genEqualsHashCode = true,
+        genToString = true,
+        genHiddenConstDefs = true,
+        genHiddenConstructor = true)
+public final class InlineSuggestionInfo implements Parcelable {
+
+    /**
+     * Suggestion source: the suggestion is made by the user selected autofill service.
+     */
+    public static final @Source String SOURCE_AUTOFILL = "android:autofill";
+    /**
+     * Suggestion source: the suggestion is made by the platform.
+     */
+    public static final @Source String SOURCE_PLATFORM = "android:platform";
+
+    /** The presentation spec to which the inflated suggestion view abides. */
+    private final @NonNull InlinePresentationSpec mPresentationSpec;
+
+    /** The source from which the suggestion is provided. */
+    private final @NonNull @Source String mSource;
+
+    /** Hints for the type of data being suggested. */
+    private final @Nullable String[] mAutofillHints;
+
+
+
+
+    // Code below generated by codegen v1.0.14.
+    //
+    // DO NOT MODIFY!
+    // CHECKSTYLE:OFF Generated code
+    //
+    // To regenerate run:
+    // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/view/inputmethod/InlineSuggestionInfo.java
+    //
+    // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
+    //   Settings > Editor > Code Style > Formatter Control
+    //@formatter:off
+
+
+    /** @hide */
+    @android.annotation.StringDef(prefix = "SOURCE_", value = {
+        SOURCE_AUTOFILL,
+        SOURCE_PLATFORM
+    })
+    @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE)
+    @DataClass.Generated.Member
+    public @interface Source {}
+
+    /**
+     * Creates a new InlineSuggestionInfo.
+     *
+     * @param presentationSpec
+     *   The presentation spec to which the inflated suggestion view abides.
+     * @param source
+     *   The source from which the suggestion is provided.
+     * @param autofillHints
+     *   Hints for the type of data being suggested.
+     * @hide
+     */
+    @DataClass.Generated.Member
+    public InlineSuggestionInfo(
+            @NonNull InlinePresentationSpec presentationSpec,
+            @NonNull @Source String source,
+            @Nullable String[] autofillHints) {
+        this.mPresentationSpec = presentationSpec;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mPresentationSpec);
+        this.mSource = source;
+
+        if (!(java.util.Objects.equals(mSource, SOURCE_AUTOFILL))
+                && !(java.util.Objects.equals(mSource, SOURCE_PLATFORM))) {
+            throw new java.lang.IllegalArgumentException(
+                    "source was " + mSource + " but must be one of: "
+                            + "SOURCE_AUTOFILL(" + SOURCE_AUTOFILL + "), "
+                            + "SOURCE_PLATFORM(" + SOURCE_PLATFORM + ")");
+        }
+
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mSource);
+        this.mAutofillHints = autofillHints;
+
+        // onConstructed(); // You can define this method to get a callback
+    }
+
+    /**
+     * The presentation spec to which the inflated suggestion view abides.
+     */
+    @DataClass.Generated.Member
+    public @NonNull InlinePresentationSpec getPresentationSpec() {
+        return mPresentationSpec;
+    }
+
+    /**
+     * The source from which the suggestion is provided.
+     */
+    @DataClass.Generated.Member
+    public @NonNull @Source String getSource() {
+        return mSource;
+    }
+
+    /**
+     * Hints for the type of data being suggested.
+     */
+    @DataClass.Generated.Member
+    public @Nullable String[] getAutofillHints() {
+        return mAutofillHints;
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public String toString() {
+        // You can override field toString logic by defining methods like:
+        // String fieldNameToString() { ... }
+
+        return "InlineSuggestionInfo { " +
+                "presentationSpec = " + mPresentationSpec + ", " +
+                "source = " + mSource + ", " +
+                "autofillHints = " + java.util.Arrays.toString(mAutofillHints) +
+        " }";
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public boolean equals(@Nullable Object o) {
+        // You can override field equality logic by defining either of the methods like:
+        // boolean fieldNameEquals(InlineSuggestionInfo other) { ... }
+        // boolean fieldNameEquals(FieldType otherValue) { ... }
+
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        @SuppressWarnings("unchecked")
+        InlineSuggestionInfo that = (InlineSuggestionInfo) o;
+        //noinspection PointlessBooleanExpression
+        return true
+                && java.util.Objects.equals(mPresentationSpec, that.mPresentationSpec)
+                && java.util.Objects.equals(mSource, that.mSource)
+                && java.util.Arrays.equals(mAutofillHints, that.mAutofillHints);
+    }
+
+    @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 + java.util.Objects.hashCode(mPresentationSpec);
+        _hash = 31 * _hash + java.util.Objects.hashCode(mSource);
+        _hash = 31 * _hash + java.util.Arrays.hashCode(mAutofillHints);
+        return _hash;
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public void writeToParcel(@NonNull android.os.Parcel dest, int flags) {
+        // You can override field parcelling by defining methods like:
+        // void parcelFieldName(Parcel dest, int flags) { ... }
+
+        byte flg = 0;
+        if (mAutofillHints != null) flg |= 0x4;
+        dest.writeByte(flg);
+        dest.writeTypedObject(mPresentationSpec, flags);
+        dest.writeString(mSource);
+        if (mAutofillHints != null) dest.writeStringArray(mAutofillHints);
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public int describeContents() { return 0; }
+
+    /** @hide */
+    @SuppressWarnings({"unchecked", "RedundantCast"})
+    @DataClass.Generated.Member
+    /* package-private */ InlineSuggestionInfo(@NonNull android.os.Parcel in) {
+        // You can override field unparcelling by defining methods like:
+        // static FieldType unparcelFieldName(Parcel in) { ... }
+
+        byte flg = in.readByte();
+        InlinePresentationSpec presentationSpec = (InlinePresentationSpec) in.readTypedObject(InlinePresentationSpec.CREATOR);
+        String source = in.readString();
+        String[] autofillHints = (flg & 0x4) == 0 ? null : in.createStringArray();
+
+        this.mPresentationSpec = presentationSpec;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mPresentationSpec);
+        this.mSource = source;
+
+        if (!(java.util.Objects.equals(mSource, SOURCE_AUTOFILL))
+                && !(java.util.Objects.equals(mSource, SOURCE_PLATFORM))) {
+            throw new java.lang.IllegalArgumentException(
+                    "source was " + mSource + " but must be one of: "
+                            + "SOURCE_AUTOFILL(" + SOURCE_AUTOFILL + "), "
+                            + "SOURCE_PLATFORM(" + SOURCE_PLATFORM + ")");
+        }
+
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mSource);
+        this.mAutofillHints = autofillHints;
+
+        // onConstructed(); // You can define this method to get a callback
+    }
+
+    @DataClass.Generated.Member
+    public static final @NonNull Parcelable.Creator<InlineSuggestionInfo> CREATOR
+            = new Parcelable.Creator<InlineSuggestionInfo>() {
+        @Override
+        public InlineSuggestionInfo[] newArray(int size) {
+            return new InlineSuggestionInfo[size];
+        }
+
+        @Override
+        public InlineSuggestionInfo createFromParcel(@NonNull android.os.Parcel in) {
+            return new InlineSuggestionInfo(in);
+        }
+    };
+
+    @DataClass.Generated(
+            time = 1574406074120L,
+            codegenVersion = "1.0.14",
+            sourceFile = "frameworks/base/core/java/android/view/inputmethod/InlineSuggestionInfo.java",
+            inputSignatures = "public static final @android.view.inputmethod.InlineSuggestionInfo.Source java.lang.String SOURCE_AUTOFILL\npublic static final @android.view.inputmethod.InlineSuggestionInfo.Source java.lang.String SOURCE_PLATFORM\nprivate final @android.annotation.NonNull android.view.inline.InlinePresentationSpec mPresentationSpec\nprivate final @android.annotation.NonNull @android.view.inputmethod.InlineSuggestionInfo.Source java.lang.String mSource\nprivate final @android.annotation.Nullable java.lang.String[] mAutofillHints\nclass InlineSuggestionInfo extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genToString=true, genHiddenConstDefs=true, genHiddenConstructor=true)")
+    @Deprecated
+    private void __metadata() {}
+
+
+    //@formatter:on
+    // End of generated code
+
+}
diff --git a/core/java/android/view/inputmethod/InlineSuggestionsRequest.aidl b/core/java/android/view/inputmethod/InlineSuggestionsRequest.aidl
new file mode 100644
index 0000000..5a8abd2
--- /dev/null
+++ b/core/java/android/view/inputmethod/InlineSuggestionsRequest.aidl
@@ -0,0 +1,19 @@
+/*
+ * 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.view.inputmethod;
+
+parcelable InlineSuggestionsRequest;
diff --git a/core/java/android/view/inputmethod/InlineSuggestionsRequest.java b/core/java/android/view/inputmethod/InlineSuggestionsRequest.java
new file mode 100644
index 0000000..dd609ee
--- /dev/null
+++ b/core/java/android/view/inputmethod/InlineSuggestionsRequest.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 android.view.inputmethod;
+
+import android.annotation.NonNull;
+import android.os.Parcelable;
+import android.view.inline.InlinePresentationSpec;
+
+import com.android.internal.util.DataClass;
+import com.android.internal.util.Preconditions;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * This class represents an inline suggestion request made by one app to get suggestions from the
+ * other source. See {@link InlineSuggestion} for more information.
+ */
+@DataClass(genEqualsHashCode = true, genToString = true, genBuilder = true)
+public final class InlineSuggestionsRequest implements Parcelable {
+
+    /** Constant used to indicate not putting a cap on the number of suggestions to return. */
+    public static final int SUGGESTION_COUNT_UNLIMITED = Integer.MAX_VALUE;
+
+    private final int mMaxSuggestionCount;
+    private final @NonNull List<InlinePresentationSpec> mPresentationSpecs;
+
+    private void onConstructed() {
+        Preconditions.checkState(mMaxSuggestionCount >= mPresentationSpecs.size());
+    }
+
+    private static int defaultMaxSuggestionCount() {
+        return SUGGESTION_COUNT_UNLIMITED;
+    }
+
+    /** @hide */
+    abstract static class BaseBuilder {
+        abstract Builder setPresentationSpecs(@NonNull List<InlinePresentationSpec> value);
+    }
+
+
+
+    // Code below generated by codegen v1.0.14.
+    //
+    // DO NOT MODIFY!
+    // CHECKSTYLE:OFF Generated code
+    //
+    // To regenerate run:
+    // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/view/inputmethod/InlineSuggestionsRequest.java
+    //
+    // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
+    //   Settings > Editor > Code Style > Formatter Control
+    //@formatter:off
+
+
+    @DataClass.Generated.Member
+    /* package-private */ InlineSuggestionsRequest(
+            int maxSuggestionCount,
+            @NonNull List<InlinePresentationSpec> presentationSpecs) {
+        this.mMaxSuggestionCount = maxSuggestionCount;
+        this.mPresentationSpecs = presentationSpecs;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mPresentationSpecs);
+
+        onConstructed();
+    }
+
+    @DataClass.Generated.Member
+    public int getMaxSuggestionCount() {
+        return mMaxSuggestionCount;
+    }
+
+    @DataClass.Generated.Member
+    public @NonNull List<InlinePresentationSpec> getPresentationSpecs() {
+        return mPresentationSpecs;
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public String toString() {
+        // You can override field toString logic by defining methods like:
+        // String fieldNameToString() { ... }
+
+        return "InlineSuggestionsRequest { " +
+                "maxSuggestionCount = " + mMaxSuggestionCount + ", " +
+                "presentationSpecs = " + mPresentationSpecs +
+        " }";
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public boolean equals(@android.annotation.Nullable Object o) {
+        // You can override field equality logic by defining either of the methods like:
+        // boolean fieldNameEquals(InlineSuggestionsRequest other) { ... }
+        // boolean fieldNameEquals(FieldType otherValue) { ... }
+
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        @SuppressWarnings("unchecked")
+        InlineSuggestionsRequest that = (InlineSuggestionsRequest) o;
+        //noinspection PointlessBooleanExpression
+        return true
+                && mMaxSuggestionCount == that.mMaxSuggestionCount
+                && java.util.Objects.equals(mPresentationSpecs, that.mPresentationSpecs);
+    }
+
+    @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 + mMaxSuggestionCount;
+        _hash = 31 * _hash + java.util.Objects.hashCode(mPresentationSpecs);
+        return _hash;
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public void writeToParcel(@NonNull android.os.Parcel dest, int flags) {
+        // You can override field parcelling by defining methods like:
+        // void parcelFieldName(Parcel dest, int flags) { ... }
+
+        dest.writeInt(mMaxSuggestionCount);
+        dest.writeParcelableList(mPresentationSpecs, flags);
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public int describeContents() { return 0; }
+
+    /** @hide */
+    @SuppressWarnings({"unchecked", "RedundantCast"})
+    @DataClass.Generated.Member
+    /* package-private */ InlineSuggestionsRequest(@NonNull android.os.Parcel in) {
+        // You can override field unparcelling by defining methods like:
+        // static FieldType unparcelFieldName(Parcel in) { ... }
+
+        int maxSuggestionCount = in.readInt();
+        List<InlinePresentationSpec> presentationSpecs = new ArrayList<>();
+        in.readParcelableList(presentationSpecs, InlinePresentationSpec.class.getClassLoader());
+
+        this.mMaxSuggestionCount = maxSuggestionCount;
+        this.mPresentationSpecs = presentationSpecs;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mPresentationSpecs);
+
+        onConstructed();
+    }
+
+    @DataClass.Generated.Member
+    public static final @NonNull Parcelable.Creator<InlineSuggestionsRequest> CREATOR
+            = new Parcelable.Creator<InlineSuggestionsRequest>() {
+        @Override
+        public InlineSuggestionsRequest[] newArray(int size) {
+            return new InlineSuggestionsRequest[size];
+        }
+
+        @Override
+        public InlineSuggestionsRequest createFromParcel(@NonNull android.os.Parcel in) {
+            return new InlineSuggestionsRequest(in);
+        }
+    };
+
+    /**
+     * A builder for {@link InlineSuggestionsRequest}
+     */
+    @SuppressWarnings("WeakerAccess")
+    @DataClass.Generated.Member
+    public static final class Builder extends BaseBuilder {
+
+        private int mMaxSuggestionCount;
+        private @NonNull List<InlinePresentationSpec> mPresentationSpecs;
+
+        private long mBuilderFieldsSet = 0L;
+
+        public Builder(
+                @NonNull List<InlinePresentationSpec> presentationSpecs) {
+            mPresentationSpecs = presentationSpecs;
+            com.android.internal.util.AnnotationValidations.validate(
+                    NonNull.class, null, mPresentationSpecs);
+        }
+
+        @DataClass.Generated.Member
+        public @NonNull Builder setMaxSuggestionCount(int value) {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x1;
+            mMaxSuggestionCount = value;
+            return this;
+        }
+
+        @DataClass.Generated.Member
+        @Override
+        @NonNull Builder setPresentationSpecs(@NonNull List<InlinePresentationSpec> value) {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x2;
+            mPresentationSpecs = value;
+            return this;
+        }
+
+        /** @see #setPresentationSpecs */
+        @DataClass.Generated.Member
+        public @NonNull Builder addPresentationSpecs(@NonNull InlinePresentationSpec value) {
+            // You can refine this method's name by providing item's singular name, e.g.:
+            // @DataClass.PluralOf("item")) mItems = ...
+
+            if (mPresentationSpecs == null) setPresentationSpecs(new ArrayList<>());
+            mPresentationSpecs.add(value);
+            return this;
+        }
+
+        /** Builds the instance. This builder should not be touched after calling this! */
+        public @NonNull InlineSuggestionsRequest build() {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x4; // Mark builder used
+
+            if ((mBuilderFieldsSet & 0x1) == 0) {
+                mMaxSuggestionCount = defaultMaxSuggestionCount();
+            }
+            InlineSuggestionsRequest o = new InlineSuggestionsRequest(
+                    mMaxSuggestionCount,
+                    mPresentationSpecs);
+            return o;
+        }
+
+        private void checkNotUsed() {
+            if ((mBuilderFieldsSet & 0x4) != 0) {
+                throw new IllegalStateException(
+                        "This Builder should not be reused. Use a new Builder instance instead");
+            }
+        }
+    }
+
+    @DataClass.Generated(
+            time = 1574406255024L,
+            codegenVersion = "1.0.14",
+            sourceFile = "frameworks/base/core/java/android/view/inputmethod/InlineSuggestionsRequest.java",
+            inputSignatures = "public static final  int SUGGESTION_COUNT_UNLIMITED\nprivate final  int mMaxSuggestionCount\nprivate final @android.annotation.NonNull java.util.List<android.view.inline.InlinePresentationSpec> mPresentationSpecs\nprivate  void onConstructed()\nprivate static  int defaultMaxSuggestionCount()\nclass InlineSuggestionsRequest extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genToString=true, genBuilder=true)\nabstract  android.view.inputmethod.InlineSuggestionsRequest.Builder setPresentationSpecs(java.util.List<android.view.inline.InlinePresentationSpec>)\nclass BaseBuilder extends java.lang.Object implements []")
+    @Deprecated
+    private void __metadata() {}
+
+
+    //@formatter:on
+    // End of generated code
+
+}
diff --git a/core/java/android/view/inputmethod/InlineSuggestionsResponse.aidl b/core/java/android/view/inputmethod/InlineSuggestionsResponse.aidl
new file mode 100644
index 0000000..9343fe9
--- /dev/null
+++ b/core/java/android/view/inputmethod/InlineSuggestionsResponse.aidl
@@ -0,0 +1,19 @@
+/*
+ * 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.view.inputmethod;
+
+parcelable InlineSuggestionsResponse;
diff --git a/core/java/android/view/inputmethod/InlineSuggestionsResponse.java b/core/java/android/view/inputmethod/InlineSuggestionsResponse.java
new file mode 100644
index 0000000..924a5ee
--- /dev/null
+++ b/core/java/android/view/inputmethod/InlineSuggestionsResponse.java
@@ -0,0 +1,165 @@
+/*
+ * 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.view.inputmethod;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.Parcelable;
+
+import com.android.internal.util.DataClass;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * This class represents an inline suggestion response. See {@link InlineSuggestion} for more
+ * information.
+ */
+@DataClass(genEqualsHashCode = true, genToString = true, genHiddenConstructor = true)
+public final class InlineSuggestionsResponse implements Parcelable {
+    private final @NonNull List<InlineSuggestion> mInlineSuggestions;
+
+
+
+    // Code below generated by codegen v1.0.14.
+    //
+    // DO NOT MODIFY!
+    // CHECKSTYLE:OFF Generated code
+    //
+    // To regenerate run:
+    // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/view/inputmethod/InlineSuggestionsResponse.java
+    //
+    // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
+    //   Settings > Editor > Code Style > Formatter Control
+    //@formatter:off
+
+
+    /**
+     * Creates a new InlineSuggestionsResponse.
+     *
+     * @hide
+     */
+    @DataClass.Generated.Member
+    public InlineSuggestionsResponse(
+            @NonNull List<InlineSuggestion> inlineSuggestions) {
+        this.mInlineSuggestions = inlineSuggestions;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mInlineSuggestions);
+
+        // onConstructed(); // You can define this method to get a callback
+    }
+
+    @DataClass.Generated.Member
+    public @NonNull List<InlineSuggestion> getInlineSuggestions() {
+        return mInlineSuggestions;
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public String toString() {
+        // You can override field toString logic by defining methods like:
+        // String fieldNameToString() { ... }
+
+        return "InlineSuggestionsResponse { " +
+                "inlineSuggestions = " + mInlineSuggestions +
+        " }";
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public boolean equals(@Nullable Object o) {
+        // You can override field equality logic by defining either of the methods like:
+        // boolean fieldNameEquals(InlineSuggestionsResponse other) { ... }
+        // boolean fieldNameEquals(FieldType otherValue) { ... }
+
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        @SuppressWarnings("unchecked")
+        InlineSuggestionsResponse that = (InlineSuggestionsResponse) o;
+        //noinspection PointlessBooleanExpression
+        return true
+                && java.util.Objects.equals(mInlineSuggestions, that.mInlineSuggestions);
+    }
+
+    @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 + java.util.Objects.hashCode(mInlineSuggestions);
+        return _hash;
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public void writeToParcel(@NonNull android.os.Parcel dest, int flags) {
+        // You can override field parcelling by defining methods like:
+        // void parcelFieldName(Parcel dest, int flags) { ... }
+
+        dest.writeParcelableList(mInlineSuggestions, flags);
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public int describeContents() { return 0; }
+
+    /** @hide */
+    @SuppressWarnings({"unchecked", "RedundantCast"})
+    @DataClass.Generated.Member
+    /* package-private */ InlineSuggestionsResponse(@NonNull android.os.Parcel in) {
+        // You can override field unparcelling by defining methods like:
+        // static FieldType unparcelFieldName(Parcel in) { ... }
+
+        List<InlineSuggestion> inlineSuggestions = new ArrayList<>();
+        in.readParcelableList(inlineSuggestions, InlineSuggestion.class.getClassLoader());
+
+        this.mInlineSuggestions = inlineSuggestions;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mInlineSuggestions);
+
+        // onConstructed(); // You can define this method to get a callback
+    }
+
+    @DataClass.Generated.Member
+    public static final @NonNull Parcelable.Creator<InlineSuggestionsResponse> CREATOR
+            = new Parcelable.Creator<InlineSuggestionsResponse>() {
+        @Override
+        public InlineSuggestionsResponse[] newArray(int size) {
+            return new InlineSuggestionsResponse[size];
+        }
+
+        @Override
+        public InlineSuggestionsResponse createFromParcel(@NonNull android.os.Parcel in) {
+            return new InlineSuggestionsResponse(in);
+        }
+    };
+
+    @DataClass.Generated(
+            time = 1574406147911L,
+            codegenVersion = "1.0.14",
+            sourceFile = "frameworks/base/core/java/android/view/inputmethod/InlineSuggestionsResponse.java",
+            inputSignatures = "private final @android.annotation.NonNull java.util.List<android.view.inputmethod.InlineSuggestion> mInlineSuggestions\nclass InlineSuggestionsResponse extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genToString=true, genHiddenConstructor=true)")
+    @Deprecated
+    private void __metadata() {}
+
+
+    //@formatter:on
+    // End of generated code
+
+}
diff --git a/core/java/android/widget/ArrayAdapter.java b/core/java/android/widget/ArrayAdapter.java
index 2bf1ba5..f7225d0 100644
--- a/core/java/android/widget/ArrayAdapter.java
+++ b/core/java/android/widget/ArrayAdapter.java
@@ -49,9 +49,6 @@
  * To customize what type of view is used for the data object,
  * override {@link #getView(int, View, ViewGroup)}
  * and inflate a view resource.
- * For a code example, see
- * the <a href="https://github.com/googlesamples/android-CustomChoiceList/#readme">
- * CustomChoiceList</a> sample.
  * </p>
  * <p>
  * For an example of using an array adapter with a ListView, see the
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/app/TEST_MAPPING b/core/java/com/android/internal/app/TEST_MAPPING
new file mode 100644
index 0000000..373a5d9
--- /dev/null
+++ b/core/java/com/android/internal/app/TEST_MAPPING
@@ -0,0 +1,20 @@
+{
+  "postsubmit": [
+    {
+      "name": "FrameworksCoreTests",
+      "options": [
+        {
+        "include-filter": "com.android.internal.app."
+        },
+
+        // Many tests failing - do not enable for continuous execution 
+        {
+        "exclude-filter": "com.android.internal.app.IntentForwarderActivityTest"
+        },
+        {
+        "exclude-filter": "com.android.internal.app.WindowDecorActionBarTest"
+        }
+      ]
+    }
+  ]
+}
\ No newline at end of file
diff --git a/core/java/com/android/internal/logging/UiEvent.java b/core/java/com/android/internal/logging/UiEvent.java
new file mode 100644
index 0000000..0407b07
--- /dev/null
+++ b/core/java/com/android/internal/logging/UiEvent.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.logging;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+@Retention(SOURCE)
+@Target(FIELD)
+public @interface UiEvent {
+    /** An explanation, suitable for Android analysts, of the UI event that this log represents. */
+    String doc();
+}
diff --git a/core/java/com/android/internal/logging/UiEventLogger.java b/core/java/com/android/internal/logging/UiEventLogger.java
new file mode 100644
index 0000000..cca97f6
--- /dev/null
+++ b/core/java/com/android/internal/logging/UiEventLogger.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.logging;
+
+/**
+ * Logging interface for UI events. Normal implementation is UiEventLoggerImpl.
+ * For testing, use fake implementation UiEventLoggerFake.
+ *
+ * See go/sysui-event-logs and UiEventReported atom in atoms.proto.
+ */
+public interface UiEventLogger {
+    /** Put your Event IDs in enums that implement this interface, and document them using the
+     * UiEventEnum annotation.
+     * Event IDs must be globally unique. This will be enforced by tooling (forthcoming).
+     * OEMs should use event IDs above 100000.
+     */
+    interface UiEventEnum {
+        int getId();
+    }
+    /**
+     * Log a simple event, with no package or instance ID.
+     */
+    void log(UiEventEnum eventID);
+}
diff --git a/core/java/com/android/internal/logging/UiEventLoggerImpl.java b/core/java/com/android/internal/logging/UiEventLoggerImpl.java
new file mode 100644
index 0000000..e64fba2
--- /dev/null
+++ b/core/java/com/android/internal/logging/UiEventLoggerImpl.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 com.android.internal.logging;
+
+import android.util.StatsLog;
+
+/**
+ * Standard implementation of UiEventLogger, writing to StatsLog.
+ *
+ * See UiEventReported atom in atoms.proto for more context.
+ */
+public class UiEventLoggerImpl implements UiEventLogger {
+    /**
+     * Log a simple event, with no package or instance ID.
+     */
+    @Override
+    public void log(UiEventEnum event) {
+        final int eventID = event.getId();
+        if (eventID > 0) {
+            StatsLog.write(StatsLog.UI_EVENT_REPORTED, eventID, 0, null);
+        }
+    }
+}
diff --git a/core/java/com/android/internal/logging/testing/UiEventLoggerFake.java b/core/java/com/android/internal/logging/testing/UiEventLoggerFake.java
new file mode 100644
index 0000000..92e9bbb
--- /dev/null
+++ b/core/java/com/android/internal/logging/testing/UiEventLoggerFake.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.logging.testing;
+
+import com.android.internal.logging.UiEventLogger;
+
+import java.util.LinkedList;
+import java.util.Queue;
+
+/**
+ * Fake logger that queues up logged events for inspection.
+ *
+ * @hide.
+ */
+public class UiEventLoggerFake implements UiEventLogger {
+    /**
+     * Immutable data class used to record fake log events.
+     */
+    public class FakeUiEvent {
+        public final int eventId;
+        public final int uid;
+        public final String packageName;
+
+        public FakeUiEvent(int eventId, int uid, String packageName) {
+            this.eventId = eventId;
+            this.uid = uid;
+            this.packageName = packageName;
+        }
+    }
+
+    private Queue<FakeUiEvent> mLogs = new LinkedList<FakeUiEvent>();
+
+    @Override
+    public void log(UiEventEnum event) {
+        final int eventId = event.getId();
+        if (eventId > 0) {
+            mLogs.offer(new FakeUiEvent(eventId, 0, null));
+        }
+    }
+
+    public Queue<FakeUiEvent> getLogs() {
+        return mLogs;
+    }
+}
diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java
index 227ef28..764d4a59 100644
--- a/core/java/com/android/internal/policy/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -3109,8 +3109,9 @@
             // On TVs, if the app doesn't implement search, we want to launch assist.
             Bundle args = new Bundle();
             args.putInt(Intent.EXTRA_ASSIST_INPUT_DEVICE_ID, event.getDeviceId());
-            return ((SearchManager)getContext().getSystemService(Context.SEARCH_SERVICE))
-                    .launchLegacyAssist(null, getContext().getUserId(), args);
+            ((SearchManager) getContext().getSystemService(Context.SEARCH_SERVICE))
+                    .launchAssist(args);
+            return true;
         }
         return result;
     }
diff --git a/core/java/com/android/internal/util/function/pooled/PooledLambda.java b/core/java/com/android/internal/util/function/pooled/PooledLambda.java
index d32ff06..a60cc0f 100755
--- a/core/java/com/android/internal/util/function/pooled/PooledLambda.java
+++ b/core/java/com/android/internal/util/function/pooled/PooledLambda.java
@@ -383,7 +383,7 @@
             QuadPredicate<? super A, ? super B, ? super C, ? super D> function,
             ArgumentPlaceholder<A> arg1, B arg2, C arg3, D arg4) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 3, 1, ReturnType.BOOLEAN, arg1, arg2, arg3, arg4, null, null, null, null,
+                function, 4, 1, ReturnType.BOOLEAN, arg1, arg2, arg3, arg4, null, null, null, null,
                 null, null, null);
     }
 
@@ -404,7 +404,7 @@
             QuintPredicate<? super A, ? super B, ? super C, ? super D, ? super E> function,
             ArgumentPlaceholder<A> arg1, B arg2, C arg3, D arg4, E arg5) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 3, 1, ReturnType.BOOLEAN, arg1, arg2, arg3, arg4, arg5, null, null, null,
+                function, 5, 1, ReturnType.BOOLEAN, arg1, arg2, arg3, arg4, arg5, null, null, null,
                 null, null, null);
     }
 
diff --git a/core/java/com/android/internal/view/IInlineSuggestionsRequestCallback.aidl b/core/java/com/android/internal/view/IInlineSuggestionsRequestCallback.aidl
new file mode 100644
index 0000000..6b54910
--- /dev/null
+++ b/core/java/com/android/internal/view/IInlineSuggestionsRequestCallback.aidl
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.view;
+
+import android.view.inputmethod.InlineSuggestionsRequest;
+
+import com.android.internal.view.IInlineSuggestionsResponseCallback;
+
+/**
+ * Binder interface for the IME service to send an inline suggestion request to the system.
+ * {@hide}
+ */
+oneway interface IInlineSuggestionsRequestCallback {
+    void onInlineSuggestionsUnsupported();
+    void onInlineSuggestionsRequest(in InlineSuggestionsRequest request,
+            in IInlineSuggestionsResponseCallback callback);
+}
diff --git a/core/java/com/android/internal/view/IInlineSuggestionsResponseCallback.aidl b/core/java/com/android/internal/view/IInlineSuggestionsResponseCallback.aidl
new file mode 100644
index 0000000..0f93b8e
--- /dev/null
+++ b/core/java/com/android/internal/view/IInlineSuggestionsResponseCallback.aidl
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.view;
+
+import android.view.inputmethod.InlineSuggestionsResponse;
+
+/**
+ * Binder interface for the IME service to receive an inline suggestion response from the system.
+ * {@hide}
+ */
+oneway interface IInlineSuggestionsResponseCallback {
+    void onInlineSuggestionsResponse(in InlineSuggestionsResponse response);
+}
diff --git a/core/java/com/android/internal/view/inline/IInlineContentCallback.aidl b/core/java/com/android/internal/view/inline/IInlineContentCallback.aidl
new file mode 100644
index 0000000..8cc49ca
--- /dev/null
+++ b/core/java/com/android/internal/view/inline/IInlineContentCallback.aidl
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.view.inline;
+
+import android.view.SurfaceControl;
+
+/**
+ * Binder interface to send the inline content from one process to the other.
+ * {@hide}
+ */
+oneway interface IInlineContentCallback {
+    void onContent(in SurfaceControl content);
+}
diff --git a/core/java/com/android/internal/view/inline/IInlineContentProvider.aidl b/core/java/com/android/internal/view/inline/IInlineContentProvider.aidl
new file mode 100644
index 0000000..08a349c
--- /dev/null
+++ b/core/java/com/android/internal/view/inline/IInlineContentProvider.aidl
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.view.inline;
+
+import com.android.internal.view.inline.IInlineContentCallback;
+
+/**
+ * Binder interface for a process to request the inline content from the other process.
+ * {@hide}
+ */
+oneway interface IInlineContentProvider {
+    void provideContent(int width, int height, in IInlineContentCallback callback);
+}
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/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp
index 0487e13..2dec4b3 100755
--- a/core/jni/android/graphics/Bitmap.cpp
+++ b/core/jni/android/graphics/Bitmap.cpp
@@ -223,97 +223,11 @@
     bitmap->getSkBitmap(outBitmap);
 }
 
-Bitmap& toBitmap(JNIEnv* env, jobject bitmap) {
-    SkASSERT(env);
-    SkASSERT(bitmap);
-    SkASSERT(env->IsInstanceOf(bitmap, gBitmap_class));
-    jlong bitmapHandle = env->GetLongField(bitmap, gBitmap_nativePtr);
-    LocalScopedBitmap localBitmap(bitmapHandle);
-    return localBitmap->bitmap();
-}
-
 Bitmap& toBitmap(jlong bitmapHandle) {
     LocalScopedBitmap localBitmap(bitmapHandle);
     return localBitmap->bitmap();
 }
 
-void imageInfo(JNIEnv* env, jobject bitmap, AndroidBitmapInfo* info) {
-    jlong bitmapHandle = env->GetLongField(bitmap, gBitmap_nativePtr);
-    LocalScopedBitmap localBitmap(bitmapHandle);
-
-    const SkImageInfo& imageInfo = localBitmap->info();
-    info->width = imageInfo.width();
-    info->height = imageInfo.height();
-    info->stride = localBitmap->rowBytes();
-    info->flags = 0;
-    switch (imageInfo.colorType()) {
-        case kN32_SkColorType:
-            info->format = ANDROID_BITMAP_FORMAT_RGBA_8888;
-            break;
-        case kRGB_565_SkColorType:
-            info->format = ANDROID_BITMAP_FORMAT_RGB_565;
-            break;
-        case kARGB_4444_SkColorType:
-            info->format = ANDROID_BITMAP_FORMAT_RGBA_4444;
-            break;
-        case kAlpha_8_SkColorType:
-            info->format = ANDROID_BITMAP_FORMAT_A_8;
-            break;
-        case kRGBA_F16_SkColorType:
-            info->format = ANDROID_BITMAP_FORMAT_RGBA_F16;
-            break;
-        default:
-            info->format = ANDROID_BITMAP_FORMAT_NONE;
-            break;
-    }
-    switch (imageInfo.alphaType()) {
-        case kUnknown_SkAlphaType:
-            LOG_ALWAYS_FATAL("Bitmap has no alpha type");
-            break;
-        case kOpaque_SkAlphaType:
-            info->flags |= ANDROID_BITMAP_FLAGS_ALPHA_OPAQUE;
-            break;
-        case kPremul_SkAlphaType:
-            info->flags |= ANDROID_BITMAP_FLAGS_ALPHA_PREMUL;
-            break;
-        case kUnpremul_SkAlphaType:
-            info->flags |= ANDROID_BITMAP_FLAGS_ALPHA_UNPREMUL;
-            break;
-    }
-}
-
-void* lockPixels(JNIEnv* env, jobject bitmap) {
-    SkASSERT(env);
-    SkASSERT(bitmap);
-    SkASSERT(env->IsInstanceOf(bitmap, gBitmap_class));
-    jlong bitmapHandle = env->GetLongField(bitmap, gBitmap_nativePtr);
-
-    LocalScopedBitmap localBitmap(bitmapHandle);
-    if (!localBitmap->valid()) return nullptr;
-
-    SkPixelRef& pixelRef = localBitmap->bitmap();
-    if (!pixelRef.pixels()) {
-        return nullptr;
-    }
-    pixelRef.ref();
-    return pixelRef.pixels();
-}
-
-bool unlockPixels(JNIEnv* env, jobject bitmap) {
-    SkASSERT(env);
-    SkASSERT(bitmap);
-    SkASSERT(env->IsInstanceOf(bitmap, gBitmap_class));
-    jlong bitmapHandle = env->GetLongField(bitmap, gBitmap_nativePtr);
-
-    LocalScopedBitmap localBitmap(bitmapHandle);
-    if (!localBitmap->valid()) return false;
-
-    SkPixelRef& pixelRef = localBitmap->bitmap();
-    pixelRef.notifyPixelsChanged();
-    pixelRef.unref();
-    return true;
-}
-
 } // namespace bitmap
 
 } // namespace android
@@ -321,6 +235,27 @@
 using namespace android;
 using namespace android::bitmap;
 
+Bitmap* GraphicsJNI::getNativeBitmap(JNIEnv* env, jobject bitmap) {
+    SkASSERT(env);
+    SkASSERT(bitmap);
+    SkASSERT(env->IsInstanceOf(bitmap, gBitmap_class));
+    jlong bitmapHandle = env->GetLongField(bitmap, gBitmap_nativePtr);
+    LocalScopedBitmap localBitmap(bitmapHandle);
+    return localBitmap.valid() ? &localBitmap->bitmap() : nullptr;
+}
+
+SkImageInfo GraphicsJNI::getBitmapInfo(JNIEnv* env, jobject bitmap, uint32_t* outRowBytes) {
+    SkASSERT(env);
+    SkASSERT(bitmap);
+    SkASSERT(env->IsInstanceOf(bitmap, gBitmap_class));
+    jlong bitmapHandle = env->GetLongField(bitmap, gBitmap_nativePtr);
+    LocalScopedBitmap localBitmap(bitmapHandle);
+    if (outRowBytes) {
+        *outRowBytes = localBitmap->rowBytes();
+    }
+    return localBitmap->info();
+}
+
 bool GraphicsJNI::SetPixels(JNIEnv* env, jintArray srcColors, int srcOffset, int srcStride,
         int x, int y, int width, int height, SkBitmap* dstBitmap) {
     const jint* array = env->GetIntArrayElements(srcColors, NULL);
diff --git a/core/jni/android/graphics/Bitmap.h b/core/jni/android/graphics/Bitmap.h
index 59adbb2..73eca3a 100644
--- a/core/jni/android/graphics/Bitmap.h
+++ b/core/jni/android/graphics/Bitmap.h
@@ -38,17 +38,8 @@
             int bitmapCreateFlags, jbyteArray ninePatchChunk = nullptr,
             jobject ninePatchInsets = nullptr, int density = -1);
 
-
-Bitmap& toBitmap(JNIEnv* env, jobject bitmap);
 Bitmap& toBitmap(jlong bitmapHandle);
 
-// NDK access
-void imageInfo(JNIEnv* env, jobject bitmap, AndroidBitmapInfo* info);
-// Returns a pointer to the pixels or nullptr if the bitmap is not valid
-void* lockPixels(JNIEnv* env, jobject bitmap);
-// Returns true if unlocked, false if the bitmap is no longer valid (destroyed)
-bool unlockPixels(JNIEnv* env, jobject bitmap);
-
 /** Reinitialize a bitmap. bitmap must already have its SkAlphaType set in
     sync with isPremultiplied
 */
diff --git a/core/jni/android/graphics/Graphics.cpp b/core/jni/android/graphics/Graphics.cpp
index bc1cc09..aa209cb 100644
--- a/core/jni/android/graphics/Graphics.cpp
+++ b/core/jni/android/graphics/Graphics.cpp
@@ -342,10 +342,6 @@
     return static_cast<SkColorType>(gConfig2ColorType[legacyConfig]);
 }
 
-void GraphicsJNI::getSkBitmap(JNIEnv* env, jobject bitmap, SkBitmap* outBitmap) {
-    bitmap::toBitmap(env, bitmap).getSkBitmap(outBitmap);
-}
-
 AndroidBitmapFormat GraphicsJNI::getFormatFromConfig(JNIEnv* env, jobject jconfig) {
     ALOG_ASSERT(env);
     if (NULL == jconfig) {
diff --git a/core/jni/android/graphics/GraphicsJNI.h b/core/jni/android/graphics/GraphicsJNI.h
index 6e7d9e7..99034ed 100644
--- a/core/jni/android/graphics/GraphicsJNI.h
+++ b/core/jni/android/graphics/GraphicsJNI.h
@@ -61,7 +61,8 @@
     static void point_to_jpointf(const SkPoint& point, JNIEnv*, jobject jpointf);
 
     static android::Canvas* getNativeCanvas(JNIEnv*, jobject canvas);
-    static void getSkBitmap(JNIEnv*, jobject bitmap, SkBitmap* outBitmap);
+    static android::Bitmap* getNativeBitmap(JNIEnv*, jobject bitmap);
+    static SkImageInfo getBitmapInfo(JNIEnv*, jobject bitmap, uint32_t* outRowBytes);
     static SkRegion* getNativeRegion(JNIEnv*, jobject region);
 
     /*
diff --git a/core/jni/android/graphics/apex/android_bitmap.cpp b/core/jni/android/graphics/apex/android_bitmap.cpp
index a328def..90cc986 100644
--- a/core/jni/android/graphics/apex/android_bitmap.cpp
+++ b/core/jni/android/graphics/apex/android_bitmap.cpp
@@ -14,19 +14,25 @@
  * limitations under the License.
  */
 
+#define LOG_TAG "Bitmap"
+#include <log/log.h>
+
 #include "android/graphics/bitmap.h"
-#include "Bitmap.h"
 #include "TypeCast.h"
 #include "GraphicsJNI.h"
 
+#include <GraphicsJNI.h>
 #include <hwui/Bitmap.h>
 
 using namespace android;
 
 ABitmap* ABitmap_acquireBitmapFromJava(JNIEnv* env, jobject bitmapObj) {
-    Bitmap& bitmap = android::bitmap::toBitmap(env, bitmapObj);
-    bitmap.ref();
-    return TypeCast::toABitmap(&bitmap);
+    Bitmap* bitmap = GraphicsJNI::getNativeBitmap(env, bitmapObj);
+    if (bitmap) {
+        bitmap->ref();
+        return TypeCast::toABitmap(bitmap);
+    }
+    return nullptr;
 }
 
 void ABitmap_acquireRef(ABitmap* bitmap) {
@@ -37,8 +43,8 @@
     SkSafeUnref(TypeCast::toBitmap(bitmap));
 }
 
-static AndroidBitmapFormat getFormat(Bitmap* bitmap) {
-    switch (bitmap->colorType()) {
+static AndroidBitmapFormat getFormat(const SkImageInfo& info) {
+    switch (info.colorType()) {
         case kN32_SkColorType:
             return ANDROID_BITMAP_FORMAT_RGBA_8888;
         case kRGB_565_SkColorType:
@@ -71,6 +77,20 @@
     }
 }
 
+static uint32_t getInfoFlags(const SkImageInfo& info) {
+    switch (info.alphaType()) {
+        case kUnknown_SkAlphaType:
+            LOG_ALWAYS_FATAL("Bitmap has no alpha type");
+            break;
+        case kOpaque_SkAlphaType:
+            return ANDROID_BITMAP_FLAGS_ALPHA_OPAQUE;
+        case kPremul_SkAlphaType:
+            return ANDROID_BITMAP_FLAGS_ALPHA_PREMUL;
+        case kUnpremul_SkAlphaType:
+            return ANDROID_BITMAP_FLAGS_ALPHA_UNPREMUL;
+    }
+}
+
 ABitmap* ABitmap_copy(ABitmap* srcBitmapHandle, AndroidBitmapFormat dstFormat) {
     SkColorType dstColorType = getColorType(dstFormat);
     if (srcBitmapHandle && dstColorType != kUnknown_SkColorType) {
@@ -87,15 +107,25 @@
     return nullptr;
 }
 
+static AndroidBitmapInfo getInfo(const SkImageInfo& imageInfo, uint32_t rowBytes) {
+    AndroidBitmapInfo info;
+    info.width = imageInfo.width();
+    info.height = imageInfo.height();
+    info.stride = rowBytes;
+    info.format = getFormat(imageInfo);
+    info.flags = getInfoFlags(imageInfo);
+    return info;
+}
+
 AndroidBitmapInfo ABitmap_getInfo(ABitmap* bitmapHandle) {
     Bitmap* bitmap = TypeCast::toBitmap(bitmapHandle);
+    return getInfo(bitmap->info(), bitmap->rowBytes());
+}
 
-    AndroidBitmapInfo info;
-    info.width = bitmap->width();
-    info.height = bitmap->height();
-    info.stride = bitmap->rowBytes();
-    info.format = getFormat(bitmap);
-    return info;
+AndroidBitmapInfo ABitmap_getInfoFromJava(JNIEnv* env, jobject bitmapObj) {
+    uint32_t rowBytes = 0;
+    SkImageInfo imageInfo = GraphicsJNI::getBitmapInfo(env, bitmapObj, &rowBytes);
+    return getInfo(imageInfo, rowBytes);
 }
 
 void* ABitmap_getPixels(ABitmap* bitmapHandle) {
@@ -107,9 +137,17 @@
 }
 
 AndroidBitmapFormat ABitmapConfig_getFormatFromConfig(JNIEnv* env, jobject bitmapConfigObj) {
-  return GraphicsJNI::getFormatFromConfig(env, bitmapConfigObj);
+    return GraphicsJNI::getFormatFromConfig(env, bitmapConfigObj);
 }
 
 jobject ABitmapConfig_getConfigFromFormat(JNIEnv* env, AndroidBitmapFormat format) {
-  return GraphicsJNI::getConfigFromFormat(env, format);
+    return GraphicsJNI::getConfigFromFormat(env, format);
+}
+
+void ABitmap_notifyPixelsChanged(ABitmap* bitmapHandle) {
+    Bitmap* bitmap = TypeCast::toBitmap(bitmapHandle);
+    if (bitmap->isImmutable()) {
+        ALOGE("Attempting to modify an immutable Bitmap!");
+    }
+    return bitmap->notifyPixelsChanged();
 }
diff --git a/core/jni/android/graphics/apex/include/android/graphics/bitmap.h b/core/jni/android/graphics/apex/include/android/graphics/bitmap.h
index dea5517..f231eed 100644
--- a/core/jni/android/graphics/apex/include/android/graphics/bitmap.h
+++ b/core/jni/android/graphics/apex/include/android/graphics/bitmap.h
@@ -27,6 +27,20 @@
  */
 typedef struct ABitmap ABitmap;
 
+/**
+ * Retrieve bitmapInfo for the provided java bitmap even if it has been recycled.  In the case of a
+ * recycled bitmap the values contained in the bitmap before it was recycled are returned.
+ *
+ * NOTE: This API does not need to remain as an APEX API if/when we pull libjnigraphics into the
+ *       UI module.
+ */
+AndroidBitmapInfo ABitmap_getInfoFromJava(JNIEnv* env, jobject bitmapObj);
+
+/**
+ *
+ * @return ptr to an opaque handle to the native bitmap or null if the java bitmap has been recycled
+ *         or does not exist.
+ */
 ABitmap* ABitmap_acquireBitmapFromJava(JNIEnv* env, jobject bitmapObj);
 
 ABitmap* ABitmap_copy(ABitmap* srcBitmap, AndroidBitmapFormat dstFormat);
@@ -37,6 +51,7 @@
 AndroidBitmapInfo ABitmap_getInfo(ABitmap* bitmap);
 
 void* ABitmap_getPixels(ABitmap* bitmap);
+void ABitmap_notifyPixelsChanged(ABitmap* bitmap);
 
 AndroidBitmapFormat ABitmapConfig_getFormatFromConfig(JNIEnv* env, jobject bitmapConfigObj);
 jobject ABitmapConfig_getConfigFromFormat(JNIEnv* env, AndroidBitmapFormat format);
@@ -88,10 +103,12 @@
             mBitmap = nullptr;
         }
 
-        const ABitmap* get() const { return mBitmap; }
+        ABitmap* get() const { return mBitmap; }
 
         AndroidBitmapInfo getInfo() const { return ABitmap_getInfo(mBitmap); }
         void* getPixels() const { return ABitmap_getPixels(mBitmap); }
+        void notifyPixelsChanged() const { ABitmap_notifyPixelsChanged(mBitmap); }
+
     private:
         // takes ownership of the provided ABitmap
         Bitmap(ABitmap* bitmap) : mBitmap(bitmap) {}
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_os_SystemProperties.cpp b/core/jni/android_os_SystemProperties.cpp
index 7f8bec6..7f3b32e 100644
--- a/core/jni/android_os_SystemProperties.cpp
+++ b/core/jni/android_os_SystemProperties.cpp
@@ -123,7 +123,7 @@
 jboolean SystemProperties_get_boolean(JNIEnv *env, jclass, jstring keyJ,
                                       jboolean defJ)
 {
-    ParseBoolResult parseResult;
+    ParseBoolResult parseResult = ParseBoolResult::kError;
     ReadProperty(env, keyJ, [&](const char* value) {
         parseResult = android::base::ParseBool(value);
     });
@@ -168,7 +168,7 @@
 
 jboolean SystemProperties_get_booleanH(CRITICAL_JNI_PARAMS_COMMA jlong propJ, jboolean defJ)
 {
-    ParseBoolResult parseResult;
+    ParseBoolResult parseResult = ParseBoolResult::kError;
     auto prop = reinterpret_cast<const prop_info*>(propJ);
     ReadProperty(prop, [&](const char* value) {
         parseResult = android::base::ParseBool(value);
diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp
index 7350396..170e467 100644
--- a/core/jni/android_view_ThreadedRenderer.cpp
+++ b/core/jni/android_view_ThreadedRenderer.cpp
@@ -180,10 +180,13 @@
     if (jsurface) {
         surface = android_view_Surface_getSurface(env, jsurface);
     }
+    bool enableTimeout = true;
     if (discardBuffer) {
+        // Currently only Surface#lockHardwareCanvas takes this path
+        enableTimeout = false;
         proxy->setSwapBehavior(SwapBehavior::kSwap_discardBuffer);
     }
-    proxy->setSurface(surface);
+    proxy->setSurface(surface, enableTimeout);
 }
 
 static jboolean android_view_ThreadedRenderer_pause(JNIEnv* env, jobject clazz,
diff --git a/core/jni/fd_utils.cpp b/core/jni/fd_utils.cpp
index 3704ccd..8fabb23 100644
--- a/core/jni/fd_utils.cpp
+++ b/core/jni/fd_utils.cpp
@@ -34,6 +34,7 @@
 // Static whitelist of open paths that the zygote is allowed to keep open.
 static const char* kPathWhitelist[] = {
   "/apex/com.android.conscrypt/javalib/conscrypt.jar",
+  "/apex/com.android.ipsec/javalib/ike.jar",
   "/apex/com.android.media/javalib/updatable-media.jar",
   "/dev/null",
   "/dev/socket/zygote",
diff --git a/core/proto/android/server/activitymanagerservice.proto b/core/proto/android/server/activitymanagerservice.proto
index 8f084ab..ce2717b 100644
--- a/core/proto/android/server/activitymanagerservice.proto
+++ b/core/proto/android/server/activitymanagerservice.proto
@@ -126,11 +126,12 @@
     optional .com.android.server.wm.ConfigurationContainerProto configuration_container = 1 [deprecated=true];
     optional .com.android.server.wm.IdentifierProto identifier = 2;
     optional string state = 3;
-    optional bool visible = 4;
+    optional bool visible_requested = 4;
     optional bool front_of_task = 5;
     optional int32 proc_id = 6;
     optional bool translucent = 7;
     optional .com.android.server.wm.AppWindowTokenProto app_window_token = 8;
+    optional bool visible = 9;
 }
 
 message KeyguardControllerProto {
diff --git a/core/proto/android/server/windowmanagerservice.proto b/core/proto/android/server/windowmanagerservice.proto
index 1a4a7ce..24456d8 100644
--- a/core/proto/android/server/windowmanagerservice.proto
+++ b/core/proto/android/server/windowmanagerservice.proto
@@ -236,7 +236,7 @@
     optional bool fills_parent = 7;
     optional bool app_stopped = 8;
     optional bool visible_requested = 9;
-    optional bool client_hidden = 10;
+    optional bool client_visible = 10;
     optional bool defer_hiding_client = 11;
     optional bool reported_drawn = 12;
     optional bool reported_visible = 13;
@@ -249,8 +249,9 @@
     optional IdentifierProto starting_window = 19;
     optional bool starting_displayed = 20;
     optional bool starting_moved = 21;
-    optional bool hidden_set_from_transferred_starting_window = 22;
+    optional bool visible_set_from_transferred_starting_window = 22;
     repeated .android.graphics.RectProto frozen_bounds = 23;
+    optional bool visible = 24;
 }
 
 /* represents WindowToken */
@@ -260,7 +261,6 @@
     optional WindowContainerProto window_container = 1;
     optional int32 hash_code = 2;
     repeated WindowStateProto windows = 3;
-    optional bool hidden = 4;
     optional bool waiting_to_show = 5;
     optional bool paused = 6;
 }
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 62001aa..a6f65f9 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -499,7 +499,6 @@
     <protected-broadcast android:name="android.telephony.action.CARRIER_CONFIG_CHANGED" />
     <protected-broadcast android:name="android.telephony.action.DEFAULT_SUBSCRIPTION_CHANGED" />
     <protected-broadcast android:name="android.telephony.action.DEFAULT_SMS_SUBSCRIPTION_CHANGED" />
-    <protected-broadcast android:name="android.telephony.action.OTA_EMERGENCY_NUMBER_DB_INSTALLED" />
     <protected-broadcast android:name="android.telephony.action.SECRET_CODE" />
     <protected-broadcast android:name="android.telephony.action.SHOW_VOICEMAIL_NOTIFICATION" />
     <protected-broadcast android:name="android.telephony.action.SUBSCRIPTION_PLANS_CHANGED" />
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 642dc92..234ffee 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -3702,8 +3702,6 @@
             <flag name="flagRequestFingerprintGestures" value="0x00000200" />
             <!-- Has flag {@link android.accessibilityservice.AccessibilityServiceInfo#FLAG_REQUEST_SHORTCUT_WARNING_DIALOG_SPOKEN_FEEDBACK}. -->
             <flag name="flagRequestShortcutWarningDialogSpokenFeedback" value="0x00000400" />
-            <!-- Has flag {@link android.accessibilityservice.AccessibilityServiceInfo#FLAG_HANDLE_SHORTCUT}. -->
-            <flag name="flagHandleShortcut" value="0x00000800" />
         </attr>
         <!-- Component name of an activity that allows the user to modify
              the settings for this service. This setting cannot be changed at runtime. -->
diff --git a/core/tests/coretests/src/android/provider/DeviceConfigTest.java b/core/tests/coretests/src/android/provider/DeviceConfigTest.java
index 0c83390..8c1c3b5 100644
--- a/core/tests/coretests/src/android/provider/DeviceConfigTest.java
+++ b/core/tests/coretests/src/android/provider/DeviceConfigTest.java
@@ -33,6 +33,9 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.util.HashMap;
+import java.util.Map;
+
 /** Tests that ensure appropriate settings are backed up. */
 @Presubmit
 @RunWith(AndroidJUnit4.class)
@@ -484,12 +487,74 @@
         assertThat(properties.getString(KEY3, DEFAULT_VALUE)).isEqualTo(DEFAULT_VALUE);
     }
 
-    // TODO(mpape): resolve b/142727848 and re-enable this test
+    @Test
+    public void setProperties() {
+        Map<String, String> keyValues = new HashMap<>();
+        keyValues.put(KEY, VALUE);
+        keyValues.put(KEY2, VALUE2);
+
+        DeviceConfig.setProperties(new Properties(NAMESPACE, keyValues));
+        Properties properties = DeviceConfig.getProperties(NAMESPACE);
+        assertThat(properties.getKeyset()).containsExactly(KEY, KEY2);
+        assertThat(properties.getString(KEY, DEFAULT_VALUE)).isEqualTo(VALUE);
+        assertThat(properties.getString(KEY2, DEFAULT_VALUE)).isEqualTo(VALUE2);
+
+        Map<String, String> newKeyValues = new HashMap<>();
+        newKeyValues.put(KEY, VALUE2);
+        newKeyValues.put(KEY3, VALUE3);
+
+        DeviceConfig.setProperties(new Properties(NAMESPACE, newKeyValues));
+        properties = DeviceConfig.getProperties(NAMESPACE);
+        assertThat(properties.getKeyset()).containsExactly(KEY, KEY3);
+        assertThat(properties.getString(KEY, DEFAULT_VALUE)).isEqualTo(VALUE2);
+        assertThat(properties.getString(KEY3, DEFAULT_VALUE)).isEqualTo(VALUE3);
+
+        assertThat(properties.getKeyset()).doesNotContain(KEY2);
+        assertThat(properties.getString(KEY2, DEFAULT_VALUE)).isEqualTo(DEFAULT_VALUE);
+    }
+
+    @Test
+    public void setProperties_multipleNamespaces() {
+        Map<String, String> keyValues = new HashMap<>();
+        keyValues.put(KEY, VALUE);
+        keyValues.put(KEY2, VALUE2);
+
+        Map<String, String> keyValues2 = new HashMap<>();
+        keyValues2.put(KEY2, VALUE);
+        keyValues2.put(KEY3, VALUE2);
+
+        final String namespace2 = "namespace2";
+        DeviceConfig.setProperties(new Properties(NAMESPACE, keyValues));
+        DeviceConfig.setProperties(new Properties(namespace2, keyValues2));
+
+        Properties properties = DeviceConfig.getProperties(NAMESPACE);
+        assertThat(properties.getKeyset()).containsExactly(KEY, KEY2);
+        assertThat(properties.getString(KEY, DEFAULT_VALUE)).isEqualTo(VALUE);
+        assertThat(properties.getString(KEY2, DEFAULT_VALUE)).isEqualTo(VALUE2);
+
+        assertThat(properties.getKeyset()).doesNotContain(KEY3);
+        assertThat(properties.getString(KEY3, DEFAULT_VALUE)).isEqualTo(DEFAULT_VALUE);
+
+        properties = DeviceConfig.getProperties(namespace2);
+        assertThat(properties.getKeyset()).containsExactly(KEY2, KEY3);
+        assertThat(properties.getString(KEY2, DEFAULT_VALUE)).isEqualTo(VALUE);
+        assertThat(properties.getString(KEY3, DEFAULT_VALUE)).isEqualTo(VALUE2);
+
+        assertThat(properties.getKeyset()).doesNotContain(KEY);
+        assertThat(properties.getString(KEY, DEFAULT_VALUE)).isEqualTo(DEFAULT_VALUE);
+
+        // clean up
+        deleteViaContentProvider(namespace2, KEY);
+        deleteViaContentProvider(namespace2, KEY2);
+        deleteViaContentProvider(namespace2, KEY3);
+    }
+
+    // TODO(mpape): resolve b/142727848 and re-enable listener tests
 //    @Test
-//    public void testOnPropertiesChangedListener() throws InterruptedException {
+//    public void onPropertiesChangedListener_setPropertyCallback() throws InterruptedException {
 //        final CountDownLatch countDownLatch = new CountDownLatch(1);
 //
-//        OnPropertiesChangedListener changeListener = (properties) -> {
+//        DeviceConfig.OnPropertiesChangedListener changeListener = (properties) -> {
 //            assertThat(properties.getNamespace()).isEqualTo(NAMESPACE);
 //            assertThat(properties.getKeyset()).contains(KEY);
 //            assertThat(properties.getString(KEY, "default_value")).isEqualTo(VALUE);
@@ -508,6 +573,42 @@
 //            DeviceConfig.removeOnPropertiesChangedListener(changeListener);
 //        }
 //    }
+//
+//    @Test
+//    public void onPropertiesChangedListener_setPropertiesCallback() throws InterruptedException {
+//        final CountDownLatch countDownLatch = new CountDownLatch(1);
+//        DeviceConfig.setProperty(NAMESPACE, KEY, VALUE, false);
+//        DeviceConfig.setProperty(NAMESPACE, KEY2, VALUE2, false);
+//
+//        Map<String, String> keyValues = new HashMap<>(2);
+//        keyValues.put(KEY, VALUE2);
+//        keyValues.put(KEY3, VALUE3);
+//        Properties setProperties = new Properties(NAMESPACE, keyValues);
+//
+//        DeviceConfig.OnPropertiesChangedListener changeListener = (properties) -> {
+//            assertThat(properties.getNamespace()).isEqualTo(NAMESPACE);
+//            assertThat(properties.getKeyset()).containsExactly(KEY, KEY2, KEY3);
+//            // KEY updated from VALUE to VALUE2
+//            assertThat(properties.getString(KEY, "default_value")).isEqualTo(VALUE2);
+//            // KEY2 deleted (returns default_value)
+//            assertThat(properties.getString(KEY2, "default_value")).isEqualTo("default_value");
+//            //KEY3 added with VALUE3
+//            assertThat(properties.getString(KEY3, "default_value")).isEqualTo(VALUE3);
+//            countDownLatch.countDown();
+//        };
+//
+//        try {
+//            DeviceConfig.addOnPropertiesChangedListener(NAMESPACE,
+//                    ActivityThread.currentApplication().getMainExecutor(), changeListener);
+//            DeviceConfig.setProperties(setProperties);
+//            assertThat(countDownLatch.await(
+//                    WAIT_FOR_PROPERTY_CHANGE_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)).isTrue();
+//        } catch (InterruptedException e) {
+//            Assert.fail(e.getMessage());
+//        } finally {
+//            DeviceConfig.removeOnPropertiesChangedListener(changeListener);
+//        }
+//    }
 
     private static boolean deleteViaContentProvider(String namespace, String key) {
         ContentResolver resolver = InstrumentationRegistry.getContext().getContentResolver();
diff --git a/core/tests/coretests/src/android/util/StatsEventTest.java b/core/tests/coretests/src/android/util/StatsEventTest.java
new file mode 100644
index 0000000..93f11db
--- /dev/null
+++ b/core/tests/coretests/src/android/util/StatsEventTest.java
@@ -0,0 +1,466 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.util;
+
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+
+import android.os.SystemClock;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.google.common.collect.Range;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+/**
+ * Internal tests for {@link StatsEvent}.
+ */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class StatsEventTest {
+
+    @Test
+    public void testNoFields() {
+        final long minTimestamp = SystemClock.elapsedRealtimeNanos();
+        final StatsEvent statsEvent = StatsEvent.newBuilder().build();
+        final long maxTimestamp = SystemClock.elapsedRealtimeNanos();
+
+        final int expectedAtomId = 0;
+        assertThat(statsEvent.getAtomId()).isEqualTo(expectedAtomId);
+
+        final ByteBuffer buffer =
+                ByteBuffer.wrap(statsEvent.getBytes()).order(ByteOrder.LITTLE_ENDIAN);
+
+        assertWithMessage("Root element in buffer is not TYPE_ERRORS")
+                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_ERRORS);
+
+        assertWithMessage("Incorrect number of elements in root object")
+                .that(buffer.get()).isEqualTo(3);
+
+        assertWithMessage("First element is not timestamp")
+                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_LONG);
+
+        assertWithMessage("Incorrect timestamp")
+                .that(buffer.getLong()).isIn(Range.closed(minTimestamp, maxTimestamp));
+
+        assertWithMessage("Second element is not atom id")
+                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_INT);
+
+        assertWithMessage("Incorrect atom id")
+                .that(buffer.getInt()).isEqualTo(expectedAtomId);
+
+        final int errorMask = buffer.getInt();
+
+        assertWithMessage("ERROR_NO_ATOM_ID should be the only error in the error mask")
+                .that(errorMask).isEqualTo(StatsEvent.ERROR_NO_ATOM_ID);
+
+        assertThat(statsEvent.getNumBytes()).isEqualTo(buffer.position());
+
+        statsEvent.release();
+    }
+
+    @Test
+    public void testIntBooleanIntInt() {
+        final int expectedAtomId = 109;
+        final int field1 = 1;
+        final boolean field2 = true;
+        final int field3 = 3;
+        final int field4 = 4;
+
+        final long minTimestamp = SystemClock.elapsedRealtimeNanos();
+        final StatsEvent statsEvent = StatsEvent.newBuilder()
+                .setAtomId(expectedAtomId)
+                .writeInt(field1)
+                .writeBoolean(field2)
+                .writeInt(field3)
+                .writeInt(field4)
+                .build();
+        final long maxTimestamp = SystemClock.elapsedRealtimeNanos();
+
+        assertThat(statsEvent.getAtomId()).isEqualTo(expectedAtomId);
+
+        final ByteBuffer buffer =
+                ByteBuffer.wrap(statsEvent.getBytes()).order(ByteOrder.LITTLE_ENDIAN);
+
+        assertWithMessage("Root element in buffer is not TYPE_OBJECT")
+                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_OBJECT);
+
+        assertWithMessage("Incorrect number of elements in root object")
+                .that(buffer.get()).isEqualTo(6);
+
+        assertWithMessage("First element is not timestamp")
+                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_LONG);
+
+        assertWithMessage("Incorrect timestamp")
+                .that(buffer.getLong()).isIn(Range.closed(minTimestamp, maxTimestamp));
+
+        assertWithMessage("Second element is not atom id")
+                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_INT);
+
+        assertWithMessage("Incorrect atom id")
+                .that(buffer.getInt()).isEqualTo(expectedAtomId);
+
+        assertWithMessage("First field is not Int")
+                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_INT);
+
+        assertWithMessage("Incorrect field 1")
+                .that(buffer.getInt()).isEqualTo(field1);
+
+        assertWithMessage("Second field is not Boolean")
+                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_BOOLEAN);
+
+        assertWithMessage("Incorrect field 2")
+                .that(buffer.get()).isEqualTo(1);
+
+        assertWithMessage("Third field is not Int")
+                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_INT);
+
+        assertWithMessage("Incorrect field 3")
+                .that(buffer.getInt()).isEqualTo(field3);
+
+        assertWithMessage("Fourth field is not Int")
+                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_INT);
+
+        assertWithMessage("Incorrect field 4")
+                .that(buffer.getInt()).isEqualTo(field4);
+
+        assertThat(statsEvent.getNumBytes()).isEqualTo(buffer.position());
+
+        statsEvent.release();
+    }
+
+    @Test
+    public void testStringFloatByteArray() {
+        final int expectedAtomId = 109;
+        final String field1 = "Str 1";
+        final float field2 = 9.334f;
+        final byte[] field3 = new byte[] { 56, 23, 89, -120 };
+
+        final long minTimestamp = SystemClock.elapsedRealtimeNanos();
+        final StatsEvent statsEvent = StatsEvent.newBuilder()
+                .setAtomId(expectedAtomId)
+                .writeString(field1)
+                .writeFloat(field2)
+                .writeByteArray(field3)
+                .build();
+        final long maxTimestamp = SystemClock.elapsedRealtimeNanos();
+
+        assertThat(statsEvent.getAtomId()).isEqualTo(expectedAtomId);
+
+        final ByteBuffer buffer =
+                ByteBuffer.wrap(statsEvent.getBytes()).order(ByteOrder.LITTLE_ENDIAN);
+
+        assertWithMessage("Root element in buffer is not TYPE_OBJECT")
+                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_OBJECT);
+
+        assertWithMessage("Incorrect number of elements in root object")
+                .that(buffer.get()).isEqualTo(5);
+
+        assertWithMessage("First element is not timestamp")
+                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_LONG);
+
+        assertWithMessage("Incorrect timestamp")
+                .that(buffer.getLong()).isIn(Range.closed(minTimestamp, maxTimestamp));
+
+        assertWithMessage("Second element is not atom id")
+                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_INT);
+
+        assertWithMessage("Incorrect atom id")
+                .that(buffer.getInt()).isEqualTo(expectedAtomId);
+
+        assertWithMessage("First field is not String")
+                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_STRING);
+
+        final String field1Actual = getStringFromByteBuffer(buffer);
+        assertWithMessage("Incorrect field 1")
+                .that(field1Actual).isEqualTo(field1);
+
+        assertWithMessage("Second field is not Float")
+                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_FLOAT);
+
+        assertWithMessage("Incorrect field 2")
+                .that(buffer.getFloat()).isEqualTo(field2);
+
+        assertWithMessage("Third field is not byte array")
+                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_BYTE_ARRAY);
+
+        final byte[] field3Actual = getByteArrayFromByteBuffer(buffer);
+        assertWithMessage("Incorrect field 3")
+                .that(field3Actual).isEqualTo(field3);
+
+        assertThat(statsEvent.getNumBytes()).isEqualTo(buffer.position());
+
+        statsEvent.release();
+    }
+
+    @Test
+    public void testAttributionChainLong() {
+        final int expectedAtomId = 109;
+        final int[] uids = new int[] { 1, 2, 3, 4, 5 };
+        final String[] tags = new String[] { "1", "2", "3", "4", "5" };
+        final long field2 = -230909823L;
+
+        final long minTimestamp = SystemClock.elapsedRealtimeNanos();
+        final StatsEvent statsEvent = StatsEvent.newBuilder()
+                .setAtomId(expectedAtomId)
+                .writeAttributionChain(uids, tags)
+                .writeLong(field2)
+                .build();
+        final long maxTimestamp = SystemClock.elapsedRealtimeNanos();
+
+        assertThat(statsEvent.getAtomId()).isEqualTo(expectedAtomId);
+
+        final ByteBuffer buffer =
+                ByteBuffer.wrap(statsEvent.getBytes()).order(ByteOrder.LITTLE_ENDIAN);
+
+        assertWithMessage("Root element in buffer is not TYPE_OBJECT")
+                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_OBJECT);
+
+        assertWithMessage("Incorrect number of elements in root object")
+                .that(buffer.get()).isEqualTo(4);
+
+        assertWithMessage("First element is not timestamp")
+                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_LONG);
+
+        assertWithMessage("Incorrect timestamp")
+                .that(buffer.getLong()).isIn(Range.closed(minTimestamp, maxTimestamp));
+
+        assertWithMessage("Second element is not atom id")
+                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_INT);
+
+        assertWithMessage("Incorrect atom id")
+                .that(buffer.getInt()).isEqualTo(expectedAtomId);
+
+        assertWithMessage("First field is not Attribution Chain")
+                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_ATTRIBUTION_CHAIN);
+
+        assertWithMessage("Incorrect number of attribution nodes")
+                .that(buffer.get()).isEqualTo((byte) uids.length);
+
+        for (int i = 0; i < tags.length; i++) {
+            assertWithMessage("Incorrect uid in Attribution Chain")
+                    .that(buffer.getInt()).isEqualTo(uids[i]);
+
+            final String tag = getStringFromByteBuffer(buffer);
+            assertWithMessage("Incorrect tag in Attribution Chain")
+                    .that(tag).isEqualTo(tags[i]);
+        }
+
+        assertWithMessage("Second field is not Long")
+                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_LONG);
+
+        assertWithMessage("Incorrect field 2")
+                .that(buffer.getLong()).isEqualTo(field2);
+
+        assertThat(statsEvent.getNumBytes()).isEqualTo(buffer.position());
+
+        statsEvent.release();
+    }
+
+    @Test
+    public void testKeyValuePairs() {
+        final int expectedAtomId = 109;
+        final SparseIntArray intMap = new SparseIntArray();
+        final SparseLongArray longMap = new SparseLongArray();
+        final SparseArray<String> stringMap = new SparseArray<>();
+        final SparseArray<Float> floatMap = new SparseArray<>();
+        intMap.put(1, -1);
+        intMap.put(2, -2);
+        stringMap.put(3, "abc");
+        stringMap.put(4, "2h");
+        floatMap.put(9, -234.344f);
+
+        final long minTimestamp = SystemClock.elapsedRealtimeNanos();
+        final StatsEvent statsEvent = StatsEvent.newBuilder()
+                .setAtomId(expectedAtomId)
+                .writeKeyValuePairs(intMap, longMap, stringMap, floatMap)
+                .build();
+        final long maxTimestamp = SystemClock.elapsedRealtimeNanos();
+
+        assertThat(statsEvent.getAtomId()).isEqualTo(expectedAtomId);
+
+        final ByteBuffer buffer =
+                ByteBuffer.wrap(statsEvent.getBytes()).order(ByteOrder.LITTLE_ENDIAN);
+
+        assertWithMessage("Root element in buffer is not TYPE_OBJECT")
+                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_OBJECT);
+
+        assertWithMessage("Incorrect number of elements in root object")
+                .that(buffer.get()).isEqualTo(3);
+
+        assertWithMessage("First element is not timestamp")
+                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_LONG);
+
+        assertWithMessage("Incorrect timestamp")
+                .that(buffer.getLong()).isIn(Range.closed(minTimestamp, maxTimestamp));
+
+        assertWithMessage("Second element is not atom id")
+                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_INT);
+
+        assertWithMessage("Incorrect atom id")
+                .that(buffer.getInt()).isEqualTo(expectedAtomId);
+
+        assertWithMessage("First field is not KeyValuePairs")
+                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_KEY_VALUE_PAIRS);
+
+        assertWithMessage("Incorrect number of key value pairs")
+                .that(buffer.get()).isEqualTo(
+                        (byte) (intMap.size() + longMap.size() + stringMap.size()
+                                + floatMap.size()));
+
+        for (int i = 0; i < intMap.size(); i++) {
+            assertWithMessage("Incorrect key in intMap")
+                    .that(buffer.getInt()).isEqualTo(intMap.keyAt(i));
+            assertWithMessage("The type id of the value should be TYPE_INT in intMap")
+                    .that(buffer.get()).isEqualTo(StatsEvent.TYPE_INT);
+            assertWithMessage("Incorrect value in intMap")
+                    .that(buffer.getInt()).isEqualTo(intMap.valueAt(i));
+        }
+
+        for (int i = 0; i < longMap.size(); i++) {
+            assertWithMessage("Incorrect key in longMap")
+                    .that(buffer.getInt()).isEqualTo(longMap.keyAt(i));
+            assertWithMessage("The type id of the value should be TYPE_LONG in longMap")
+                    .that(buffer.get()).isEqualTo(StatsEvent.TYPE_LONG);
+            assertWithMessage("Incorrect value in longMap")
+                    .that(buffer.getLong()).isEqualTo(longMap.valueAt(i));
+        }
+
+        for (int i = 0; i < stringMap.size(); i++) {
+            assertWithMessage("Incorrect key in stringMap")
+                    .that(buffer.getInt()).isEqualTo(stringMap.keyAt(i));
+            assertWithMessage("The type id of the value should be TYPE_STRING in stringMap")
+                    .that(buffer.get()).isEqualTo(StatsEvent.TYPE_STRING);
+            final String value = getStringFromByteBuffer(buffer);
+            assertWithMessage("Incorrect value in stringMap")
+                    .that(value).isEqualTo(stringMap.valueAt(i));
+        }
+
+        for (int i = 0; i < floatMap.size(); i++) {
+            assertWithMessage("Incorrect key in floatMap")
+                    .that(buffer.getInt()).isEqualTo(floatMap.keyAt(i));
+            assertWithMessage("The type id of the value should be TYPE_FLOAT in floatMap")
+                    .that(buffer.get()).isEqualTo(StatsEvent.TYPE_FLOAT);
+            assertWithMessage("Incorrect value in floatMap")
+                    .that(buffer.getFloat()).isEqualTo(floatMap.valueAt(i));
+        }
+
+        assertThat(statsEvent.getNumBytes()).isEqualTo(buffer.position());
+
+        statsEvent.release();
+    }
+
+    @Test
+    public void testSingleAnnotations() {
+        final int expectedAtomId = 109;
+        final int field1 = 1;
+        final byte field1AnnotationId = 45;
+        final boolean field1AnnotationValue = false;
+        final boolean field2 = true;
+        final byte field2AnnotationId = 1;
+        final int field2AnnotationValue = 23;
+
+        final long minTimestamp = SystemClock.elapsedRealtimeNanos();
+        final StatsEvent statsEvent = StatsEvent.newBuilder()
+                .setAtomId(expectedAtomId)
+                .writeInt(field1)
+                .addBooleanAnnotation(field1AnnotationId, field1AnnotationValue)
+                .writeBoolean(field2)
+                .addIntAnnotation(field2AnnotationId, field2AnnotationValue)
+                .build();
+        final long maxTimestamp = SystemClock.elapsedRealtimeNanos();
+
+        assertThat(statsEvent.getAtomId()).isEqualTo(expectedAtomId);
+
+        final ByteBuffer buffer =
+                ByteBuffer.wrap(statsEvent.getBytes()).order(ByteOrder.LITTLE_ENDIAN);
+
+        assertWithMessage("Root element in buffer is not TYPE_OBJECT")
+                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_OBJECT);
+
+        assertWithMessage("Incorrect number of elements in root object")
+                .that(buffer.get()).isEqualTo(4);
+
+        assertWithMessage("First element is not timestamp")
+                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_LONG);
+
+        assertWithMessage("Incorrect timestamp")
+                .that(buffer.getLong()).isIn(Range.closed(minTimestamp, maxTimestamp));
+
+        assertWithMessage("Second element is not atom id")
+                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_INT);
+
+        assertWithMessage("Incorrect atom id")
+                .that(buffer.getInt()).isEqualTo(expectedAtomId);
+
+        final byte field1Header = buffer.get();
+        final int field1AnnotationValueCount = field1Header >> 4;
+        final byte field1Type = (byte) (field1Header & 0x0F);
+        assertWithMessage("First field is not Int")
+                .that(field1Type).isEqualTo(StatsEvent.TYPE_INT);
+        assertWithMessage("First field annotation count is wrong")
+                .that(field1AnnotationValueCount).isEqualTo(1);
+        assertWithMessage("Incorrect field 1")
+                .that(buffer.getInt()).isEqualTo(field1);
+        assertWithMessage("First field's annotation id is wrong")
+                .that(buffer.get()).isEqualTo(field1AnnotationId);
+        assertWithMessage("First field's annotation type is wrong")
+                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_BOOLEAN);
+        assertWithMessage("First field's annotation value is wrong")
+                .that(buffer.get()).isEqualTo(field1AnnotationValue ? 1 : 0);
+
+        final byte field2Header = buffer.get();
+        final int field2AnnotationValueCount = field2Header >> 4;
+        final byte field2Type = (byte) (field2Header & 0x0F);
+        assertWithMessage("Second field is not boolean")
+                .that(field2Type).isEqualTo(StatsEvent.TYPE_BOOLEAN);
+        assertWithMessage("Second field annotation count is wrong")
+                .that(field2AnnotationValueCount).isEqualTo(1);
+        assertWithMessage("Incorrect field 2")
+                .that(buffer.get()).isEqualTo(field2 ? 1 : 0);
+        assertWithMessage("Second field's annotation id is wrong")
+                .that(buffer.get()).isEqualTo(field2AnnotationId);
+        assertWithMessage("Second field's annotation type is wrong")
+                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_INT);
+        assertWithMessage("Second field's annotation value is wrong")
+                .that(buffer.getInt()).isEqualTo(field2AnnotationValue);
+
+        assertThat(statsEvent.getNumBytes()).isEqualTo(buffer.position());
+
+        statsEvent.release();
+    }
+
+    private static byte[] getByteArrayFromByteBuffer(final ByteBuffer buffer) {
+        final int numBytes = buffer.getInt();
+        byte[] bytes = new byte[numBytes];
+        buffer.get(bytes);
+        return bytes;
+    }
+
+    private static String getStringFromByteBuffer(final ByteBuffer buffer) {
+        final byte[] bytes = getByteArrayFromByteBuffer(buffer);
+        return new String(bytes, UTF_8);
+    }
+}
diff --git a/core/tests/coretests/src/com/android/internal/app/ResolverActivityTest.java b/core/tests/coretests/src/com/android/internal/app/ResolverActivityTest.java
index a401e21..344c286 100644
--- a/core/tests/coretests/src/com/android/internal/app/ResolverActivityTest.java
+++ b/core/tests/coretests/src/com/android/internal/app/ResolverActivityTest.java
@@ -50,6 +50,7 @@
 import com.android.internal.widget.ResolverDrawerLayout;
 
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -103,6 +104,7 @@
         assertThat(chosen[0], is(toChoose));
     }
 
+    @Ignore // Failing - b/144929805
     @Test
     public void setMaxHeight() throws Exception {
         Intent sendIntent = createSendImageIntent();
@@ -146,6 +148,7 @@
             resolverList.getHeight() == initialResolverHeight);
     }
 
+    @Ignore // Failing - b/144929805
     @Test
     public void setShowAtTopToTrue() throws Exception {
         Intent sendIntent = createSendImageIntent();
diff --git a/data/etc/services.core.protolog.json b/data/etc/services.core.protolog.json
index 5c48d91..440b885 100644
--- a/data/etc/services.core.protolog.json
+++ b/data/etc/services.core.protolog.json
@@ -55,6 +55,12 @@
       "group": "WM_DEBUG_REMOTE_ANIMATIONS",
       "at": "com\/android\/server\/wm\/RemoteAnimationController.java"
     },
+    "-2006946193": {
+      "message": "setClientVisible: %s clientVisible=%b Callers=%s",
+      "level": "VERBOSE",
+      "group": "WM_DEBUG_APP_TRANSITIONS",
+      "at": "com\/android\/server\/wm\/ActivityRecord.java"
+    },
     "-2002500255": {
       "message": "Defer removing snapshot surface in %dms",
       "level": "VERBOSE",
@@ -73,10 +79,10 @@
       "group": "WM_ERROR",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
-    "-1972506791": {
-      "message": "Set freezing of %s: hidden=%b freezing=%b visibleRequested=%b. %s",
-      "level": "INFO",
-      "group": "WM_DEBUG_ORIENTATION",
+    "-1976550065": {
+      "message": "commitVisibility: %s: visible=%b visibleRequested=%b",
+      "level": "VERBOSE",
+      "group": "WM_DEBUG_APP_TRANSITIONS",
       "at": "com\/android\/server\/wm\/ActivityRecord.java"
     },
     "-1963461591": {
@@ -85,12 +91,6 @@
       "group": "WM_DEBUG_ADD_REMOVE",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
-    "-1958209312": {
-      "message": "Clear freezing of %s: hidden=%b freezing=%b",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_ORIENTATION",
-      "at": "com\/android\/server\/wm\/ActivityRecord.java"
-    },
     "-1953668890": {
       "message": "Can't start recents animation, nextAppTransition=%s",
       "level": "DEBUG",
@@ -307,12 +307,6 @@
       "group": "WM_DEBUG_ADD_REMOVE",
       "at": "com\/android\/server\/wm\/ActivityRecord.java"
     },
-    "-1456549051": {
-      "message": "setClientHidden: %s clientHidden=%b Callers=%s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_APP_TRANSITIONS",
-      "at": "com\/android\/server\/wm\/ActivityRecord.java"
-    },
     "-1455600136": {
       "message": "Attempted to add Dream window with unknown token %s.  Aborting.",
       "level": "WARN",
@@ -547,12 +541,6 @@
       "group": "WM_DEBUG_STARTING_WINDOW",
       "at": "com\/android\/server\/wm\/WindowState.java"
     },
-    "-931184679": {
-      "message": "Changing app %s hidden=%b performLayout=%b",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_APP_TRANSITIONS",
-      "at": "com\/android\/server\/wm\/ActivityRecord.java"
-    },
     "-928291778": {
       "message": "applyAnimation: anim=%s nextAppTransition=%d transit=%s Callers=%s",
       "level": "VERBOSE",
@@ -841,6 +829,12 @@
       "group": "WM_DEBUG_APP_TRANSITIONS",
       "at": "com\/android\/server\/wm\/AppTransitionController.java"
     },
+    "-374767836": {
+      "message": "setAppVisibility(%s, visible=%b): %s visible=%b mVisibleRequested=%b Callers=%s",
+      "level": "VERBOSE",
+      "group": "WM_DEBUG_APP_TRANSITIONS",
+      "at": "com\/android\/server\/wm\/ActivityRecord.java"
+    },
     "-371630969": {
       "message": "New wallpaper target=%s, oldWallpaper=%s, openingApps=%s, closingApps=%s",
       "level": "VERBOSE",
@@ -883,12 +877,6 @@
       "group": "WM_DEBUG_ORIENTATION",
       "at": "com\/android\/server\/wm\/ActivityRecord.java"
     },
-    "-229838822": {
-      "message": "setAppVisibility(%s, visible=%b): %s hidden=%b mVisibleRequested=%b Callers=%s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_APP_TRANSITIONS",
-      "at": "com\/android\/server\/wm\/ActivityRecord.java"
-    },
     "-198463978": {
       "message": "updateRotationUnchecked: alwaysSendConfiguration=%b forceRelayout=%b",
       "level": "VERBOSE",
@@ -1273,6 +1261,12 @@
       "group": "WM_DEBUG_SCREEN_ON",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
+    "466506262": {
+      "message": "Clear freezing of %s: visible=%b freezing=%b",
+      "level": "VERBOSE",
+      "group": "WM_DEBUG_ORIENTATION",
+      "at": "com\/android\/server\/wm\/ActivityRecord.java"
+    },
     "474000473": {
       "message": "No stack above target stack=%s",
       "level": "DEBUG",
@@ -1483,6 +1477,12 @@
       "group": "WM_DEBUG_REMOTE_ANIMATIONS",
       "at": "com\/android\/server\/wm\/RemoteAnimationController.java"
     },
+    "841702299": {
+      "message": "Changing app %s visible=%b performLayout=%b",
+      "level": "VERBOSE",
+      "group": "WM_DEBUG_APP_TRANSITIONS",
+      "at": "com\/android\/server\/wm\/ActivityRecord.java"
+    },
     "845234215": {
       "message": "App is requesting an orientation, return %d for display id=%d",
       "level": "VERBOSE",
@@ -1891,6 +1891,12 @@
       "group": "WM_DEBUG_STARTING_WINDOW",
       "at": "com\/android\/server\/wm\/ActivityRecord.java"
     },
+    "1746778201": {
+      "message": "Set freezing of %s: visible=%b freezing=%b visibleRequested=%b. %s",
+      "level": "INFO",
+      "group": "WM_DEBUG_ORIENTATION",
+      "at": "com\/android\/server\/wm\/ActivityRecord.java"
+    },
     "1747941491": {
       "message": "SURFACE controller=%s alpha=%f matrix=[%f*%f,%f*%f][%f*%f,%f*%f]: %s",
       "level": "INFO",
@@ -1987,12 +1993,6 @@
       "group": "WM_DEBUG_REMOTE_ANIMATIONS",
       "at": "com\/android\/server\/wm\/RemoteAnimationController.java"
     },
-    "1965198071": {
-      "message": "commitVisibility: %s: hidden=%b visibleRequested=%b",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_APP_TRANSITIONS",
-      "at": "com\/android\/server\/wm\/ActivityRecord.java"
-    },
     "1984470582": {
       "message": "Creating TaskScreenshotAnimatable: task: %s width: %d height: %d",
       "level": "DEBUG",
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index f086768..8490221 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -140,13 +140,15 @@
     mAnimationContext->destroy();
 }
 
-void CanvasContext::setSurface(sp<Surface>&& surface) {
+void CanvasContext::setSurface(sp<Surface>&& surface, bool enableTimeout) {
     ATRACE_CALL();
 
     if (surface) {
         mNativeSurface = new ReliableSurface{std::move(surface)};
-        // TODO: Fix error handling & re-shorten timeout
-        ANativeWindow_setDequeueTimeout(mNativeSurface.get(), 4000_ms);
+        if (enableTimeout) {
+            // TODO: Fix error handling & re-shorten timeout
+            ANativeWindow_setDequeueTimeout(mNativeSurface.get(), 4000_ms);
+        }
     } else {
         mNativeSurface = nullptr;
     }
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index b192d46..4490f80 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -111,7 +111,7 @@
     // Won't take effect until next EGLSurface creation
     void setSwapBehavior(SwapBehavior swapBehavior);
 
-    void setSurface(sp<Surface>&& surface);
+    void setSurface(sp<Surface>&& surface, bool enableTimeout = true);
     bool pauseSurface();
     void setStopped(bool stopped);
     bool hasSurface() const { return mNativeSurface.get(); }
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index 4f7ad7b..f9e401a 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -78,9 +78,10 @@
     mRenderThread.queue().runSync([this, name]() { mContext->setName(std::string(name)); });
 }
 
-void RenderProxy::setSurface(const sp<Surface>& surface) {
-    mRenderThread.queue().post(
-            [this, surf = surface]() mutable { mContext->setSurface(std::move(surf)); });
+void RenderProxy::setSurface(const sp<Surface>& surface, bool enableTimeout) {
+    mRenderThread.queue().post([this, surf = surface, enableTimeout]() mutable {
+        mContext->setSurface(std::move(surf), enableTimeout);
+    });
 }
 
 void RenderProxy::allocateBuffers() {
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index e6fe1d4..4683e1d 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -69,7 +69,7 @@
     ANDROID_API bool loadSystemProperties();
     ANDROID_API void setName(const char* name);
 
-    ANDROID_API void setSurface(const sp<Surface>& surface);
+    ANDROID_API void setSurface(const sp<Surface>& surface, bool enableTimeout = true);
     ANDROID_API void allocateBuffers();
     ANDROID_API bool pause();
     ANDROID_API void setStopped(bool stopped);
diff --git a/libs/input/tests/PointerController_test.cpp b/libs/input/tests/PointerController_test.cpp
index 92efb4e..b36406d 100644
--- a/libs/input/tests/PointerController_test.cpp
+++ b/libs/input/tests/PointerController_test.cpp
@@ -32,8 +32,8 @@
     CURSOR_TYPE_HOVER,
     CURSOR_TYPE_TOUCH,
     CURSOR_TYPE_ANCHOR,
-    CURSOR_TYPE_ADDITIONAL_1,
-    CURSOR_TYPE_ADDITIONAL_2,
+    CURSOR_TYPE_ADDITIONAL,
+    CURSOR_TYPE_ADDITIONAL_ANIM,
     CURSOR_TYPE_CUSTOM = -1,
 };
 
@@ -79,13 +79,18 @@
     SpriteIcon icon;
     PointerAnimation anim;
 
-    for (int32_t cursorType : {CURSOR_TYPE_ADDITIONAL_1, CURSOR_TYPE_ADDITIONAL_2}) {
-        loadPointerIconForType(&icon, cursorType);
-        anim.animationFrames.push_back(icon);
-        anim.durationPerFrame = 10;
-        (*outResources)[cursorType] = icon;
-        (*outAnimationResources)[cursorType] = anim;
-    }
+    // CURSOR_TYPE_ADDITIONAL doesn't have animation resource.
+    int32_t cursorType = CURSOR_TYPE_ADDITIONAL;
+    loadPointerIconForType(&icon, cursorType);
+    (*outResources)[cursorType] = icon;
+
+    // CURSOR_TYPE_ADDITIONAL_ANIM has animation resource.
+    cursorType = CURSOR_TYPE_ADDITIONAL_ANIM;
+    loadPointerIconForType(&icon, cursorType);
+    anim.animationFrames.push_back(icon);
+    anim.durationPerFrame = 10;
+    (*outResources)[cursorType] = icon;
+    (*outAnimationResources)[cursorType] = anim;
 }
 
 int32_t MockPointerControllerPolicyInterface::getDefaultPointerIconId() {
@@ -178,7 +183,7 @@
 TEST_F(PointerControllerTest, updatePointerIcon) {
     mPointerController->unfade(PointerController::TRANSITION_IMMEDIATE);
 
-    int32_t type = CURSOR_TYPE_ADDITIONAL_1;
+    int32_t type = CURSOR_TYPE_ADDITIONAL;
     std::pair<float, float> hotspot = getHotSpotCoordinatesForType(type);
     EXPECT_CALL(*mPointerSprite, setVisible(true));
     EXPECT_CALL(*mPointerSprite, setAlpha(1.0f));
diff --git a/location/java/android/location/Location.java b/location/java/android/location/Location.java
index 27274d1..db48ee7 100644
--- a/location/java/android/location/Location.java
+++ b/location/java/android/location/Location.java
@@ -161,7 +161,10 @@
      * <p>By default time, latitude and longitude are 0, and the location
      * has no bearing, altitude, speed, accuracy or extras.
      *
-     * @param provider the name of the provider that generated this location
+     * @param provider the source that provides the location. It can be of type
+     * {@link LocationManager#GPS_PROVIDER}, {@link LocationManager#NETWORK_PROVIDER},
+     * or {@link LocationManager#PASSIVE_PROVIDER}. You can also define your own
+     * provider string, in which case an empty string is a valid provider.
      */
     public Location(String provider) {
         mProvider = provider;
diff --git a/location/java/android/location/OnNmeaMessageListener.java b/location/java/android/location/OnNmeaMessageListener.java
index ccf6ce8..05647bc 100644
--- a/location/java/android/location/OnNmeaMessageListener.java
+++ b/location/java/android/location/OnNmeaMessageListener.java
@@ -28,7 +28,9 @@
     /**
      * Called when an NMEA message is received.
      * @param message NMEA message
-     * @param timestamp milliseconds since January 1, 1970.
+     * @param timestamp Date and time of the location fix, as reported by the GNSS
+     *                  chipset. The value is specified in milliseconds since 0:00
+     *                  UTC 1 January 1970.
      */
     void onNmeaMessage(String message, long timestamp);
 }
diff --git a/location/java/com/android/internal/location/gnssmetrics/GnssMetrics.java b/location/java/com/android/internal/location/gnssmetrics/GnssMetrics.java
index e0bff74..c20dc61 100644
--- a/location/java/com/android/internal/location/gnssmetrics/GnssMetrics.java
+++ b/location/java/com/android/internal/location/gnssmetrics/GnssMetrics.java
@@ -114,6 +114,7 @@
      * Logs the status of a location report received from the HAL
      */
     public void logReceivedLocationStatus(boolean isSuccessful) {
+        StatsLog.write(StatsLog.GPS_LOCATION_STATUS_REPORTED, isSuccessful);
         if (!isSuccessful) {
             mLocationFailureStatistics.addItem(1.0);
             return;
@@ -130,6 +131,7 @@
                 DEFAULT_TIME_BETWEEN_FIXES_MILLISECS, desiredTimeBetweenFixesMilliSeconds)) - 1;
         if (numReportMissed > 0) {
             for (int i = 0; i < numReportMissed; i++) {
+                StatsLog.write(StatsLog.GPS_LOCATION_STATUS_REPORTED, false);
                 mLocationFailureStatistics.addItem(1.0);
             }
         }
@@ -140,6 +142,7 @@
      */
     public void logTimeToFirstFixMilliSecs(int timeToFirstFixMilliSeconds) {
         mTimeToFirstFixSecStatistics.addItem((double) (timeToFirstFixMilliSeconds / 1000));
+        StatsLog.write(StatsLog.GPS_TIME_TO_FIRST_FIX_REPORTED, timeToFirstFixMilliSeconds);
     }
 
     /**
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/native/graphics/jni/bitmap.cpp b/native/graphics/jni/bitmap.cpp
index ff14832..1aebeaf 100644
--- a/native/graphics/jni/bitmap.cpp
+++ b/native/graphics/jni/bitmap.cpp
@@ -15,7 +15,7 @@
  */
 
 #include <android/bitmap.h>
-#include <android/graphics/Bitmap.h>
+#include <android/graphics/bitmap.h>
 
 int AndroidBitmap_getInfo(JNIEnv* env, jobject jbitmap,
                           AndroidBitmapInfo* info) {
@@ -24,7 +24,7 @@
     }
 
     if (info) {
-        android::bitmap::imageInfo(env, jbitmap, info);
+        *info = ABitmap_getInfoFromJava(env, jbitmap);
     }
     return ANDROID_BITMAP_RESULT_SUCCESS;
 }
@@ -34,11 +34,15 @@
         return ANDROID_BITMAP_RESULT_BAD_PARAMETER;
     }
 
-    void* addr = android::bitmap::lockPixels(env, jbitmap);
+    android::graphics::Bitmap bitmap(env, jbitmap);
+    void* addr = bitmap.isValid() ? bitmap.getPixels() : nullptr;
+
     if (!addr) {
         return ANDROID_BITMAP_RESULT_JNI_EXCEPTION;
     }
 
+    ABitmap_acquireRef(bitmap.get());
+
     if (addrPtr) {
         *addrPtr = addr;
     }
@@ -50,9 +54,13 @@
         return ANDROID_BITMAP_RESULT_BAD_PARAMETER;
     }
 
-    bool unlocked = android::bitmap::unlockPixels(env, jbitmap);
-    if (!unlocked) {
+    android::graphics::Bitmap bitmap(env, jbitmap);
+
+    if (!bitmap.isValid()) {
         return ANDROID_BITMAP_RESULT_JNI_EXCEPTION;
     }
+
+    bitmap.notifyPixelsChanged();
+    ABitmap_releaseRef(bitmap.get());
     return ANDROID_BITMAP_RESULT_SUCCESS;
 }
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java
index b188dc3..4543019 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java
@@ -50,9 +50,6 @@
 @Singleton
 public class FullscreenUserSwitcher {
     private static final String TAG = FullscreenUserSwitcher.class.getSimpleName();
-    // Because user 0 is headless, user count for single user is 2
-    private static final int NUMBER_OF_BACKGROUND_USERS = 1;
-
     private final Context mContext;
     private final Resources mResources;
     private final UserManager mUserManager;
@@ -137,27 +134,18 @@
                 /* isStartGuestSession= */ false,
                 /* isAddUser= */ false,
                 /* isForeground= */ true);
-        // For single user without trusted device, hide the user switcher.
-        if (!hasMultipleUsers() && !hasTrustedDevice(initialUser)) {
-            dismissUserSwitcher();
-            return;
-        }
-        // Show unlock dialog for initial user
+
+        // If the initial user has trusted device, display the unlock dialog on the keyguard.
         if (hasTrustedDevice(initialUser)) {
             mUnlockDialogHelper.showUnlockDialogAfterDelay(initialUser,
                     mOnHideListener);
+        } else {
+            // If no trusted device, dismiss the keyguard.
+            dismissUserSwitcher();
         }
     }
 
     /**
-     * Check if there is only one possible user to login in.
-     * In a Multi-User system there is always one background user (user 0)
-     */
-    private boolean hasMultipleUsers() {
-        return mUserManager.getUserCount() > NUMBER_OF_BACKGROUND_USERS + 1;
-    }
-
-    /**
      * Makes user grid visible.
      */
     public void show() {
diff --git a/packages/CarrierDefaultApp/tests/unit/src/com/android/carrierdefaultapp/CarrierDefaultReceiverTest.java b/packages/CarrierDefaultApp/tests/unit/src/com/android/carrierdefaultapp/CarrierDefaultReceiverTest.java
index 5d84d64..1928ad9 100644
--- a/packages/CarrierDefaultApp/tests/unit/src/com/android/carrierdefaultapp/CarrierDefaultReceiverTest.java
+++ b/packages/CarrierDefaultApp/tests/unit/src/com/android/carrierdefaultapp/CarrierDefaultReceiverTest.java
@@ -21,7 +21,6 @@
 import android.content.Intent;
 import android.os.PersistableBundle;
 import android.telephony.CarrierConfigManager;
-import android.telephony.Rlog;
 import android.telephony.TelephonyManager;
 import android.test.InstrumentationTestCase;
 
@@ -90,12 +89,10 @@
 
         Intent intent = new Intent(TelephonyIntents.ACTION_CARRIER_SIGNAL_REDIRECTED);
         intent.putExtra(PhoneConstants.SUBSCRIPTION_KEY, subId);
-        Rlog.d(TAG, "OnReceive redirection intent");
         mReceiver.onReceive(mContext, intent);
 
         mContext.waitForMs(100);
 
-        Rlog.d(TAG, "verify carrier action: showPortalNotification");
         verify(mNotificationMgr, times(1)).notify(mString.capture(), mInt.capture(),
                 mNotification.capture());
         assertEquals(PORTAL_NOTIFICATION_ID, (int) mInt.getValue());
@@ -103,7 +100,6 @@
         PendingIntent pendingIntent = mNotification.getValue().contentIntent;
         assertNotNull(pendingIntent);
 
-        Rlog.d(TAG, "verify carrier action: disable all metered apns");
         verify(mTelephonyMgr).setCarrierDataEnabled(eq(false));
     }
 }
diff --git a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/ActivityTile.java b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/ActivityTile.java
index 8cd33a5..b739ee6 100644
--- a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/ActivityTile.java
+++ b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/ActivityTile.java
@@ -18,6 +18,7 @@
 
 import android.content.Context;
 import android.content.Intent;
+import android.content.pm.ActivityInfo;
 import android.content.pm.ComponentInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
@@ -33,7 +34,7 @@
 public class ActivityTile extends Tile {
     private static final String TAG = "ActivityTile";
 
-    public ActivityTile(ComponentInfo info, String category) {
+    public ActivityTile(ActivityInfo info, String category) {
         super(info, category);
         setMetaData(info.metaData);
     }
diff --git a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/MasterSwitchController.java b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/MasterSwitchController.java
new file mode 100644
index 0000000..a12aa83
--- /dev/null
+++ b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/MasterSwitchController.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 com.android.settingslib.drawer;
+
+import android.os.Bundle;
+
+/**
+ * A controller that manages event for master switch.
+ */
+public abstract class MasterSwitchController extends SwitchController {
+
+    @Override
+    protected final MetaData getMetaData() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    final Bundle getBundle() {
+        throw new UnsupportedOperationException();
+    }
+}
diff --git a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/ProviderTile.java b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/ProviderTile.java
index b2ba5de..312d30e 100644
--- a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/ProviderTile.java
+++ b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/ProviderTile.java
@@ -42,10 +42,10 @@
     private String mAuthority;
     private String mKey;
 
-    public ProviderTile(ComponentInfo info, String category, Bundle metaData) {
+    public ProviderTile(ProviderInfo info, String category, Bundle metaData) {
         super(info, category);
         setMetaData(metaData);
-        mAuthority = ((ProviderInfo) info).authority;
+        mAuthority = info.authority;
         mKey = metaData.getString(META_DATA_PREFERENCE_KEYHINT);
     }
 
diff --git a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/SwitchController.java b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/SwitchController.java
index e48da86..23669b2 100644
--- a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/SwitchController.java
+++ b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/SwitchController.java
@@ -108,7 +108,7 @@
     Bundle getBundle() {
         final MetaData metaData = getMetaData();
         if (metaData == null) {
-            throw new IllegalArgumentException("Should not return null in getMetaData()");
+            throw new NullPointerException("Should not return null in getMetaData()");
         }
 
         final Bundle bundle = metaData.build();
diff --git a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/SwitchesProvider.java b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/SwitchesProvider.java
index a05c7d5..73f1a90 100644
--- a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/SwitchesProvider.java
+++ b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/SwitchesProvider.java
@@ -55,7 +55,7 @@
 
     private String mAuthority;
     private final Map<String, SwitchController> mControllerMap = new LinkedHashMap<>();
-    private final List<Bundle> mSwitchList = new ArrayList<>();
+    private final List<Bundle> mSwitchDataList = new ArrayList<>();
 
     /**
      * Get a list of {@link SwitchController} for this provider.
@@ -88,7 +88,9 @@
 
             controller.setAuthority(mAuthority);
             mControllerMap.put(key, controller);
-            mSwitchList.add(controller.getBundle());
+            if (!(controller instanceof MasterSwitchController)) {
+                mSwitchDataList.add(controller.getBundle());
+            }
         });
         return true;
     }
@@ -101,7 +103,7 @@
                 : null;
         if (TextUtils.isEmpty(key)) {
             if (METHOD_GET_SWITCH_DATA.equals(method)) {
-                bundle.putParcelableList(EXTRA_SWITCH_DATA, mSwitchList);
+                bundle.putParcelableList(EXTRA_SWITCH_DATA, mSwitchDataList);
                 return bundle;
             }
             return null;
@@ -114,7 +116,10 @@
 
         switch (method) {
             case METHOD_GET_SWITCH_DATA:
-                return controller.getBundle();
+                if (!(controller instanceof MasterSwitchController)) {
+                    return controller.getBundle();
+                }
+                break;
             case METHOD_GET_PROVIDER_ICON:
                 if (controller instanceof ProviderIcon) {
                     return ((ProviderIcon) controller).getProviderIcon();
diff --git a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/TileUtils.java b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/TileUtils.java
index 71ffff7..f93faeb 100644
--- a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/TileUtils.java
+++ b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/TileUtils.java
@@ -244,15 +244,15 @@
             // TODO: Needs much optimization, too many PM queries going on here.
             if (user.getIdentifier() == ActivityManager.getCurrentUser()) {
                 // Only add Settings for this user.
-                getTilesForAction(context, user, SETTINGS_ACTION, cache, null, tiles, true);
-                getTilesForAction(context, user, OPERATOR_SETTINGS, cache,
+                loadTilesForAction(context, user, SETTINGS_ACTION, cache, null, tiles, true);
+                loadTilesForAction(context, user, OPERATOR_SETTINGS, cache,
                         OPERATOR_DEFAULT_CATEGORY, tiles, false);
-                getTilesForAction(context, user, MANUFACTURER_SETTINGS, cache,
+                loadTilesForAction(context, user, MANUFACTURER_SETTINGS, cache,
                         MANUFACTURER_DEFAULT_CATEGORY, tiles, false);
             }
             if (setup) {
-                getTilesForAction(context, user, EXTRA_SETTINGS_ACTION, cache, null, tiles, false);
-                getTilesForAction(context, user, IA_SETTINGS_ACTION, cache, null, tiles, false);
+                loadTilesForAction(context, user, EXTRA_SETTINGS_ACTION, cache, null, tiles, false);
+                loadTilesForAction(context, user, IA_SETTINGS_ACTION, cache, null, tiles, false);
             }
         }
 
@@ -284,18 +284,18 @@
     }
 
     @VisibleForTesting
-    static void getTilesForAction(Context context,
+    static void loadTilesForAction(Context context,
             UserHandle user, String action, Map<Pair<String, String>, Tile> addedCache,
             String defaultCategory, List<Tile> outTiles, boolean requireSettings) {
         final Intent intent = new Intent(action);
         if (requireSettings) {
             intent.setPackage(SETTING_PKG);
         }
-        getActivityTiles(context, user, addedCache, defaultCategory, outTiles, intent);
-        getProviderTiles(context, user, addedCache, defaultCategory, outTiles, intent);
+        loadActivityTiles(context, user, addedCache, defaultCategory, outTiles, intent);
+        loadProviderTiles(context, user, addedCache, defaultCategory, outTiles, intent);
     }
 
-    private static void getActivityTiles(Context context,
+    private static void loadActivityTiles(Context context,
             UserHandle user, Map<Pair<String, String>, Tile> addedCache,
             String defaultCategory, List<Tile> outTiles, Intent intent) {
         final PackageManager pm = context.getPackageManager();
@@ -308,11 +308,11 @@
             }
             final ActivityInfo activityInfo = resolved.activityInfo;
             final Bundle metaData = activityInfo.metaData;
-            getTile(user, addedCache, defaultCategory, outTiles, intent, metaData, activityInfo);
+            loadTile(user, addedCache, defaultCategory, outTiles, intent, metaData, activityInfo);
         }
     }
 
-    private static void getProviderTiles(Context context,
+    private static void loadProviderTiles(Context context,
             UserHandle user, Map<Pair<String, String>, Tile> addedCache,
             String defaultCategory, List<Tile> outTiles, Intent intent) {
         final PackageManager pm = context.getPackageManager();
@@ -330,13 +330,13 @@
                 continue;
             }
             for (Bundle metaData : switchData) {
-                getTile(user, addedCache, defaultCategory, outTiles, intent, metaData,
+                loadTile(user, addedCache, defaultCategory, outTiles, intent, metaData,
                         providerInfo);
             }
         }
     }
 
-    private static void getTile(UserHandle user, Map<Pair<String, String>, Tile> addedCache,
+    private static void loadTile(UserHandle user, Map<Pair<String, String>, Tile> addedCache,
             String defaultCategory, List<Tile> outTiles, Intent intent, Bundle metaData,
             ComponentInfo componentInfo) {
         String categoryKey = defaultCategory;
@@ -359,8 +359,8 @@
         Tile tile = addedCache.get(key);
         if (tile == null) {
             tile = isProvider
-                    ? new ProviderTile(componentInfo, categoryKey, metaData)
-                    : new ActivityTile(componentInfo, categoryKey);
+                    ? new ProviderTile((ProviderInfo) componentInfo, categoryKey, metaData)
+                    : new ActivityTile((ActivityInfo) componentInfo, categoryKey);
             addedCache.put(key, tile);
         } else {
             tile.setMetaData(metaData);
@@ -516,7 +516,7 @@
      * @param value       Boolean associated with the key
      * @return Bundle associated with the action, if returned by the content provider
      */
-    public static Bundle putBooleanToUri(Context context, Uri uri,
+    public static Bundle putBooleanToUriAndGetResult(Context context, Uri uri,
             Map<String, IContentProvider> providerMap, String key, boolean value) {
         final Bundle bundle = new Bundle();
         bundle.putBoolean(key, value);
diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml
index 3ff5cf4..6289b87 100644
--- a/packages/SettingsLib/res/values-af/strings.xml
+++ b/packages/SettingsLib/res/values-af/strings.xml
@@ -233,6 +233,7 @@
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Gebruik Bluetooth-oudiokodek\nKeuse"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Bluetooth-oudiovoorbeeldkoers"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Gebruik Bluetooth-oudiokodek\nKeuse: monsterkoers"</string>
+    <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Dofgemaak beteken dit word nie deur foon of kopstuk gesteun nie"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Bluetooth-oudiobisse per voorbeeld"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Gebruik Bluetooth-oudiokodek\nKeuse: bisse per monster"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Bluetooth-oudiokanaalmodus"</string>
diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml
index 264d8de..45545a7 100644
--- a/packages/SettingsLib/res/values-am/strings.xml
+++ b/packages/SettingsLib/res/values-am/strings.xml
@@ -233,6 +233,7 @@
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"የብሉቱዝ ኦዲዮ ኮዴክ አስጀምር\nምርጫ"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"የብሉቱዝ ኦዲዮ ናሙና ፍጥነት"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"የብሉቱዝ ኦዲዮ ኮዴክን አስጀምር\nምርጫ፦ የናሙና ደረጃ አሰጣጥ"</string>
+    <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"ግራጫ መልክ ሲታይ በስልክ ወይም በጆሮ ማዳመጫ አይደገፍም ማለት ነው"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"የብሉቱዝ ኦዲዮ ቢት በናሙና"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"የብሉቱዝ ኦዲዮ ኮዴክን አስጀምር\nምርጫ፦ ቢትስ በናሙና"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"የብሉቱዝ ኦዲዮ ሰርጥ ሁነታ"</string>
diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml
index c230236..af06fc7 100644
--- a/packages/SettingsLib/res/values-ar/strings.xml
+++ b/packages/SettingsLib/res/values-ar/strings.xml
@@ -233,6 +233,7 @@
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"اختيار برنامج ترميز الصوت لمشغّل\nالبلوتوث"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"معدّل عيّنة صوت بلوتوث"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"اختيار برنامج ترميز الصوت لمشغّل\nالبلوتوث: معدّل العيّنة"</string>
+    <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"\"غير متوفّر\" تعني أن الهاتف أو سماعة الرأس لا يدعمان برنامج الترميز"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"وحدات البت لكل عيّنة في صوت بلوتوث"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"اختيار برنامج ترميز الصوت لمشغّل\nالبلوتوث: عدد وحدات البت لكل عيّنة"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"وضع قناة صوت بلوتوث"</string>
diff --git a/packages/SettingsLib/res/values-as/strings.xml b/packages/SettingsLib/res/values-as/strings.xml
index ab0ed29..49eabe1 100644
--- a/packages/SettingsLib/res/values-as/strings.xml
+++ b/packages/SettingsLib/res/values-as/strings.xml
@@ -233,6 +233,7 @@
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"ব্লুটুথ অডিঅ\' ক\'ডেকৰ বাছনি\nআৰম্ভ কৰক"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"ব্লুটুথ অডিঅ\' ছেম্পল ৰেইট"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"ব্লুটুথ অডিঅ\' LDAC বাছনি\nআৰম্ভ কৰক: নমুনাৰ হাৰ"</string>
+    <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"ধোঁৱাবৰণীয়া হৈ থকা মানে এয়া ফ’ন অথবা হেডছেটটোৱে সমৰ্থন নকৰে"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"প্ৰতি ছেম্পলত ব্লুটুথ অডিঅ\' বিটসমূহ"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"ব্লুটুথ অডিঅ\' ক\'ডেকৰ বাছনি\nআৰম্ভ কৰক: প্ৰতি নমুনা ইমান বিট"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"ব্লুটুথ অডিঅ\' চ্চেনেল ম\'ড"</string>
diff --git a/packages/SettingsLib/res/values-az/strings.xml b/packages/SettingsLib/res/values-az/strings.xml
index fe62d31..158f13a 100644
--- a/packages/SettingsLib/res/values-az/strings.xml
+++ b/packages/SettingsLib/res/values-az/strings.xml
@@ -233,6 +233,7 @@
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Bluetooth Audio KodeK\nSeçimini aktiv edin"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Bluetooth Audio Nümunə Göstəricisi"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Bluetooth Audio Kodek\nSeçimini aktiv edin: Nümunə Göstəricisi"</string>
+    <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Boz rəng telefon və ya qulaqlıq tərəfindən dəstəklənmədiyini bildirir"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Hər Nümunə Üçün Bluetooth Audio Bit"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Bluetooth Audio Kodek\nSeçimini aktiv edin: Hər Nümunə üçün Bit"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Bluetooth Audio Kanal Rejimi"</string>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
index 1619584..2709df5 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
@@ -233,6 +233,7 @@
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Izaberite Bluetooth audio kodek\n"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Brzina uzorkovanja za Bluetooth audio"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Izaberite Bluetooth audio kodek:\n brzina uzorkovanja"</string>
+    <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Ako je neka stavka zasivljena, to znači da je telefon ili slušalice ne podržavaju"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Bitova po uzorku za Bluetooth audio"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Izaberite Bluetooth audio kodek:\n broj bitova po uzorku"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Režim kanala za Bluetooth audio"</string>
diff --git a/packages/SettingsLib/res/values-be/strings.xml b/packages/SettingsLib/res/values-be/strings.xml
index 0f2df49..40295ea 100644
--- a/packages/SettingsLib/res/values-be/strings.xml
+++ b/packages/SettingsLib/res/values-be/strings.xml
@@ -233,6 +233,7 @@
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Уключыць кодэк Bluetooth Audio\nВыбар"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Частата дыскрэтызацыі Bluetooth Audio"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Уключыць кодэк Bluetooth Audio\nВыбар: частата дыскрэтызацыі"</string>
+    <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Шэрым афарбаваны функцыі, якія не падтрымліваюцца тэлефонам або гарнітурай"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Біты на сэмпл для Bluetooth Audio"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Уключыць кодэк Bluetooth Audio\nВыбар: біты на дыскрэтызацыю"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Канальны рэжым Bluetooth Audio"</string>
diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml
index a3be2812..7b25374 100644
--- a/packages/SettingsLib/res/values-bg/strings.xml
+++ b/packages/SettingsLib/res/values-bg/strings.xml
@@ -233,6 +233,7 @@
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Задействане на аудиокодек за Bluetooth\nИзбор"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Честота на дискретизация за звука през Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Задействане на аудиокодек за Bluetooth\nИзбор: Честота на дискретизация"</string>
+    <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Неактивното състояние означава, че елементът не се поддържа от телефона или слушалките"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Битове на дискрет за звука през Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Задействане на аудиокодек за Bluetooth\nИзбор: Битове на дискрет"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Режим на канала на звука през Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml
index 743de50..c41a3e5 100644
--- a/packages/SettingsLib/res/values-bn/strings.xml
+++ b/packages/SettingsLib/res/values-bn/strings.xml
@@ -233,6 +233,7 @@
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"ব্লুটুথ অডিও কোডেক ট্রিগার করুন\nএটি বেছে নেওয়া আছে"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"ব্লুটুথ অডিওর নমুনা হার"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"ব্লুটুথ অডিও কোডেক ট্রিগার করুন\nএটি বেছে নেওয়া আছে: স্যাম্পল রেট"</string>
+    <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"গ্রে-আউট মানে যেখানে ফোন বা হেডসেট কাজ করে না"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"নমুনা প্রতি ব্লুটুথ অডিও বিট"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"ব্লুটুথ অডিও কোডেক ট্রিগার করুন\nএটি বেছে নেওয়া আছে: বিট্স পার স্যাম্পল"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"ব্লুটুথ অডিও চ্যানেল মোড"</string>
diff --git a/packages/SettingsLib/res/values-bs/strings.xml b/packages/SettingsLib/res/values-bs/strings.xml
index 75a4047..381fe4b 100644
--- a/packages/SettingsLib/res/values-bs/strings.xml
+++ b/packages/SettingsLib/res/values-bs/strings.xml
@@ -233,6 +233,7 @@
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Aktivirajte Bluetooth Audio Codec\nOdabir"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Brzina uzorkovanja za Bluetooth audio"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Aktivirajte Bluetooth Audio Codec\nOdabir: Brzina uzorkovanja"</string>
+    <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Ako je stavka nedostupna, to znači da je telefon ili slušalice ne podržavaju"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Bluetooth audio bitovi po uzorku"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Aktivirajte Bluetooth Audio Codec\nOdabir: Bitovi po uzorku"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Način Bluetooth audio kanala"</string>
diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml
index 8627cf3..3257dc5 100644
--- a/packages/SettingsLib/res/values-ca/strings.xml
+++ b/packages/SettingsLib/res/values-ca/strings.xml
@@ -233,6 +233,7 @@
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Activa el còdec d\'àudio per Bluetooth\nSelecció"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Freqüència de mostratge d’àudio per Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Activa el còdec d\'àudio per Bluetooth\nSelecció: freqüència de mostratge"</string>
+    <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Si una opció està ombrejada, vol dir que el telèfon o els auriculars no l\'admeten"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Bits per mostra de l\'àudio per Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Activa el còdec d\'àudio per Bluetooth\nSelecció: bits per mostra"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Mode de canal de l\'àudio per Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml
index 6fef07a..92ba7d1 100644
--- a/packages/SettingsLib/res/values-cs/strings.xml
+++ b/packages/SettingsLib/res/values-cs/strings.xml
@@ -233,6 +233,7 @@
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Spustit zvukový kodek Bluetooth\nVýběr"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Bluetooth Audio – vzorkovací frekvence"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Spustit zvukový kodek Bluetooth\nVýběr: vzorkovací frekvence"</string>
+    <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Zašedlé možnosti nejsou telefonem nebo náhlavní soupravou podporovány"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Bluetooth Audio – počet bitů na vzorek"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Spustit zvukový kodek Bluetooth\nVýběr: počet bitů na vzorek"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Bluetooth Audio – režim kanálu"</string>
diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml
index 80ee95e..d836b4a 100644
--- a/packages/SettingsLib/res/values-da/strings.xml
+++ b/packages/SettingsLib/res/values-da/strings.xml
@@ -233,6 +233,7 @@
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Udløs codec for Bluetooth-lyd\nValg"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Eksempelfrekvens for Bluetooth-lyd"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Udløs codec for Bluetooth-lyd\nValg: Samplingfrekvens"</string>
+    <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Nedtonede funktioner understøttes ikke af telefonen eller headsettet."</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Bit pr. eksempel for Bluetooth-lyd"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Udløs codec for Bluetooth-lyd\nValg: Bits pr. sampling"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Kanaltilstand for Bluetooth-lyd"</string>
diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml
index 1cd1e55..dff8247 100644
--- a/packages/SettingsLib/res/values-de/strings.xml
+++ b/packages/SettingsLib/res/values-de/strings.xml
@@ -234,6 +234,7 @@
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Bluetooth-Audio-Codec auslösen\nAuswahl"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Bluetooth-Audio-Abtastrate"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Bluetooth-Audio-Codec auslösen\nAuswahl: Abtastrate"</string>
+    <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Wenn etwas ausgegraut ist, wird es nicht vom Smartphone oder Headset unterstützt"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Bluetooth-Audio/Bits pro Sample"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Bluetooth-Audio-Codec auslösen\nAuswahl: Bits pro Sample"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Bluetooth-Audiokanal-Modus"</string>
diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml
index 7dee120..a86d259 100644
--- a/packages/SettingsLib/res/values-el/strings.xml
+++ b/packages/SettingsLib/res/values-el/strings.xml
@@ -233,6 +233,7 @@
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Ενεργοποίηση κωδικοποιητή ήχου Bluetooth\nΕπιλογή"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Ρυθμός δειγματοληψίας ήχου Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Ενεργοποίηση κωδικοποιητή ήχου Bluetooth\nΕπιλογή: Ρυθμός δειγματοληψίας"</string>
+    <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Οι γκριζαρισμένες επιλογές δεν υποστηρίζονται από τηλέφωνο ή ακουστικά"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Bit ανά δείγμα ήχου Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Ενεργοποίηση κωδικοποιητή ήχου Bluetooth\nΕπιλογή: Bit ανά δείγμα"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Λειτουργία καναλιού ήχου Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml
index ba9beb6..cadafce 100644
--- a/packages/SettingsLib/res/values-en-rAU/strings.xml
+++ b/packages/SettingsLib/res/values-en-rAU/strings.xml
@@ -233,6 +233,7 @@
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Trigger Bluetooth Audio Codec\nSelection"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Bluetooth audio sample rate"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Trigger Bluetooth Audio Codec\nSelection: Sample Rate"</string>
+    <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Grey-out means not supported by phone or headset"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Bluetooth audio bits per sample"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Trigger Bluetooth Audio Codec\nSelection: Bits Per Sample"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Bluetooth audio channel mode"</string>
diff --git a/packages/SettingsLib/res/values-en-rCA/strings.xml b/packages/SettingsLib/res/values-en-rCA/strings.xml
index ba9beb6..cadafce 100644
--- a/packages/SettingsLib/res/values-en-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-en-rCA/strings.xml
@@ -233,6 +233,7 @@
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Trigger Bluetooth Audio Codec\nSelection"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Bluetooth audio sample rate"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Trigger Bluetooth Audio Codec\nSelection: Sample Rate"</string>
+    <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Grey-out means not supported by phone or headset"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Bluetooth audio bits per sample"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Trigger Bluetooth Audio Codec\nSelection: Bits Per Sample"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Bluetooth audio channel mode"</string>
diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml
index ba9beb6..cadafce 100644
--- a/packages/SettingsLib/res/values-en-rGB/strings.xml
+++ b/packages/SettingsLib/res/values-en-rGB/strings.xml
@@ -233,6 +233,7 @@
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Trigger Bluetooth Audio Codec\nSelection"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Bluetooth audio sample rate"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Trigger Bluetooth Audio Codec\nSelection: Sample Rate"</string>
+    <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Grey-out means not supported by phone or headset"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Bluetooth audio bits per sample"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Trigger Bluetooth Audio Codec\nSelection: Bits Per Sample"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Bluetooth audio channel mode"</string>
diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml
index ba9beb6..cadafce 100644
--- a/packages/SettingsLib/res/values-en-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-en-rIN/strings.xml
@@ -233,6 +233,7 @@
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Trigger Bluetooth Audio Codec\nSelection"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Bluetooth audio sample rate"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Trigger Bluetooth Audio Codec\nSelection: Sample Rate"</string>
+    <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Grey-out means not supported by phone or headset"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Bluetooth audio bits per sample"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Trigger Bluetooth Audio Codec\nSelection: Bits Per Sample"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Bluetooth audio channel mode"</string>
diff --git a/packages/SettingsLib/res/values-en-rXC/strings.xml b/packages/SettingsLib/res/values-en-rXC/strings.xml
index 0f11774..444dbcb 100644
--- a/packages/SettingsLib/res/values-en-rXC/strings.xml
+++ b/packages/SettingsLib/res/values-en-rXC/strings.xml
@@ -233,6 +233,7 @@
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‏‎‎‎‎‎‏‏‏‎‏‎‏‏‎‎‏‏‏‎‏‎‎‎‎‏‏‎‎‎‏‎‏‎‏‎‎‏‏‏‏‎‎‎‏‏‎‏‎‏‏‏‏‏‎‎‏‎‎‏‎Trigger Bluetooth Audio Codec‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎Selection‎‏‎‎‏‎"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‎‏‏‎‏‎‏‏‏‏‎‏‏‎‎‎‏‏‏‏‎‎‎‎‎‎‎‏‏‎‎‏‏‎‏‎‎‏‏‎‎‏‏‏‎‏‎‎‏‎‎‏‏‎‏‏‏‏‏‏‎Bluetooth Audio Sample Rate‎‏‎‎‏‎"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‎‎‎‏‏‎‎‎‏‏‎‎‏‏‎‏‎‏‎‎‎‏‎‏‏‎‏‏‎‏‏‏‏‎‎‎‎‏‎‎‏‏‎‎‏‏‎‏‎‎‏‏‎‎‎‏‎‏‏‎‎Trigger Bluetooth Audio Codec‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎Selection: Sample Rate‎‏‎‎‏‎"</string>
+    <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‏‎‎‎‎‎‎‎‎‎‎‏‎‎‎‎‎‏‏‎‏‏‏‏‎‏‏‎‏‏‎‎‎‏‏‏‏‏‏‏‎‎‏‏‏‎‎‎‏‏‏‏‎‎‏‏‎‎‏‎‎Gray-out means not supported by phone or headset‎‏‎‎‏‎"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‎‏‏‎‏‏‎‎‏‎‏‎‏‎‎‎‏‏‎‎‎‏‎‎‏‏‎‎‏‏‏‎‏‏‎‏‏‏‏‎‏‎‏‏‎‏‏‏‏‎‏‏‎‎‎‏‎‏‏‎‎Bluetooth Audio Bits Per Sample‎‏‎‎‏‎"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‎‎‏‏‏‏‏‏‏‎‏‏‏‎‏‎‎‏‏‏‏‏‏‏‎‎‏‏‏‎‎‏‎‎‏‏‎‎‎‏‏‏‎‏‎‎‎‏‏‎‏‏‎‎‏‎‏‏‏‏‎Trigger Bluetooth Audio Codec‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎Selection: Bits Per Sample‎‏‎‎‏‎"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‎‏‏‏‎‏‎‎‎‎‏‏‏‎‎‎‏‎‏‏‎‎‎‏‎‎‎‎‏‎‏‏‏‎‎‏‎‏‎‎‏‎‏‏‎‏‎‏‏‏‎‏‏‎‎‏‎‏‏‎‏‏‎Bluetooth Audio Channel Mode‎‏‎‎‏‎"</string>
diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml
index 41c817e..6a6f800 100644
--- a/packages/SettingsLib/res/values-es-rUS/strings.xml
+++ b/packages/SettingsLib/res/values-es-rUS/strings.xml
@@ -233,6 +233,7 @@
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Activar el códec de audio por Bluetooth\nSelección"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Frecuencia de muestreo del audio Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Activar el códec de audio por Bluetooth\nSelección: porcentaje de la muestra"</string>
+    <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Si la opción está inhabilitada, significa que el teléfono o los auriculares no la admiten"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Bits por muestra del audio Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Activar el códec de audio por Bluetooth\nSelección: bits por muestra"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Modo de canal del audio Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml
index 897eaa3..e29773a 100644
--- a/packages/SettingsLib/res/values-es/strings.xml
+++ b/packages/SettingsLib/res/values-es/strings.xml
@@ -233,6 +233,7 @@
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Activar el códec de audio por Bluetooth\nSelección"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Frecuencia de muestreo de audio de Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Activar el códec de audio por Bluetooth\nSelección: frecuencia de muestreo"</string>
+    <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Si una opción aparece atenuada, no es compatible con el teléfono o los auriculares"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Bits por muestra del audio Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Activar el códec de audio por Bluetooth\nSelección: bits por muestra"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Modo de canal de audio de Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-et/strings.xml b/packages/SettingsLib/res/values-et/strings.xml
index 9b94222..f425e1e 100644
--- a/packages/SettingsLib/res/values-et/strings.xml
+++ b/packages/SettingsLib/res/values-et/strings.xml
@@ -233,6 +233,7 @@
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Bluetoothi helikodeki käivitamine\nValik"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Bluetoothi heli diskreetimissagedus"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Bluetoothi helikodeki käivitamine\nValik: diskreetimissagedus"</string>
+    <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Hallilt kuvamine tähendab, et telefon või peakomplekt seda ei toeta"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Bluetoothi heli bitte diskreedi kohta"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Bluetoothi helikodeki käivitamine\nValik: bittide arv diskreedi kohta"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Bluetoothi heli kanalirežiim"</string>
diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml
index b0e4b26..e9810e5 100644
--- a/packages/SettingsLib/res/values-eu/strings.xml
+++ b/packages/SettingsLib/res/values-eu/strings.xml
@@ -233,6 +233,7 @@
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Abiarazi Bluetooth bidezko audio-kodeka\nHautapena"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Bluetooth bidezko audioaren lagin-abiadura"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Abiarazi Bluetooth bidezko audio-kodeka\nHautapena: lagin-abiadura"</string>
+    <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Kolore apalagoz agertzen bada, esan nahi du telefonoak edo entzungailuak ez duela onartzen"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Bluetooth bidezko audioaren lagin bakoitzeko bit kopurua"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Abiarazi Bluetooth bidezko audio-kodeka\nHautapena: lagin bakoitzeko bitak"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Bluetooth bidezko audioaren kanalaren modua"</string>
diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml
index 7298826..2f25ab2 100644
--- a/packages/SettingsLib/res/values-fa/strings.xml
+++ b/packages/SettingsLib/res/values-fa/strings.xml
@@ -233,6 +233,7 @@
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"راه‌اندازی کدک صوتی بلوتوثی\nانتخاب"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"سرعت نمونه بلوتوث صوتی"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"راه‌اندازی کدک صوتی بلوتوثی\nانتخاب: سرعت نمونه"</string>
+    <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"«خاکستری» به این معناست که تلفن یا هدست از آن پشتیبانی نمی‌کند"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"بیت‌های بلوتوث صوتی در هر نمونه"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"راه‌اندازی کدک صوتی بلوتوثی\nانتخاب: تعداد بیت در نمونه"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"حالت کانال بلوتوث‌ صوتی"</string>
diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml
index 6f58f03..a9904af 100644
--- a/packages/SettingsLib/res/values-fi/strings.xml
+++ b/packages/SettingsLib/res/values-fi/strings.xml
@@ -233,6 +233,7 @@
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Käynnistä Bluetooth-äänipakkaus\nValinta"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Bluetooth-ääninäytteen siirtonopeus"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Käynnistä Bluetooth-äänipakkaus\nValinta: esimerkkinopeus"</string>
+    <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Himmennys tarkoittaa, että puhelin tai kuulokemikrofoni ei tue tätä"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Bluetooth-äänen bittiä/näyte-arvo"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Käynnistä Bluetooth-äänipakkaus\nValinta: bittiä/näyte"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Bluetooth-äänen kanavatila"</string>
diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml
index a5526f3..0f1c213 100644
--- a/packages/SettingsLib/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml
@@ -233,6 +233,7 @@
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Déclencher le codec audio Bluetooth\nSélection"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Taux d\'échantillonnage pour l\'audio Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Déclencher le codec audio Bluetooth\nSélection : taux d\'échantillonnage"</string>
+    <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Une option grisée signifie qu\'elle n\'est pas prise en charge par le téléphone ou par les écouteurs"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Bits par échantillon pour l\'audio Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Déclencher le codec audio Bluetooth\nSélection : bits par échantillon"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Mode de canal pour l\'audio Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml
index 069825a..0bfb3c7 100644
--- a/packages/SettingsLib/res/values-fr/strings.xml
+++ b/packages/SettingsLib/res/values-fr/strings.xml
@@ -234,6 +234,7 @@
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Critère pour déclencher la sélection du codec audio\nBluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Taux d\'échantillonnage audio Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Critère de sélection du codec audio\nBluetooth : taux d\'échantillonnage"</string>
+    <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Si le codec est grisé, c\'est qu\'il n\'est pas compatible avec le téléphone ou le casque"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Bits par échantillon pour l\'audio Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Critère de sélection du codec audio\nBluetooth : nombre de bits par échantillon"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Mode de chaîne de l\'audio Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-gl/strings.xml b/packages/SettingsLib/res/values-gl/strings.xml
index eaab027..213d33a 100644
--- a/packages/SettingsLib/res/values-gl/strings.xml
+++ b/packages/SettingsLib/res/values-gl/strings.xml
@@ -233,6 +233,7 @@
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Activar códec de audio por Bluetooth\nSelección"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Taxa de mostra de audio por Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Activar códec de audio por Bluetooth\nSelección: taxa de mostra"</string>
+    <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Os elementos deshabilitados non son compatibles co teléfono ou cos auriculares"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Bits por mostra de audio por Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Activar códec de audio por Bluetooth\nSelección: bits por mostra"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Modo de canle de audio por Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml
index 00fd024..8192d47 100644
--- a/packages/SettingsLib/res/values-gu/strings.xml
+++ b/packages/SettingsLib/res/values-gu/strings.xml
@@ -233,6 +233,7 @@
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"બ્લૂટૂથ ઑડિઓ કોડેક\nપસંદગી ટ્રિગર કરો"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"બ્લૂટૂથ ઑડિઓ નમૂના દર"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"બ્લૂટૂથ ઑડિઓ કોડેક\nપસંદગી ટ્રિગર કરો: નમૂના રેટ"</string>
+    <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"નિષ્ક્રિય હોવાનો અર્થ એ છે કે ફોન અથવા હૅડસેટ દ્વારા સપોર્ટ આપવામાં આવતો નથી"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"નમૂના દીઠ બ્લૂટૂથ ઑડિઓ બિટ"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"બ્લૂટૂથ ઑડિઓ કોડેક\nપસંદગી ટ્રિગર કરો: નમૂના દીઠ બિટ"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"બ્લૂટૂથ ઑડિઓ ચેનલ મોડ"</string>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index 96aec94..207a479 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -233,6 +233,7 @@
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"ब्लूटूथ ऑडियो कोडेक का\nविकल्प चालू करें"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"ब्लूटूथ ऑडियो नमूना दर"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"ब्लूटूथ ऑडियो कोडेक का\nयह विकल्प चालू करें: सैंपल की दर"</string>
+    <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"धूसर किया गया का मतलब है कि फ़ोन या हेडसेट पर काम नहीं करता"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"ब्लूटूथ ऑडियो बिट प्रति नमूना"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"ब्लूटूथ ऑडियो कोडेक का\nयह विकल्प चालू करें: हर सैंपल के लिए बिट की संख्या"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"ब्लूटूथ ऑडियो चैनल मोड"</string>
diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml
index 6df46ca..97a5862 100644
--- a/packages/SettingsLib/res/values-hr/strings.xml
+++ b/packages/SettingsLib/res/values-hr/strings.xml
@@ -233,6 +233,7 @@
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Pokreni odabir kodeka za Bluetooth\nAudio"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Brzina uzorka za Bluetooth Audio"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Pokreni odabir kodeka za Bluetooth\nAudio: brzina uzorkovanja"</string>
+    <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Ako je stavka siva, znači da je telefon ili slušalice ne podržavaju"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Bitovi po uzorku za Bluetooth Audio"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Pokreni odabir kodeka za Bluetooth\nAudio: bitovi po uzorku"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Način kanala za Bluetooth Audio"</string>
diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml
index 6b5b05e..cba6c65 100644
--- a/packages/SettingsLib/res/values-hu/strings.xml
+++ b/packages/SettingsLib/res/values-hu/strings.xml
@@ -233,6 +233,7 @@
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Bluetooth-hangkodek aktiválása\nKiválasztás"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Bluetooth hang – mintavételezési gyakoriság"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Bluetooth-hangkodek aktiválása\nKiválasztás: Mintavételezési gyakoriság"</string>
+    <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"A kiszürkítés azt jelenti, hogy nem támogatja telefon vagy headset"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Bluetooth hang – bit/minta"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Bluetooth-hangkodek aktiválása\nKiválasztás: Bit/minta"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Bluetooth hang – Csatornamód"</string>
diff --git a/packages/SettingsLib/res/values-hy/strings.xml b/packages/SettingsLib/res/values-hy/strings.xml
index c4002b9..a76c960 100644
--- a/packages/SettingsLib/res/values-hy/strings.xml
+++ b/packages/SettingsLib/res/values-hy/strings.xml
@@ -233,6 +233,7 @@
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Գործարկել Bluetooth աուդիո կոդեկը\nԸնտրություն"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Bluetooth աուդիոյի ընդհատավորման հաճախականությունը"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Գործարկել Bluetooth աուդիո կոդեկը\nԸնտրություն՝ ընդհատավորման հաճախականություն"</string>
+    <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Եթե տարրը մոխրագույն է, նշանակում է, որ չի աջակցվում հեռախոսի համ ականջակալի կողմից։"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Bluetooth աուդիո, բիթ / նմուշ"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Գործարկել Bluetooth աուդիո կոդեկը\nԸնտրություն՝ բիթ/նմուշ"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Bluetooth աուդիո կապուղու ռեժիմը"</string>
diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml
index 753f225..0feae4e 100644
--- a/packages/SettingsLib/res/values-in/strings.xml
+++ b/packages/SettingsLib/res/values-in/strings.xml
@@ -233,6 +233,7 @@
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Aktifkan Codec Audio Bluetooth\nPilihan"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Frekuensi Sampel Audio Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Aktifkan Codec Audio Bluetooth\nPilihan: Frekuensi Sampel"</string>
+    <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Berwarna abu-abu artinya tidak didukung oleh ponsel atau headset"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Bit Per Sampel Audio Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Aktifkan Codec Audio Bluetooth\nPilihan: Bit Per Sampel"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Mode Channel Audio Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-is/strings.xml b/packages/SettingsLib/res/values-is/strings.xml
index b1d40bf..d45f433 100644
--- a/packages/SettingsLib/res/values-is/strings.xml
+++ b/packages/SettingsLib/res/values-is/strings.xml
@@ -233,6 +233,7 @@
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Virkja Bluetooth-hljóðkóðara\nVal"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Bluetooth hljóðtökutíðni"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Virkja Bluetooth-hljóðkóðara\nVal: upptökutíðni"</string>
+    <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Óvirkt þýðir að síminn eða höfuðtólin styðja þetta ekki"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Bluetooth hljóðbitar í úrtaki"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Virkja Bluetooth-hljóðkóðara\nVal: bitar í úrtaki"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Hljóðrásarstilling Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml
index 7f2bd3e..fe111fc 100644
--- a/packages/SettingsLib/res/values-it/strings.xml
+++ b/packages/SettingsLib/res/values-it/strings.xml
@@ -233,6 +233,7 @@
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Attiva il codec audio Bluetooth\nSelezione"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Frequenza campionamento audio Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Attiva il codec audio Bluetooth\nSelezione: Frequenza di campionamento"</string>
+    <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Se il codec non è selezionabile significa che non è supportato dal telefono o dalle cuffie"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Bit per campione dell\'audio Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Attiva il codec audio Bluetooth\nSelezione: bit per campione"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Modalità canale audio Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml
index bdd1bab..8b47c54 100644
--- a/packages/SettingsLib/res/values-iw/strings.xml
+++ b/packages/SettingsLib/res/values-iw/strings.xml
@@ -233,6 +233,7 @@
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"‏הפעלת ‏Codec אודיו ל-Bluetooth\nבחירה"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"‏קצב דגימה של אודיו ל-Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"‏הפעלת ‏Codec אודיו ל-Bluetooth\nבחירה: קצב דגימה"</string>
+    <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"כשזה מופיע באפור, אין לזה תמיכה בטלפון או באוזניות"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"‏מספר סיביות לדגימה באודיו ל-Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"‏הפעלת ‏Codec אודיו ל-Bluetooth\nבחירה: סיביות לדגימה"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"‏מצב של ערוץ אודיו ל-Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml
index a6192a4..c955a39 100644
--- a/packages/SettingsLib/res/values-ja/strings.xml
+++ b/packages/SettingsLib/res/values-ja/strings.xml
@@ -233,6 +233,7 @@
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Bluetooth オーディオ コーデックを起動\n選択"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Bluetooth オーディオ サンプルレート"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Bluetooth オーディオ コーデックを起動\n選択: サンプルレート"</string>
+    <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"グレー表示のコーデックは、スマートフォンまたはヘッドセットが対応していません"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"サンプルあたりの Bluetooth オーディオ ビット"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Bluetooth オーディオ コーデックを起動\n選択: サンプルあたりのビット数"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Bluetooth オーディオ チャンネル モード"</string>
diff --git a/packages/SettingsLib/res/values-ka/strings.xml b/packages/SettingsLib/res/values-ka/strings.xml
index a3633f6..d8fda4b 100644
--- a/packages/SettingsLib/res/values-ka/strings.xml
+++ b/packages/SettingsLib/res/values-ka/strings.xml
@@ -233,6 +233,7 @@
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Bluetooth-ის აუდიო კოდეკის გაშვება\nარჩევანი"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Bluetooth აუდიოს დისკრეტიზაციის სიხშირე"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Bluetooth-ის აუდიო კოდეკის გაშვება\nარჩევანი: ნიმუშთა მაჩვენებელი"</string>
+    <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"არააქტიური ნიშნავს, რომ ტელეფონის ან ყურსასმენის მიერ მხარდაჭერილი არ არის"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Bluetooth აუდიოს ბიტების რაოდენობა ნიმუშზე"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Bluetooth-ის აუდიო კოდეკის გაშვება\nარჩევანი: ბიტები ნიმუშზე"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Bluetooth აუდიოს არხის რეჟიმი"</string>
diff --git a/packages/SettingsLib/res/values-kk/strings.xml b/packages/SettingsLib/res/values-kk/strings.xml
index 0962e55..025532d 100644
--- a/packages/SettingsLib/res/values-kk/strings.xml
+++ b/packages/SettingsLib/res/values-kk/strings.xml
@@ -233,6 +233,7 @@
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Bluetooth аудиокодегін іске қосу\nТаңдау"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Bluetooth арқылы дыбыс іріктеу жиілігі"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Bluetooth аудиокодегін іске қосу\nТаңдау: іріктеу жылдамдығы"</string>
+    <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Сұр түсті болса, бұл оған телефонда не гарнитурада қолдау көрсетілмейтінін білдіреді."</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Bluetooth арқылы дыбыстың разрядтылық мөлшері"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Bluetooth аудиокодегін іске қосу\nТаңдау: разрядтылық"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Bluetooth дыбыстық арна режимі"</string>
diff --git a/packages/SettingsLib/res/values-km/strings.xml b/packages/SettingsLib/res/values-km/strings.xml
index 45620e8..e9f5ab0 100644
--- a/packages/SettingsLib/res/values-km/strings.xml
+++ b/packages/SettingsLib/res/values-km/strings.xml
@@ -233,6 +233,7 @@
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"ជំរុញ​ការជ្រើសរើស​កូឌិក​សំឡេង​\n​ប៊្លូធូស"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"អត្រា​គំរូ​សំឡេង​ប៊្លូធូស"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"ជំរុញ​ការជ្រើសរើស​កូឌិក​សំឡេង\n​ប៊្លូធូស​៖ អត្រា​គំរូ"</string>
+    <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"ការកំណត់ជា​ពណ៌ប្រផេះ​មានន័យថា​ទូរសព្ទ ឬ​កាស​មិនស្គាល់ទេ"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"កម្រិត​ប៊ីត​ក្នុង​មួយ​គំរូ​នៃ​សំឡេង​ប៊្លូធូស"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"ជំរុញ​ការជ្រើសរើស​កូឌិក​សំឡេង​\nប៊្លូធូស៖ កម្រិត​ប៊ីត​ក្នុង​មួយ​គំរូ"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"មុខ​ងារ​រលកសញ្ញា​សំឡេង​ប៊្លូធូស"</string>
diff --git a/packages/SettingsLib/res/values-kn/strings.xml b/packages/SettingsLib/res/values-kn/strings.xml
index 1fc2e4a..4feccaf 100644
--- a/packages/SettingsLib/res/values-kn/strings.xml
+++ b/packages/SettingsLib/res/values-kn/strings.xml
@@ -233,6 +233,7 @@
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"ಬ್ಲೂಟೂತ್ ಆಡಿಯೋ ಕೋಡೆಕ್ ಅನ್ನು ಟ್ರಿಗ್ಗರ್ ಮಾಡಿ\nಆಯ್ಕೆ"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"ಬ್ಲೂಟೂತ್ ಆಡಿಯೋ ಮಾದರಿ ದರ"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"ಬ್ಲೂಟೂತ್ ಆಡಿಯೋ ಕೋಡೆಕ್ ಅನ್ನು ಟ್ರಿಗ್ಗರ್ ಮಾಡಿ\nಆಯ್ಕೆ: ಮಾದರಿ ರೇಟ್"</string>
+    <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"ಬೂದುಬಣ್ಣಕ್ಕೆ ತಿರುಗುವುದು ಎಂದರೆ ಫೋನ್ ಅಥವಾ ಹೆಡ್‌ಸೆಟ್ ಬೆಂಬಲಿಸುವುದಿಲ್ಲ ಎಂದರ್ಥ"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"ಬ್ಲೂಟೂತ್‌ ಆಡಿಯೊ ಬಿಟ್ಸ್‌‌ನ ಪ್ರತಿ ಮಾದರಿ"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"ಬ್ಲೂಟೂತ್ ಆಡಿಯೋ ಕೋಡೆಕ್ ಅನ್ನು ಟ್ರಿಗ್ಗರ್ ಮಾಡಿ \nಆಯ್ಕೆ: ಬಿಟ್ಸ್‌‌ನ ಪ್ರತಿ ಮಾದರಿ"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"ಬ್ಲೂಟೂತ್ ಆಡಿಯೋ ಚಾನೆಲ್ ಮೋಡ್"</string>
diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml
index 8e7c697..4707ef8 100644
--- a/packages/SettingsLib/res/values-ko/strings.xml
+++ b/packages/SettingsLib/res/values-ko/strings.xml
@@ -233,6 +233,7 @@
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"블루투스 오디오 코덱 실행\n선택"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"블루투스 오디오 샘플링 비율"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"블루투스 오디오 코덱 실행\n선택: 샘플링 비율"</string>
+    <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"비활성화되어 있으면 스마트폰 또는 헤드셋에서 지원하지 않음을 의미함"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"블루투스 오디오 샘플당 비트"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"블루투스 오디오 코덱 실행\n선택: 샘플당 비트"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"블루투스 오디오 채널 모드"</string>
diff --git a/packages/SettingsLib/res/values-ky/strings.xml b/packages/SettingsLib/res/values-ky/strings.xml
index 18a1468..2197a9f 100644
--- a/packages/SettingsLib/res/values-ky/strings.xml
+++ b/packages/SettingsLib/res/values-ky/strings.xml
@@ -233,6 +233,7 @@
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Bluetooth Audio кодегин иштетүү\nТандоо"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Bluetooth аудио үлгүсүнүн ылдамдыгы"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Bluetooth Audio кодегин иштетүү\nТандоо: Үлгү жыштыгы"</string>
+    <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Боз түс менен белгиленген кодек – бул телефондо же гарнитурада колдоого алынбайт дегенди билдирет"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Бир үлгүдөгү Bluetooth аудио биттери"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Bluetooth Audio кодегин иштетүү\nТандоо: Бир үлгүдөгү биттер"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Bluetooth аудио каналынын режими"</string>
diff --git a/packages/SettingsLib/res/values-lo/strings.xml b/packages/SettingsLib/res/values-lo/strings.xml
index 808d5a7..de3f644 100644
--- a/packages/SettingsLib/res/values-lo/strings.xml
+++ b/packages/SettingsLib/res/values-lo/strings.xml
@@ -233,6 +233,7 @@
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"ເປີດໃຊ້ Bluetooth Audio Codec\nການເລືອກ"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Bluetooth Audio Sample Rate"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"ເປີດໃຊ້ Bluetooth Audio Codec\nການເລືອກ: Sample Rate"</string>
+    <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"ສ່ວນທີ່ເປັນສີເທົາໝາຍຄວາມວ່າບໍ່ຮອງຮັບໂດຍໂທລະສັບ ຫຼື ຊຸດຫູຟັງ"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Bluetooth Audio Bits Per Sample"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"ເປີດໃຊ້ Bluetooth Audio Codec\nການເລືອກ: Bits Per Sample"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"ໂໝດຊ່ອງສຽງ Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml
index 78d1b1b..6157a87 100644
--- a/packages/SettingsLib/res/values-lt/strings.xml
+++ b/packages/SettingsLib/res/values-lt/strings.xml
@@ -233,6 +233,7 @@
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Suaktyvinti „Bluetooth“ garso kodeką\nPasirinkimas"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"„Bluetooth“ garso pavyzdžio dažnis"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Suaktyvinti „Bluetooth“ garso kodeką\nPasirinkimas: pavyzdžio dažnis"</string>
+    <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Pilka spalva reiškia, kad telefonas arba ausinės nepalaiko tos funkcijos"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"„Bluetooth“ garso įrašo bitų skaičius pavyzdyje"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Suaktyvinti „Bluetooth“ garso kodeką\nPasirinkimas: bitų skaičius pavyzdyje"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"„Bluetooth“ garso kanalo režimas"</string>
diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml
index 0ae10aa..51b909c 100644
--- a/packages/SettingsLib/res/values-lv/strings.xml
+++ b/packages/SettingsLib/res/values-lv/strings.xml
@@ -233,6 +233,7 @@
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Aktivizēt Bluetooth audio kodeku\nAtlase"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Bluetooth audio iztveršanas ātrums"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Aktivizēt Bluetooth audio kodeku\nAtlase: iztveršanas ātrums"</string>
+    <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Ja vienums ir pelēkots, tas netiek atbalstīts tālrunī vai austiņās."</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Bluetooth audio bitu skaits iztvērumā"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Aktivizēt Bluetooth audio kodeku\nAtlase: bitu skaitu iztvērumā"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Bluetooth audio kanāla režīms"</string>
diff --git a/packages/SettingsLib/res/values-mk/strings.xml b/packages/SettingsLib/res/values-mk/strings.xml
index 9850ac5..9a0d2da 100644
--- a/packages/SettingsLib/res/values-mk/strings.xml
+++ b/packages/SettingsLib/res/values-mk/strings.xml
@@ -233,6 +233,7 @@
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Вклучете го аудио кодекот преку Bluetooth\nСелекција"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Стапка на семпл преку Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Вклучете го аудио кодекот преку Bluetooth\nСелекција: стапка на примерокот"</string>
+    <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Ако е сиво, значи дека не е поддржано од телефонот или од слушалките"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Аудио бит-по-семпл преку Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Вклучете го аудио кодекот преку Bluetooth\nСелекција: бит-по-семпл"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Режим на канал за аудио преку Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-ml/strings.xml b/packages/SettingsLib/res/values-ml/strings.xml
index 2692a30..e9558fc 100644
--- a/packages/SettingsLib/res/values-ml/strings.xml
+++ b/packages/SettingsLib/res/values-ml/strings.xml
@@ -233,6 +233,7 @@
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Bluetooth Audio Codec\nSelection ട്രിഗ്ഗര്‍ ചെയ്യുക"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Bluetooth ഓഡിയോ സാമ്പിൾ നിരക്ക്"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Bluetooth Audio Codec\nSelection ട്രിഗ്ഗര്‍ ചെയ്യുക: സാമ്പിൾ റേറ്റ്"</string>
+    <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"ചാരനിറത്തിലാക്കിയിട്ടുണ്ടെങ്കിൽ, ഫോണോ ഹെഡ്‌സെറ്റോ പിന്തുണയ്ക്കുന്നില്ലെന്നാണ് അർത്ഥം"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"പ്രതി സാമ്പിളിലെ Bluetooth ഓഡിയോ ബിറ്റ് നി"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Bluetooth Audio Codec\nSelection ട്രിഗ്ഗര്‍ ചെയ്യുക: ഓരോ സാമ്പിളിനുള്ള ബിറ്റുകൾ"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Bluetooth ഓഡിയോ ചാനൽ മോഡ്"</string>
diff --git a/packages/SettingsLib/res/values-mn/strings.xml b/packages/SettingsLib/res/values-mn/strings.xml
index aa4ec76..4997f0b 100644
--- a/packages/SettingsLib/res/values-mn/strings.xml
+++ b/packages/SettingsLib/res/values-mn/strings.xml
@@ -233,6 +233,7 @@
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Bluetooth-н аудио кодлогчийг өдөөх\nСонголт"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Bluetooth аудио жишээний үнэлгээ"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Bluetooth-н аудио кодлогчийг өдөөх\nСонголт: Жишээ үнэлгээ"</string>
+    <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Идэвхгүй саарал байх нь утас эсвэл чихэвч дэмждэггүй болохыг илтгэнэ"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Жишээ тутмын Bluetooth аудионы бит"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Bluetooth-н аудио кодлогчийг өдөөх\nСонголт: Жишээ бүрийн бит"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Bluetooth аудио сувгийн горим"</string>
diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml
index 966cdff..1dbd592 100644
--- a/packages/SettingsLib/res/values-mr/strings.xml
+++ b/packages/SettingsLib/res/values-mr/strings.xml
@@ -233,6 +233,7 @@
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"ब्लूटूथ ऑडिओ Codec ट्रिगर करा\nनिवड"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"ब्लूटूथ ऑडिओ पॅटर्न दर"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"ब्लूटूथ ऑडिओ Codec ट्रिगर करा\nनिवड: नमुना दर"</string>
+    <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"फोन किंवा हेडसेटला सपोर्ट करत नाही म्हणजे ती निकामी झाली आहे"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"प्रति पॅटर्न ब्लूटूध ऑडिओ बिट"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"ब्लूटूथ ऑडिओ Codec ट्रिगर करा\nनिवड: बिट प्रति नमुना"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"ब्लूटूथ ऑडिओ चॅनेल मोड"</string>
diff --git a/packages/SettingsLib/res/values-ms/strings.xml b/packages/SettingsLib/res/values-ms/strings.xml
index 88d7c7d..790480d 100644
--- a/packages/SettingsLib/res/values-ms/strings.xml
+++ b/packages/SettingsLib/res/values-ms/strings.xml
@@ -233,6 +233,7 @@
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Cetuskan Codec Audio Bluetooth\nPilihan"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Kadar Sampel Audio Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Cetuskan Codec Audio Bluetooth\nPilihan: Kadar Sampel"</string>
+    <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Bahagian yang dikelabukan bermaksud tidak disokong oleh telefon atau set kepala"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Bit Per Sampel Audio Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Cetuskan Codec Audio Bluetooth\nPilihan: Bit Per Sampel"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Mod Saluran Audio Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-my/strings.xml b/packages/SettingsLib/res/values-my/strings.xml
index 6dfd290..dc81d05 100644
--- a/packages/SettingsLib/res/values-my/strings.xml
+++ b/packages/SettingsLib/res/values-my/strings.xml
@@ -233,6 +233,7 @@
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"ဘလူးတုသ် အသံ LDAC ကိုးဒက်ခ် ဖွင့်ခြင်း\nရွေးချယ်မှု"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"ဘလူးတုသ်အသံနမူနာနှုန်း"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"ဘလူးတုသ် အသံ ကိုးဒက်ခ် ဖွင့်ခြင်း\nရွေးချယ်မှု- နမူနာနှုန်း"</string>
+    <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"မီးခိုးရောင် ခြယ်ထားခြင်းသည် ဖုန်း သို့မဟုတ် မိုက်ခွက်ပါနားကြပ်မှ ပံ့ပိုးထားမှုမရှိခြင်းကို ဆိုလိုသည်။"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"နမူနာတစ်ခုစီတွင် ပါဝင်သော ဘလူးတုသ်အသံပမာဏ Bits"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"ဘလူးတုသ် အသံ ကိုးဒက်ခ် ဖွင့်ခြင်း\nရွေးချယ်မှု- နမူနာတစ်ခုစီအတွက် Bits"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"ဘလူးတုသ်အသံချန်နယ်မုဒ်"</string>
diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml
index 760c409..d0e4966 100644
--- a/packages/SettingsLib/res/values-nb/strings.xml
+++ b/packages/SettingsLib/res/values-nb/strings.xml
@@ -233,6 +233,7 @@
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Utløs kodek for Bluetooth-lyd\nValg"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Samplefrekvens for Bluetooth-lyd"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Utløs kodek for Bluetooth-lyd\nValg: samplefrekvens"</string>
+    <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Hvis den er nedtonet, støttes den ikke av telefonen eller hodetelefonene"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Bits per sample for Bluetooth-lyd"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Utløs kodek for Bluetooth-lyd\nValg: bits per sample"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Kanalmodus for Bluetooth-lyd"</string>
diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml
index 77f87ff..d8ed4cb 100644
--- a/packages/SettingsLib/res/values-ne/strings.xml
+++ b/packages/SettingsLib/res/values-ne/strings.xml
@@ -233,6 +233,7 @@
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"ब्लुटुथ अडियो कोडेक ट्रिगर गर्नुहोस्\nचयन"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"ब्लुटुथ अडियोको नमूना दर"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"ब्लुटुथ अडियो कोडेक ट्रिगर गर्नुहोस्\nचयन: नमुना दर"</string>
+    <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"खरानी रङले भरिएको भन्नाले फोन वा हेडसेटले समर्थन नगरेको बुझाउँछ"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"प्रति नमूना ब्लुटुथ अडियोका बिटहरू"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"ब्लुटुथ अडियो कोडेक ट्रिगर गर्नुहोस्\nचयन: बिट प्रति नमुना"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"ब्लुटुथ अडियो च्यानलको मोड"</string>
diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml
index 55f56d9..d5ce540 100644
--- a/packages/SettingsLib/res/values-nl/strings.xml
+++ b/packages/SettingsLib/res/values-nl/strings.xml
@@ -233,6 +233,7 @@
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Codec voor Bluetooth-audio activeren\nSelectie"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Sample rate van Bluetooth-audio"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Codec voor Bluetooth-audio activeren\nSelectie: Bemonsteringsfrequentie"</string>
+    <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Uitgegrijsd betekent niet ondersteund door telefoon of headset"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Bits per sample voor Bluetooth-audio"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Codec voor Bluetooth-audio activeren\nSelectie: Bits per sample"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Kanaalmodus voor Bluetooth-audio"</string>
diff --git a/packages/SettingsLib/res/values-or/strings.xml b/packages/SettingsLib/res/values-or/strings.xml
index 98c302d..024bd3c 100644
--- a/packages/SettingsLib/res/values-or/strings.xml
+++ b/packages/SettingsLib/res/values-or/strings.xml
@@ -233,6 +233,7 @@
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"ବ୍ଲୁଟୂଥ୍‍ ଅଡିଓ କୋଡେକ୍\nସିଲେକ୍ସନ୍‌କୁ ଗତିଶୀଳ କରନ୍ତୁ"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"ବ୍ଲୁଟୂଥ୍‌ ଅଡିଓ ସାମ୍ପଲ୍‌ ରେଟ୍‌"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"ବ୍ଲୁଟୂଥ୍‍ ଅଡିଓ କୋଡେକ୍\nସିଲେକ୍ସନ୍‌କୁ ଗତିଶୀଳ କରନ୍ତୁ: ସାମ୍ପଲ୍ ରେଟ୍"</string>
+    <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"ଗ୍ରେ-ଆଉଟ୍ ଅର୍ଥ ଫୋନ୍ କିମ୍ବା ହେଡ୍‌ସେଟ୍‌ରେ ସମର୍ଥନ କରୁନାହିଁ"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"ନମୁନା ପିଛା ବ୍ଲୁଟୂଥ୍‍‌ ଅଡିଓ ବିଟ୍ସ"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"ବ୍ଲୁଟୂଥ୍‍ ଅଡିଓ କୋଡେକ୍\nସିଲେକ୍ସନ୍‌କୁ ଗତିଶୀଳ କରନ୍ତୁ: ନମୁନା ପିଛା ବିଟ୍ସ"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"ବ୍ଲୁଟୂଥ୍‍‌ ଅଡିଓ ଚ୍ୟାନେଲ୍‌ ମୋଡ୍"</string>
diff --git a/packages/SettingsLib/res/values-pa/strings.xml b/packages/SettingsLib/res/values-pa/strings.xml
index 525ad2e..042bbf7 100644
--- a/packages/SettingsLib/res/values-pa/strings.xml
+++ b/packages/SettingsLib/res/values-pa/strings.xml
@@ -233,6 +233,7 @@
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"ਬਲੂਟੁੱਥ ਆਡੀਓ ਕੋਡੇਕ\nਚੋਣ ਨੂੰ ਟ੍ਰਿਗਰ ਕਰੋ"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"ਬਲੂਟੁੱਥ ਆਡੀਓ ਸੈਂਪਲ ਰੇਟ"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"ਬਲੂਟੁੱਥ ਆਡੀਓ ਕੋਡੇਕ\nਚੋਣ ਨੂੰ ਟ੍ਰਿਗਰ ਕਰੋ: ਸੈਂਪਲ ਰੇਟ"</string>
+    <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"ਅਯੋਗ ਦਾ ਮਤਲਬ ਹੈ ਫ਼ੋਨ ਜਾਂ ਹੈੱਡਸੈੱਟ ਵੱਲੋਂ ਸਮਰਥਿਤ ਨਹੀਂ ਹੈ"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"ਪ੍ਰਤੀ ਸੈਂਪਲ ਬਲੂਟੁੱਥ ਆਡੀਓ ਬਿਟਾਂ"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"ਬਲੂਟੁੱਥ ਆਡੀਓ ਕੋਡੇਕ\nਚੋਣ ਨੂੰ ਟ੍ਰਿਗਰ ਕਰੋ: ਪ੍ਰਤੀ ਸੈਂਪਲ ਬਿਟਾਂ"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"ਬਲੂਟੁੱਥ ਆਡੀਓ ਚੈਨਲ ਮੋਡ"</string>
diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml
index 69ebc59..7856679 100644
--- a/packages/SettingsLib/res/values-pl/strings.xml
+++ b/packages/SettingsLib/res/values-pl/strings.xml
@@ -233,6 +233,7 @@
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Uruchom kodek dźwięku Bluetooth\nWybór"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Dźwięk Bluetooth – współczynnik próbkowania"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Uruchom kodek dźwięku Bluetooth\nWybór: częstotliwość próbkowania"</string>
+    <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Elementy wyszarzone nie są obsługiwane przez telefon lub zestaw słuchawkowy"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Dźwięk Bluetooth – liczba bitów na próbkę"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Uruchom kodek dźwięku Bluetooth\nWybór: liczba bitów na próbkę"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Dźwięk Bluetooth – tryb kanału"</string>
diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml
index 62017f1..6a32200 100644
--- a/packages/SettingsLib/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml
@@ -233,6 +233,7 @@
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Acionar codec de áudio Bluetooth\nSeleção"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Taxa de amostra do áudio Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Acionar codec de áudio Bluetooth\nSeleção: taxa de amostra"</string>
+    <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Os itens esmaecidos não são compatíveis com o smartphone ou o fone de ouvido"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Bits por amostra do áudio Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Acionar codec de áudio Bluetooth\nSeleção: bits por amostra"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Modo de canal de áudio Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml
index 8304768..caf1ba4 100644
--- a/packages/SettingsLib/res/values-pt-rPT/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml
@@ -233,6 +233,7 @@
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Acionar o codec de áudio Bluetooth\nSeleção"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Taxa de amostragem de áudio Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Acionar o codec de áudio Bluetooth\nSeleção: frequência de amostragem"</string>
+    <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Se estiver assinalado a cinzento, significa que não é suportado pelo telemóvel ou pelos auscultadores com microfone integrado"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Bits por amostra de áudio Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Acionar o codec de áudio Bluetooth\nSeleção: bits por amostra"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Modo de canal áudio Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml
index 62017f1..6a32200 100644
--- a/packages/SettingsLib/res/values-pt/strings.xml
+++ b/packages/SettingsLib/res/values-pt/strings.xml
@@ -233,6 +233,7 @@
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Acionar codec de áudio Bluetooth\nSeleção"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Taxa de amostra do áudio Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Acionar codec de áudio Bluetooth\nSeleção: taxa de amostra"</string>
+    <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Os itens esmaecidos não são compatíveis com o smartphone ou o fone de ouvido"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Bits por amostra do áudio Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Acionar codec de áudio Bluetooth\nSeleção: bits por amostra"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Modo de canal de áudio Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml
index 50ea4a0..38cd60f 100644
--- a/packages/SettingsLib/res/values-ro/strings.xml
+++ b/packages/SettingsLib/res/values-ro/strings.xml
@@ -233,6 +233,7 @@
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Declanșați codecul audio Bluetooth\nSelecție"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Rată de eșantionare audio Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Declanșați codecul audio Bluetooth\nSelecție: rată de eșantionare"</string>
+    <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"O opțiune inactivă înseamnă incompatibilitate cu telefonul sau setul căști-microfon"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Biți audio Bluetooth per eșantion"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Declanșați codecul audio Bluetooth\nSelecție: biți per eșantion"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Modul canal audio Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml
index 0582a0c..124bf13 100644
--- a/packages/SettingsLib/res/values-ru/strings.xml
+++ b/packages/SettingsLib/res/values-ru/strings.xml
@@ -233,6 +233,7 @@
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Запустить аудиокодек для Bluetooth\nВыбор"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Частота дискретизации аудио Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Запустить аудиокодек для Bluetooth\nВыбор: частота дискретизации"</string>
+    <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Серым окрашены неподдерживаемые функции"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Бит на выборку аудио Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Запустить аудиокодек для Bluetooth\nВыбор: разрядность"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Режим аудиоканала Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-si/strings.xml b/packages/SettingsLib/res/values-si/strings.xml
index 43a4978..d5fbb6b 100644
--- a/packages/SettingsLib/res/values-si/strings.xml
+++ b/packages/SettingsLib/res/values-si/strings.xml
@@ -233,6 +233,7 @@
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"බ්ලූටූත් ශ්‍රව්‍ය කෝඩෙක් ක්‍රියාරම්භ කරන්න\nතෝරා ගැනීම"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"බ්ලූටූත් ශ්‍රව්‍ය නියැදි අනුපාතය"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"බ්ලූටූත් ශ්‍රව්‍ය කෝඩෙක් ක්‍රියාරම්භ කරන්න\nතෝරා ගැනීම: නියැදි අනුපාතය"</string>
+    <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"අළු පැහැ ගැන්වී ඇත යන්නෙන් අදහස් කරන්නේ දුරකථනය හෝ හෙඩ්සෙට් එක මගින් සහාය නොදක්වන බවයි"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"නියැදියකට බ්ලූටූත් ශ්‍රව්‍ය බිටු"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"බ්ලූටූත් ශ්‍රව්‍ය කේතය ක්‍රියාරම්භ කරන්න\nතෝරා ගැනීම: නියැදි සඳහා බිටු"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"බ්ලූටූත් ශ්‍රව්‍ය නාලිකා ප්‍රකාරය"</string>
diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml
index 3a3958f..ba13586 100644
--- a/packages/SettingsLib/res/values-sk/strings.xml
+++ b/packages/SettingsLib/res/values-sk/strings.xml
@@ -233,6 +233,7 @@
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Spustiť zvukový kodek Bluetooth\nVýber"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Bluetooth Audio – vzorkovacia frekvencia"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Spustiť zvukový kodek Bluetooth\nVýber: vzorkovacia frekvencia"</string>
+    <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Sivé možnosti nie sú podporované telefónom ani náhlavnou súpravou"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Bluetooth Audio – počet bitov na vzorku"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Spustiť zvukový kodek Bluetooth\nVýber: počet bitov na vzorku"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Bluetooth Audio – režim kanála"</string>
diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml
index 068f221..90d7829 100644
--- a/packages/SettingsLib/res/values-sl/strings.xml
+++ b/packages/SettingsLib/res/values-sl/strings.xml
@@ -233,6 +233,7 @@
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Sproži zvočni kodek za Bluetooth\nIzbor"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Hitrost vzorčenja zvoka prek Bluetootha"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Sproži zvočni kodek za Bluetooth\nIzbor: hitrost vzorčenja"</string>
+    <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Če je možnost zatemnjena, to pomeni, da je telefon ali slušalke z mikrofonom ne podpirajo"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Bitov na vzorec za zvok prek Bluetootha"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Sproži zvočni kodek za Bluetooth\nIzbor: število bitov na vzorec"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Način zvočnega kanala prek Bluetootha"</string>
diff --git a/packages/SettingsLib/res/values-sq/strings.xml b/packages/SettingsLib/res/values-sq/strings.xml
index 54d4637..15b2ed3 100644
--- a/packages/SettingsLib/res/values-sq/strings.xml
+++ b/packages/SettingsLib/res/values-sq/strings.xml
@@ -233,6 +233,7 @@
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Aktivizo kodekun e audios me Bluetooth\nZgjedhja"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Shpejtësia e shembullit të Bluetooth Audio"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Aktivizo kodekun e audios me Bluetooth\nZgjedhja: Shpejtësia e shembullit"</string>
+    <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Çaktivizimi do të thotë se nuk mbështetet nga telefoni ose kufjet"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Bite për shembull Bluetooth Audio"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Aktivizo kodekun e audios me Bluetooth\nZgjedhja: Bite për shembull"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Regjimi i kanalit Bluetooth Audio"</string>
diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml
index ab081ae..381edef 100644
--- a/packages/SettingsLib/res/values-sr/strings.xml
+++ b/packages/SettingsLib/res/values-sr/strings.xml
@@ -233,6 +233,7 @@
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Изаберите Bluetooth аудио кодек\n"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Брзина узорковања за Bluetooth аудио"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Изаберите Bluetooth аудио кодек:\n брзина узорковања"</string>
+    <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Ако је нека ставка засивљена, то значи да је телефон или слушалице не подржавају"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Битова по узорку за Bluetooth аудио"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Изаберите Bluetooth аудио кодек:\n број битова по узорку"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Режим канала за Bluetooth аудио"</string>
diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml
index cab971f..65fbe20 100644
--- a/packages/SettingsLib/res/values-sv/strings.xml
+++ b/packages/SettingsLib/res/values-sv/strings.xml
@@ -233,6 +233,7 @@
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Aktivera ljudkodek för Bluetooth\nVal"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Samplingsfrekvens för Bluetooth-ljud"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Aktivera ljudkodek för Bluetooth\nVal: samplingsfrekvens"</string>
+    <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"En nedtonad kodek stöds inte av telefonen eller headsetet"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Antar bitar per sampling för Bluetooth-ljud"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Aktivera ljudkodek för Bluetooth\nVal: bitar per sampling"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Kanalläge för Bluetooth-ljud"</string>
diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml
index df71b82..e6ccc65 100644
--- a/packages/SettingsLib/res/values-sw/strings.xml
+++ b/packages/SettingsLib/res/values-sw/strings.xml
@@ -233,6 +233,7 @@
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Weka Kodeki ya Sauti ya Bluetooth\nUteuzi"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Kiwango cha Sampuli ya Sauti ya Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Weka Kodeki ya Sauti ya Bluetooth\nUteuzi: Kasi ya Sampuli"</string>
+    <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Kipengele cha Haiwezi kutumiwa kina maana kuwa hakitumiki kwenye simu au vifaa vya sauti"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Biti za Sauti ya Bluetooth kwa Kila Sampuli"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Weka Kodeki ya Sauti ya Bluetooth\nUteuzi: Biti Kwa Kila Sampuli"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Hali ya Mkondo wa Sauti ya Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-ta/strings.xml b/packages/SettingsLib/res/values-ta/strings.xml
index 084ec16..f0f4bef 100644
--- a/packages/SettingsLib/res/values-ta/strings.xml
+++ b/packages/SettingsLib/res/values-ta/strings.xml
@@ -233,6 +233,7 @@
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"புளூடூத் ஆடியோ கோடெக்கைத் தொடங்கு\nதேர்வு"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"புளூடூத் ஆடியோ சாம்பிள் ரேட்"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"புளூடூத் ஆடியோ கோடெக்கைத் தொடங்கு\nதேர்வு: சாம்பிள் ரேட்"</string>
+    <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"கிரே-அவுட் என்றால் மொபைலாலோ ஹெட்செட்டாலோ ஆதரிக்கப்படவில்லை என்று அர்த்தம்"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"புளூடூத் ஆடியோ பிட்கள்/சாம்பிள்"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"புளூடூத் ஆடியோ கோடெக்கைத் தொடங்கு\nதேர்வு: பிட்கள் / சாம்பிள்"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"புளூடூத் ஆடியோ சேனல் பயன்முறை"</string>
diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml
index cbcaf1a..cf5097e 100644
--- a/packages/SettingsLib/res/values-te/strings.xml
+++ b/packages/SettingsLib/res/values-te/strings.xml
@@ -233,6 +233,7 @@
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"బ్లూటూత్ ఆడియో కోడెక్‌ని సక్రియం చేయండి\nఎంపిక"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"బ్లూటూత్ ఆడియో నమూనా రేట్"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"బ్లూటూత్ ఆడియో కోడెక్‌ని సక్రియం చేయండి\nఎంపిక: నమూనా రేట్"</string>
+    <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"గ్రే-అవుట్ అంటే ఫోన్ లేదా హెడ్‌సెట్ మద్దతు లేదు అని అర్ధం"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"ఒక్కో నమూనాకు బ్లూటూత్ ఆడియో బిట్‌లు"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"బ్లూటూత్ ఆడియో కోడెక్‌ని సక్రియం చేయండి\nఎంపిక: ఒక్కో నమూనాలో బిట్‌లు"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"బ్లూటూత్ ఆడియో ఛానెల్ మోడ్"</string>
diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml
index fa8caa1..145e161 100644
--- a/packages/SettingsLib/res/values-th/strings.xml
+++ b/packages/SettingsLib/res/values-th/strings.xml
@@ -233,6 +233,7 @@
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"ทริกเกอร์การเลือกตัวแปลงรหัส\nเสียงบลูทูธ"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"อัตราตัวอย่างเสียงบลูทูธ"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"ทริกเกอร์การเลือกตัวแปลงรหัส\nเสียงบลูทูธ: อัตราตัวอย่าง"</string>
+    <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"เป็นสีเทาหมายความว่าโทรศัพท์หรือชุดหูฟังไม่รองรับ"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"บิตต่อตัวอย่างของเสียงบลูทูธ"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"ทริกเกอร์การเลือกตัวแปลงรหัส\nเสียงบลูทูธ: บิตต่อตัวอย่าง"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"โหมดช่องสัญญาณเสียงบลูทูธ"</string>
diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml
index 21fe58c..e190773 100644
--- a/packages/SettingsLib/res/values-tl/strings.xml
+++ b/packages/SettingsLib/res/values-tl/strings.xml
@@ -233,6 +233,7 @@
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"I-trigger ang Pagpili sa Audio Codec ng\nBluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Sample na Rate ng Bluetooth Audio"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"I-trigger ang Pagpili sa Audio Codec ng\nBluetooth: Rate ng Sample"</string>
+    <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Ang ibig sabihin ng na-gray out ay hindi sinusuportahan ng telepono o headset"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Bits Per Sample ng Bluetooth Audio"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"I-trigger ang Pagpili sa Audio Codec ng\nBluetooth: Bits Per Sample"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Channel Mode ng Bluetooth Audio"</string>
diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml
index 4e7f38d..dc11e80 100644
--- a/packages/SettingsLib/res/values-tr/strings.xml
+++ b/packages/SettingsLib/res/values-tr/strings.xml
@@ -233,6 +233,7 @@
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Bluetooth Ses Codec\'i Tetikleme\nSeçimi"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Bluetooth Ses Örnek Hızı"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Bluetooth Ses Codec\'i Tetikleme\nSeçimi: Örnek Hızı"</string>
+    <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Devre dışı bırakılmış olması telefon veya mikrofonlu kulaklık tarafından desteklenmediği anlamına gelir."</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Bluetooth Ses Örnek Başına Bit Sayısı"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Bluetooth Ses Codec\'i Tetikleme\nSeçimi: Örnek Başına Bit Sayısı"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Bluetooth Ses Kanalı Modu"</string>
diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml
index 9807417..f8a88b83 100644
--- a/packages/SettingsLib/res/values-uk/strings.xml
+++ b/packages/SettingsLib/res/values-uk/strings.xml
@@ -233,6 +233,7 @@
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Активувати кодек для аудіо Bluetooth\nВибір"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Частота вибірки для аудіо Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Активувати кодек для аудіо Bluetooth\nВибір: частота зразка"</string>
+    <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Затіненння означає, що телефон або гарнітура не підтримуються"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Кількість бітів на зразок для аудіо Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Активувати кодек для аудіо Bluetooth\nВибір: біти на зразок"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Режим каналу для аудіо Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-ur/strings.xml b/packages/SettingsLib/res/values-ur/strings.xml
index e17b0b0..246b6a2 100644
--- a/packages/SettingsLib/res/values-ur/strings.xml
+++ b/packages/SettingsLib/res/values-ur/strings.xml
@@ -233,6 +233,7 @@
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"بلوٹوتھ آڈیو کوڈیک کو ٹریگر کریں\nانتخاب"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"بلوٹوتھ آڈیو کے نمونے کی شرح"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"بلوٹوتھ آڈیو کوڈیک کو ٹریگر کریں\nانتخاب: نمونے کی شرح"</string>
+    <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"گرے آؤٹ کا مطلب ہے فون یا ہیڈ سیٹ کے ذریعہ تعاون یافتہ نہیں"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"بلوٹوتھ آڈیو بٹس فی نمونہ"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"بلوٹوتھ آڈیو کوڈیک کو ٹریگر کریں\nانتخاب: بِٹس فی نمونہ"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"بلوٹوتھ آڈیو چینل موڈ"</string>
diff --git a/packages/SettingsLib/res/values-uz/strings.xml b/packages/SettingsLib/res/values-uz/strings.xml
index ea51eba..87cc2a0 100644
--- a/packages/SettingsLib/res/values-uz/strings.xml
+++ b/packages/SettingsLib/res/values-uz/strings.xml
@@ -233,6 +233,7 @@
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Bluetooth orqali uzatish uchun audiokodek\nTanlash"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Bluetooth audio namunasi chastotasi"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Bluetooth orqali uzatish uchun audiokodek\nTanlash: namuna chastotasi"</string>
+    <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Parametr yoqilmasa, garnitura yoki telefonda ishlamaydi"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Bluetooth audio namunasidagi bitlar soni"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Bluetooth orqali uzatish uchun audiokodek\nTanlash: namunadagi bitlar soni"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Bluetooth audio kanali rejimi"</string>
diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml
index 0b71a8c..0a9726a 100644
--- a/packages/SettingsLib/res/values-vi/strings.xml
+++ b/packages/SettingsLib/res/values-vi/strings.xml
@@ -233,6 +233,7 @@
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Kích hoạt chế độ chọn codec\nâm thanh Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Tốc độ lấy mẫu âm thanh Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Kích hoạt chế độ chọn codec\nâm thanh Bluetooth: Tần số lấy mẫu"</string>
+    <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Trạng thái chuyển sang màu xám có nghĩa là điện thoại hoặc tai nghe không hỗ trợ"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Số bit âm thanh Bluetooth mỗi mẫu"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Kích hoạt chế độ chọn codec\nâm thanh Bluetooth: Số bit trên mỗi mẫu"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Chế độ kênh âm thanh Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml
index 1805694..514e677 100644
--- a/packages/SettingsLib/res/values-zh-rCN/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml
@@ -233,6 +233,7 @@
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"触发蓝牙音频编解码器\n选择"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"蓝牙音频采样率"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"触发蓝牙音频编解码器\n选择:采样率"</string>
+    <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"灰显意味着手机或耳机不支持该功能"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"蓝牙音频每样本位数"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"触发蓝牙音频编解码器\n选择:每样本位数"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"蓝牙音频声道模式"</string>
diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml
index 1d217b5..261e8d02 100644
--- a/packages/SettingsLib/res/values-zh-rHK/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml
@@ -233,6 +233,7 @@
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"觸發藍牙音訊編解碼器\n選項"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"藍牙音訊取樣率"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"觸發藍牙音訊編解碼器\n選項:取樣率"</string>
+    <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"以灰色顯示代表手機或耳機不支援此音訊編解碼器"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"藍牙音訊每個樣本位元數"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"觸發藍牙音訊編解碼器\n選項:每個樣本位元數"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"藍牙音訊聲道模式"</string>
diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml
index ee68665..d0ba3d0 100644
--- a/packages/SettingsLib/res/values-zh-rTW/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml
@@ -233,6 +233,7 @@
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"觸發藍牙音訊轉碼器\n選項"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"藍牙音訊取樣率"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"觸發藍牙音訊轉碼器\n選項:取樣率"</string>
+    <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"如果顯示為灰色,表示手機或耳機不支援這項功能"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"藍牙音訊每單位樣本位元數"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"觸發藍牙音訊轉碼器\n選項:每單位樣本位元數"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"藍牙音訊聲道模式"</string>
diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml
index 820aa77..f8cc50b 100644
--- a/packages/SettingsLib/res/values-zu/strings.xml
+++ b/packages/SettingsLib/res/values-zu/strings.xml
@@ -233,6 +233,7 @@
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Qalisa i-codec ye-bluetooth yomsindo\nUkukhethwa"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Isilinganiso sesampula yomsindo we-Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Qalisa i-codec ye-bluetooth yomsindo\nUkukhethwa: Isampuli yesilinganiso"</string>
+    <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Okwenziwa mpunga ngokuphelele kusho ukuthi akusekelwe ifoni noma ihedisethi"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Ama-Bits omsindo we-Bluetooth ngesampula ngayinye"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Qalisa i-codec ye-bluetooth yomsindo\nUkukhethwa: Amabhithi ngesampuli ngayinye"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Imodi yesiteshi somsindo we-Bluetooth"</string>
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
index 0095692..833c4ac 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
@@ -241,9 +241,7 @@
 
     public void disconnect() {
         synchronized (mProfileLock) {
-            for (LocalBluetoothProfile profile : mProfiles) {
-                disconnect(profile);
-            }
+            mLocalAdapter.disconnectAllEnabledProfiles(mDevice);
         }
         // Disconnect  PBAP server in case its connected
         // This is to ensure all the profiles are disconnected as some CK/Hs do not
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawable/UserIconDrawable.java b/packages/SettingsLib/src/com/android/settingslib/drawable/UserIconDrawable.java
index 69487d5..274696b 100644
--- a/packages/SettingsLib/src/com/android/settingslib/drawable/UserIconDrawable.java
+++ b/packages/SettingsLib/src/com/android/settingslib/drawable/UserIconDrawable.java
@@ -39,7 +39,6 @@
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
 import android.os.UserHandle;
-import android.os.UserManager;
 
 import com.android.settingslib.R;
 
@@ -177,8 +176,8 @@
             boolean isManaged = context.getSystemService(DevicePolicyManager.class)
                     .getProfileOwnerAsUser(userId) != null;
             if (isManaged) {
-                badge = getDrawableForDisplayDensity(context,
-                        context.getSystemService(UserManager.class).getUserBadgeResId(userId));
+                badge = getDrawableForDisplayDensity(
+                        context, com.android.internal.R.drawable.ic_corp_badge_case);
             }
         }
         return setBadge(badge);
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/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/MasterSwitchControllerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/MasterSwitchControllerTest.java
new file mode 100644
index 0000000..69d0f2e
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/MasterSwitchControllerTest.java
@@ -0,0 +1,80 @@
+/*
+ * 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.settingslib.drawer;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+
+@RunWith(RobolectricTestRunner.class)
+public class MasterSwitchControllerTest {
+
+    @Rule
+    public final ExpectedException thrown = ExpectedException.none();
+
+    private MasterSwitchController mController;
+
+    @Before
+    public void setUp() {
+        mController = new TestMasterSwitchController("123");
+    }
+
+    @Test
+    public void getMetaData_shouldThrowUnsupportedOperationException() {
+        thrown.expect(UnsupportedOperationException.class);
+
+        mController.getMetaData();
+    }
+
+    @Test
+    public void getBundle_shouldThrowUnsupportedOperationException() {
+        thrown.expect(UnsupportedOperationException.class);
+
+        mController.getBundle();
+    }
+
+    static class TestMasterSwitchController extends MasterSwitchController {
+
+        private String mKey;
+
+        TestMasterSwitchController(String key) {
+            mKey = key;
+        }
+
+        @Override
+        public String getSwitchKey() {
+            return mKey;
+        }
+
+        @Override
+        protected boolean isChecked() {
+            return true;
+        }
+
+        @Override
+        protected boolean onCheckedChanged(boolean checked) {
+            return true;
+        }
+
+        @Override
+        protected String getErrorMessage(boolean attemptedChecked) {
+            return null;
+        }
+    }
+}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/SwitchesProviderTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/SwitchesProviderTest.java
index 27b3697..a740e68 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/SwitchesProviderTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/SwitchesProviderTest.java
@@ -35,6 +35,7 @@
 import android.content.pm.ProviderInfo;
 import android.os.Bundle;
 
+import com.android.settingslib.drawer.MasterSwitchControllerTest.TestMasterSwitchController;
 import com.android.settingslib.drawer.SwitchController.MetaData;
 
 import org.junit.Before;
@@ -84,8 +85,8 @@
     }
 
     @Test
-    public void attachInfo_NoMetaDataInController_shouldThrowIllegalArgumentException() {
-        thrown.expect(IllegalArgumentException.class);
+    public void attachInfo_NoMetaDataInController_shouldThrowNullPointerException() {
+        thrown.expect(NullPointerException.class);
         final TestSwitchController controller = new TestSwitchController();
         controller.setKey("123");
         mSwitchesProvider.addSwitchController(controller);
@@ -123,6 +124,19 @@
     }
 
     @Test
+    public void getSwitchData_shouldNotReturnMasterSwitchData() {
+        final SwitchController controller = new TestMasterSwitchController("123");
+        mSwitchesProvider.addSwitchController(controller);
+        mSwitchesProvider.attachInfo(mContext, mProviderInfo);
+
+        final Bundle switchData = mSwitchesProvider.call(METHOD_GET_SWITCH_DATA, "uri" ,
+                null /* extras*/);
+
+        final ArrayList<Bundle> dataList = switchData.getParcelableArrayList(EXTRA_SWITCH_DATA);
+        assertThat(dataList).isEmpty();
+    }
+
+    @Test
     public void getSwitchData_shouldReturnDataList() {
         final TestSwitchController controller = new TestSwitchController();
         controller.setKey("123");
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java
index b36eb49..9b4b97e 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java
@@ -113,7 +113,7 @@
         when(mPackageManager.queryIntentContentProvidersAsUser(any(Intent.class), anyInt(),
                 anyInt())).thenReturn(info);
 
-        TileUtils.getTilesForAction(mContext, UserHandle.CURRENT, IA_SETTINGS_ACTION, addedCache,
+        TileUtils.loadTilesForAction(mContext, UserHandle.CURRENT, IA_SETTINGS_ACTION, addedCache,
                 null /* defaultCategory */, outTiles, false /* usePriority */);
 
         assertThat(outTiles).hasSize(2);
@@ -135,7 +135,7 @@
         when(mPackageManager.queryIntentContentProvidersAsUser(any(Intent.class), anyInt(),
                 anyInt())).thenReturn(info);
 
-        TileUtils.getTilesForAction(mContext, UserHandle.CURRENT, IA_SETTINGS_ACTION, addedCache,
+        TileUtils.loadTilesForAction(mContext, UserHandle.CURRENT, IA_SETTINGS_ACTION, addedCache,
                 null /* defaultCategory */, outTiles, false /* requiresSettings */);
 
         assertThat(outTiles).hasSize(2);
@@ -156,7 +156,7 @@
         when(mPackageManager.queryIntentContentProvidersAsUser(any(Intent.class), anyInt(),
                 anyInt())).thenReturn(info);
 
-        TileUtils.getTilesForAction(mContext, UserHandle.CURRENT, IA_SETTINGS_ACTION,
+        TileUtils.loadTilesForAction(mContext, UserHandle.CURRENT, IA_SETTINGS_ACTION,
                 addedCache, null /* defaultCategory */, outTiles, false /* requiresSettings */);
 
         assertThat(outTiles).isEmpty();
@@ -197,7 +197,7 @@
         when(mPackageManager.queryIntentContentProvidersAsUser(any(Intent.class), anyInt(),
                 anyInt())).thenReturn(info);
 
-        TileUtils.getTilesForAction(mContext, UserHandle.CURRENT, IA_SETTINGS_ACTION, addedCache,
+        TileUtils.loadTilesForAction(mContext, UserHandle.CURRENT, IA_SETTINGS_ACTION, addedCache,
                 null /* defaultCategory */, outTiles, false /* usePriority */);
 
         assertThat(outTiles).hasSize(2);
@@ -222,7 +222,7 @@
         when(mResources.getString(eq(123)))
                 .thenReturn("my localized title");
 
-        TileUtils.getTilesForAction(mContext, UserHandle.CURRENT, IA_SETTINGS_ACTION, addedCache,
+        TileUtils.loadTilesForAction(mContext, UserHandle.CURRENT, IA_SETTINGS_ACTION, addedCache,
                 null /* defaultCategory */, outTiles, false /* usePriority */);
         assertThat(outTiles).hasSize(2);
         assertThat(outTiles.get(0).getTitle(mContext)).isEqualTo("my localized title");
@@ -245,7 +245,7 @@
         when(mPackageManager.queryIntentContentProvidersAsUser(any(Intent.class), anyInt(),
                 anyInt())).thenReturn(info);
 
-        TileUtils.getTilesForAction(mContext, UserHandle.CURRENT, IA_SETTINGS_ACTION, addedCache,
+        TileUtils.loadTilesForAction(mContext, UserHandle.CURRENT, IA_SETTINGS_ACTION, addedCache,
                 null /* defaultCategory */, outTiles, false /* usePriority */);
 
         assertThat(outTiles.get(0).isIconTintable(mContext)).isFalse();
@@ -266,7 +266,7 @@
         when(mPackageManager.queryIntentActivitiesAsUser(any(Intent.class), anyInt(), anyInt()))
                 .thenReturn(info);
 
-        TileUtils.getTilesForAction(mContext, UserHandle.CURRENT, IA_SETTINGS_ACTION, addedCache,
+        TileUtils.loadTilesForAction(mContext, UserHandle.CURRENT, IA_SETTINGS_ACTION, addedCache,
                 null /* defaultCategory */, outTiles, false /* usePriority */);
 
         assertThat(outTiles).hasSize(1);
@@ -276,7 +276,7 @@
         resolveInfo.activityInfo.metaData.putInt(META_DATA_PREFERENCE_ICON,
                 com.android.internal.R.drawable.ic_phone);
         outTiles.clear();
-        TileUtils.getTilesForAction(mContext, UserHandle.CURRENT, IA_SETTINGS_ACTION, addedCache,
+        TileUtils.loadTilesForAction(mContext, UserHandle.CURRENT, IA_SETTINGS_ACTION, addedCache,
                 null /* defaultCategory */, outTiles, false /* usePriority */);
 
         assertThat(outTiles).hasSize(1);
@@ -300,7 +300,7 @@
         when(mPackageManager.queryIntentContentProvidersAsUser(any(Intent.class), anyInt(),
                 anyInt())).thenReturn(info);
 
-        TileUtils.getTilesForAction(mContext, UserHandle.CURRENT, IA_SETTINGS_ACTION, addedCache,
+        TileUtils.loadTilesForAction(mContext, UserHandle.CURRENT, IA_SETTINGS_ACTION, addedCache,
                 null /* defaultCategory */, outTiles, false /* usePriority */);
 
         assertThat(outTiles.get(0).isIconTintable(mContext)).isTrue();
@@ -321,7 +321,7 @@
         when(mPackageManager.queryIntentContentProvidersAsUser(any(Intent.class), anyInt(),
                 anyInt())).thenReturn(info);
 
-        TileUtils.getTilesForAction(mContext, UserHandle.CURRENT, IA_SETTINGS_ACTION, addedCache,
+        TileUtils.loadTilesForAction(mContext, UserHandle.CURRENT, IA_SETTINGS_ACTION, addedCache,
                 null /* defaultCategory */, outTiles, false /* usePriority */);
 
         assertThat(outTiles).hasSize(2);
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-af/strings.xml b/packages/SettingsProvider/res/values-af/strings.xml
index 79a7f2d..2c45484 100644
--- a/packages/SettingsProvider/res/values-af/strings.xml
+++ b/packages/SettingsProvider/res/values-af/strings.xml
@@ -20,4 +20,10 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Instellingsberging"</string>
+    <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsProvider/res/values-am/strings.xml b/packages/SettingsProvider/res/values-am/strings.xml
index 6380b99..0630560 100644
--- a/packages/SettingsProvider/res/values-am/strings.xml
+++ b/packages/SettingsProvider/res/values-am/strings.xml
@@ -20,4 +20,10 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"የቅንብሮች ማከማቻ"</string>
+    <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsProvider/res/values-ar/strings.xml b/packages/SettingsProvider/res/values-ar/strings.xml
index ab1b808..19306a6 100644
--- a/packages/SettingsProvider/res/values-ar/strings.xml
+++ b/packages/SettingsProvider/res/values-ar/strings.xml
@@ -20,4 +20,10 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"تخزين الإعدادات"</string>
+    <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsProvider/res/values-as/strings.xml b/packages/SettingsProvider/res/values-as/strings.xml
index 233253e..13b90d6 100644
--- a/packages/SettingsProvider/res/values-as/strings.xml
+++ b/packages/SettingsProvider/res/values-as/strings.xml
@@ -20,4 +20,10 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"ছেটিংছসমূহৰ সঞ্চয়াগাৰ"</string>
+    <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsProvider/res/values-az/strings.xml b/packages/SettingsProvider/res/values-az/strings.xml
index e99e99b..4737a1e 100644
--- a/packages/SettingsProvider/res/values-az/strings.xml
+++ b/packages/SettingsProvider/res/values-az/strings.xml
@@ -20,4 +20,10 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Ayarlar Deposu"</string>
+    <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsProvider/res/values-b+sr+Latn/strings.xml b/packages/SettingsProvider/res/values-b+sr+Latn/strings.xml
index 337b18e..032dbc5 100644
--- a/packages/SettingsProvider/res/values-b+sr+Latn/strings.xml
+++ b/packages/SettingsProvider/res/values-b+sr+Latn/strings.xml
@@ -20,4 +20,10 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Podešavanja skladišta"</string>
+    <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsProvider/res/values-be/strings.xml b/packages/SettingsProvider/res/values-be/strings.xml
index 3a8557c..60bdb2d 100644
--- a/packages/SettingsProvider/res/values-be/strings.xml
+++ b/packages/SettingsProvider/res/values-be/strings.xml
@@ -20,4 +20,10 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Сховішча налад"</string>
+    <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsProvider/res/values-bg/strings.xml b/packages/SettingsProvider/res/values-bg/strings.xml
index f3d21d8..c3a994b 100644
--- a/packages/SettingsProvider/res/values-bg/strings.xml
+++ b/packages/SettingsProvider/res/values-bg/strings.xml
@@ -20,4 +20,10 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Настройки за хранилище"</string>
+    <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsProvider/res/values-bn/strings.xml b/packages/SettingsProvider/res/values-bn/strings.xml
index 7e72dfb..71ee99b 100644
--- a/packages/SettingsProvider/res/values-bn/strings.xml
+++ b/packages/SettingsProvider/res/values-bn/strings.xml
@@ -20,4 +20,10 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"সেটিংস স্টোরেজ"</string>
+    <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsProvider/res/values-bs/strings.xml b/packages/SettingsProvider/res/values-bs/strings.xml
index 464a29f..09d4c68 100644
--- a/packages/SettingsProvider/res/values-bs/strings.xml
+++ b/packages/SettingsProvider/res/values-bs/strings.xml
@@ -20,4 +20,10 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Postavke za pohranu podataka"</string>
+    <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsProvider/res/values-ca/strings.xml b/packages/SettingsProvider/res/values-ca/strings.xml
index 9d6ac7a..ee6b51e 100644
--- a/packages/SettingsProvider/res/values-ca/strings.xml
+++ b/packages/SettingsProvider/res/values-ca/strings.xml
@@ -20,4 +20,10 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Configuració de l\'emmagatzematge"</string>
+    <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsProvider/res/values-cs/strings.xml b/packages/SettingsProvider/res/values-cs/strings.xml
index a28ffa1..f134e05 100644
--- a/packages/SettingsProvider/res/values-cs/strings.xml
+++ b/packages/SettingsProvider/res/values-cs/strings.xml
@@ -20,4 +20,10 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Paměť pro nastavení"</string>
+    <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsProvider/res/values-da/strings.xml b/packages/SettingsProvider/res/values-da/strings.xml
index ed450d5..99988a5 100644
--- a/packages/SettingsProvider/res/values-da/strings.xml
+++ b/packages/SettingsProvider/res/values-da/strings.xml
@@ -20,4 +20,10 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Lagring af indstillinger"</string>
+    <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsProvider/res/values-de/strings.xml b/packages/SettingsProvider/res/values-de/strings.xml
index 6effbae..ddcabaa 100644
--- a/packages/SettingsProvider/res/values-de/strings.xml
+++ b/packages/SettingsProvider/res/values-de/strings.xml
@@ -20,4 +20,10 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Einstellungsspeicher"</string>
+    <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsProvider/res/values-el/strings.xml b/packages/SettingsProvider/res/values-el/strings.xml
index 5bd1fa6..924fab5 100644
--- a/packages/SettingsProvider/res/values-el/strings.xml
+++ b/packages/SettingsProvider/res/values-el/strings.xml
@@ -20,4 +20,10 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Αποθηκευτικός χώρος ρυθμίσεων"</string>
+    <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsProvider/res/values-en-rAU/strings.xml b/packages/SettingsProvider/res/values-en-rAU/strings.xml
index c19fdd7..05cd54e 100644
--- a/packages/SettingsProvider/res/values-en-rAU/strings.xml
+++ b/packages/SettingsProvider/res/values-en-rAU/strings.xml
@@ -20,4 +20,10 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Settings Storage"</string>
+    <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsProvider/res/values-en-rCA/strings.xml b/packages/SettingsProvider/res/values-en-rCA/strings.xml
index c19fdd7..05cd54e 100644
--- a/packages/SettingsProvider/res/values-en-rCA/strings.xml
+++ b/packages/SettingsProvider/res/values-en-rCA/strings.xml
@@ -20,4 +20,10 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Settings Storage"</string>
+    <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsProvider/res/values-en-rGB/strings.xml b/packages/SettingsProvider/res/values-en-rGB/strings.xml
index c19fdd7..05cd54e 100644
--- a/packages/SettingsProvider/res/values-en-rGB/strings.xml
+++ b/packages/SettingsProvider/res/values-en-rGB/strings.xml
@@ -20,4 +20,10 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Settings Storage"</string>
+    <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsProvider/res/values-en-rIN/strings.xml b/packages/SettingsProvider/res/values-en-rIN/strings.xml
index c19fdd7..05cd54e 100644
--- a/packages/SettingsProvider/res/values-en-rIN/strings.xml
+++ b/packages/SettingsProvider/res/values-en-rIN/strings.xml
@@ -20,4 +20,10 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Settings Storage"</string>
+    <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsProvider/res/values-en-rXC/strings.xml b/packages/SettingsProvider/res/values-en-rXC/strings.xml
index 9b18e2b..fbc348b 100644
--- a/packages/SettingsProvider/res/values-en-rXC/strings.xml
+++ b/packages/SettingsProvider/res/values-en-rXC/strings.xml
@@ -20,4 +20,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‏‏‏‏‎‏‏‎‎‎‏‏‎‏‎‎‎‎‎‏‎‎‏‎‏‎‏‎‏‎‏‎‎‏‏‎‏‏‏‎‏‎‎‏‏‏‎‏‎‏‎‎‎‎‏‏‏‏‏‏‎Settings Storage‎‏‎‎‏‎"</string>
+    <string name="wifi_softap_config_change" msgid="5338670993556993667">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‏‎‏‎‎‎‎‏‎‏‏‎‏‏‎‎‎‏‎‎‏‏‏‏‏‎‏‏‏‎‏‎‏‏‏‏‏‎‏‎‎‏‎‏‎‏‏‏‎‏‏‎‏‎‎‎‎‎‏‏‎Changes to your hotspot settings‎‏‎‎‏‎"</string>
+    <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‏‎‎‏‎‏‏‏‏‎‎‎‏‎‏‎‎‏‎‎‏‎‎‎‎‎‎‏‏‏‏‎‏‏‏‏‏‏‎‎‎‎‎‎‎‎‎‎‎‏‏‎‏‏‏‎‎‏‏‎‎Your hotspot band has changed.‎‏‎‎‏‎"</string>
+    <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‎‎‏‎‏‏‎‎‎‎‏‎‎‏‎‏‏‎‏‏‎‏‎‏‎‎‏‏‎‎‎‎‎‎‎‏‏‏‏‎‏‎‏‎‎‏‎‎‎‎‎‏‏‎‏‏‎‎‏‎‎This device doesn’t support your preference for 5GHz only. Instead, this device will use the 5GHz band when available.‎‏‎‎‏‎"</string>
 </resources>
diff --git a/packages/SettingsProvider/res/values-es-rUS/strings.xml b/packages/SettingsProvider/res/values-es-rUS/strings.xml
index 7a15d8b..d5e6da9 100644
--- a/packages/SettingsProvider/res/values-es-rUS/strings.xml
+++ b/packages/SettingsProvider/res/values-es-rUS/strings.xml
@@ -20,4 +20,10 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Almacenamiento de configuración"</string>
+    <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsProvider/res/values-es/strings.xml b/packages/SettingsProvider/res/values-es/strings.xml
index 7a15d8b..d5e6da9 100644
--- a/packages/SettingsProvider/res/values-es/strings.xml
+++ b/packages/SettingsProvider/res/values-es/strings.xml
@@ -20,4 +20,10 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Almacenamiento de configuración"</string>
+    <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsProvider/res/values-et/strings.xml b/packages/SettingsProvider/res/values-et/strings.xml
index 30b7293..a3e4db6 100644
--- a/packages/SettingsProvider/res/values-et/strings.xml
+++ b/packages/SettingsProvider/res/values-et/strings.xml
@@ -20,4 +20,10 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Seadete talletusruum"</string>
+    <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsProvider/res/values-eu/strings.xml b/packages/SettingsProvider/res/values-eu/strings.xml
index 6780ae0..8d410de1 100644
--- a/packages/SettingsProvider/res/values-eu/strings.xml
+++ b/packages/SettingsProvider/res/values-eu/strings.xml
@@ -20,4 +20,10 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Ezarpenen biltegia"</string>
+    <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsProvider/res/values-fa/strings.xml b/packages/SettingsProvider/res/values-fa/strings.xml
index 97fe0ab..ed9d168 100644
--- a/packages/SettingsProvider/res/values-fa/strings.xml
+++ b/packages/SettingsProvider/res/values-fa/strings.xml
@@ -20,4 +20,10 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"تنظیم محل ذخیره"</string>
+    <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsProvider/res/values-fi/strings.xml b/packages/SettingsProvider/res/values-fi/strings.xml
index 83c7f66..9ff2c41 100644
--- a/packages/SettingsProvider/res/values-fi/strings.xml
+++ b/packages/SettingsProvider/res/values-fi/strings.xml
@@ -20,4 +20,10 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Asetuksien tallennus"</string>
+    <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsProvider/res/values-fr-rCA/strings.xml b/packages/SettingsProvider/res/values-fr-rCA/strings.xml
index c90eb09..fdfdb1d 100644
--- a/packages/SettingsProvider/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsProvider/res/values-fr-rCA/strings.xml
@@ -20,4 +20,10 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Stockage des paramètres"</string>
+    <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsProvider/res/values-fr/strings.xml b/packages/SettingsProvider/res/values-fr/strings.xml
index c90eb09..fdfdb1d 100644
--- a/packages/SettingsProvider/res/values-fr/strings.xml
+++ b/packages/SettingsProvider/res/values-fr/strings.xml
@@ -20,4 +20,10 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Stockage des paramètres"</string>
+    <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsProvider/res/values-gl/strings.xml b/packages/SettingsProvider/res/values-gl/strings.xml
index 80ef310..7b1599e 100644
--- a/packages/SettingsProvider/res/values-gl/strings.xml
+++ b/packages/SettingsProvider/res/values-gl/strings.xml
@@ -20,4 +20,10 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Almacenamento da configuración"</string>
+    <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsProvider/res/values-gu/strings.xml b/packages/SettingsProvider/res/values-gu/strings.xml
index 7241974..00246f9 100644
--- a/packages/SettingsProvider/res/values-gu/strings.xml
+++ b/packages/SettingsProvider/res/values-gu/strings.xml
@@ -20,4 +20,10 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"સેટિંગ્સ સંગ્રહ"</string>
+    <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsProvider/res/values-hi/strings.xml b/packages/SettingsProvider/res/values-hi/strings.xml
index da8193f..35ed78f 100644
--- a/packages/SettingsProvider/res/values-hi/strings.xml
+++ b/packages/SettingsProvider/res/values-hi/strings.xml
@@ -20,4 +20,10 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"सेटिंग मेमोरी"</string>
+    <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsProvider/res/values-hr/strings.xml b/packages/SettingsProvider/res/values-hr/strings.xml
index 87f1270..070d061 100644
--- a/packages/SettingsProvider/res/values-hr/strings.xml
+++ b/packages/SettingsProvider/res/values-hr/strings.xml
@@ -20,4 +20,10 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Postavke pohrane"</string>
+    <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsProvider/res/values-hu/strings.xml b/packages/SettingsProvider/res/values-hu/strings.xml
index dab1b17..97124ae 100644
--- a/packages/SettingsProvider/res/values-hu/strings.xml
+++ b/packages/SettingsProvider/res/values-hu/strings.xml
@@ -20,4 +20,10 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Beállítástároló"</string>
+    <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsProvider/res/values-hy/strings.xml b/packages/SettingsProvider/res/values-hy/strings.xml
index b1f1afb..d494012 100644
--- a/packages/SettingsProvider/res/values-hy/strings.xml
+++ b/packages/SettingsProvider/res/values-hy/strings.xml
@@ -20,4 +20,10 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Կարգավորումների պահուստ"</string>
+    <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsProvider/res/values-in/strings.xml b/packages/SettingsProvider/res/values-in/strings.xml
index bed20eb..4ec8f84 100644
--- a/packages/SettingsProvider/res/values-in/strings.xml
+++ b/packages/SettingsProvider/res/values-in/strings.xml
@@ -20,4 +20,10 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Setelan Penyimpanan"</string>
+    <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsProvider/res/values-is/strings.xml b/packages/SettingsProvider/res/values-is/strings.xml
index c4e2aa6..d75abae 100644
--- a/packages/SettingsProvider/res/values-is/strings.xml
+++ b/packages/SettingsProvider/res/values-is/strings.xml
@@ -20,4 +20,10 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Stillingageymsla"</string>
+    <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsProvider/res/values-it/strings.xml b/packages/SettingsProvider/res/values-it/strings.xml
index ba1431d..a1e3901 100644
--- a/packages/SettingsProvider/res/values-it/strings.xml
+++ b/packages/SettingsProvider/res/values-it/strings.xml
@@ -20,4 +20,10 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Memoria impostazioni"</string>
+    <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsProvider/res/values-iw/strings.xml b/packages/SettingsProvider/res/values-iw/strings.xml
index ad2eaf4..c14f776 100644
--- a/packages/SettingsProvider/res/values-iw/strings.xml
+++ b/packages/SettingsProvider/res/values-iw/strings.xml
@@ -20,4 +20,10 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"אחסון הגדרות"</string>
+    <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsProvider/res/values-ja/strings.xml b/packages/SettingsProvider/res/values-ja/strings.xml
index d222ca9..b11ec3b 100644
--- a/packages/SettingsProvider/res/values-ja/strings.xml
+++ b/packages/SettingsProvider/res/values-ja/strings.xml
@@ -20,4 +20,10 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"ストレージの設定"</string>
+    <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsProvider/res/values-ka/strings.xml b/packages/SettingsProvider/res/values-ka/strings.xml
index 691a2e9..d08e71e 100644
--- a/packages/SettingsProvider/res/values-ka/strings.xml
+++ b/packages/SettingsProvider/res/values-ka/strings.xml
@@ -20,4 +20,10 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"პარამეტრების საცავი"</string>
+    <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsProvider/res/values-kk/strings.xml b/packages/SettingsProvider/res/values-kk/strings.xml
index 8cf8af2..c07264c 100644
--- a/packages/SettingsProvider/res/values-kk/strings.xml
+++ b/packages/SettingsProvider/res/values-kk/strings.xml
@@ -20,4 +20,10 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Параметрлер жады"</string>
+    <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsProvider/res/values-km/strings.xml b/packages/SettingsProvider/res/values-km/strings.xml
index 7be62427..c880ead 100644
--- a/packages/SettingsProvider/res/values-km/strings.xml
+++ b/packages/SettingsProvider/res/values-km/strings.xml
@@ -20,4 +20,10 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"កំណត់​ការ​ផ្ទុក"</string>
+    <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsProvider/res/values-kn/strings.xml b/packages/SettingsProvider/res/values-kn/strings.xml
index ca427ec..d823323 100644
--- a/packages/SettingsProvider/res/values-kn/strings.xml
+++ b/packages/SettingsProvider/res/values-kn/strings.xml
@@ -20,4 +20,10 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"ಸೆಟ್ಟಿಂಗ್‌ಗಳ ಸಂಗ್ರಹಣೆ"</string>
+    <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsProvider/res/values-ko/strings.xml b/packages/SettingsProvider/res/values-ko/strings.xml
index 8e0cc75..ab8fb2b 100644
--- a/packages/SettingsProvider/res/values-ko/strings.xml
+++ b/packages/SettingsProvider/res/values-ko/strings.xml
@@ -20,4 +20,10 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"설정 저장소"</string>
+    <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsProvider/res/values-ky/strings.xml b/packages/SettingsProvider/res/values-ky/strings.xml
index 2b3cf61..566c481 100644
--- a/packages/SettingsProvider/res/values-ky/strings.xml
+++ b/packages/SettingsProvider/res/values-ky/strings.xml
@@ -20,4 +20,10 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Жөндөөлөрдү сактоо"</string>
+    <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsProvider/res/values-lo/strings.xml b/packages/SettingsProvider/res/values-lo/strings.xml
index 4e57936..1aa5fe9 100644
--- a/packages/SettingsProvider/res/values-lo/strings.xml
+++ b/packages/SettingsProvider/res/values-lo/strings.xml
@@ -20,4 +20,10 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"ບ່ອນເກັບຂໍ້ມູນການຕັ້ງຄ່າ"</string>
+    <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsProvider/res/values-lt/strings.xml b/packages/SettingsProvider/res/values-lt/strings.xml
index 5b4432f..47cd6b4 100644
--- a/packages/SettingsProvider/res/values-lt/strings.xml
+++ b/packages/SettingsProvider/res/values-lt/strings.xml
@@ -20,4 +20,10 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Nustatymų saugykla"</string>
+    <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsProvider/res/values-lv/strings.xml b/packages/SettingsProvider/res/values-lv/strings.xml
index c83580c..d221d46 100644
--- a/packages/SettingsProvider/res/values-lv/strings.xml
+++ b/packages/SettingsProvider/res/values-lv/strings.xml
@@ -20,4 +20,10 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Iestatījumu krātuve"</string>
+    <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsProvider/res/values-mk/strings.xml b/packages/SettingsProvider/res/values-mk/strings.xml
index f281bae..dc74c4a 100644
--- a/packages/SettingsProvider/res/values-mk/strings.xml
+++ b/packages/SettingsProvider/res/values-mk/strings.xml
@@ -20,4 +20,10 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Поставки за меморија"</string>
+    <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsProvider/res/values-ml/strings.xml b/packages/SettingsProvider/res/values-ml/strings.xml
index 43a88e1..a11e236 100644
--- a/packages/SettingsProvider/res/values-ml/strings.xml
+++ b/packages/SettingsProvider/res/values-ml/strings.xml
@@ -20,4 +20,10 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"സംഭരണ ക്രമീകരണം"</string>
+    <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsProvider/res/values-mn/strings.xml b/packages/SettingsProvider/res/values-mn/strings.xml
index 9452145..f6437c75 100644
--- a/packages/SettingsProvider/res/values-mn/strings.xml
+++ b/packages/SettingsProvider/res/values-mn/strings.xml
@@ -20,4 +20,10 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Тохиргооны Сан"</string>
+    <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsProvider/res/values-mr/strings.xml b/packages/SettingsProvider/res/values-mr/strings.xml
index 65a876f..7888488 100644
--- a/packages/SettingsProvider/res/values-mr/strings.xml
+++ b/packages/SettingsProvider/res/values-mr/strings.xml
@@ -20,4 +20,10 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"सेटिंग्ज संचयन"</string>
+    <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsProvider/res/values-ms/strings.xml b/packages/SettingsProvider/res/values-ms/strings.xml
index 9108b07..bcde71c 100644
--- a/packages/SettingsProvider/res/values-ms/strings.xml
+++ b/packages/SettingsProvider/res/values-ms/strings.xml
@@ -20,4 +20,10 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Storan Tetapan"</string>
+    <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsProvider/res/values-my/strings.xml b/packages/SettingsProvider/res/values-my/strings.xml
index 0c5e840..b2e670e 100644
--- a/packages/SettingsProvider/res/values-my/strings.xml
+++ b/packages/SettingsProvider/res/values-my/strings.xml
@@ -20,4 +20,10 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"သိုလှောင်မှုဆက်တင်များ"</string>
+    <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsProvider/res/values-nb/strings.xml b/packages/SettingsProvider/res/values-nb/strings.xml
index ad18f94..5c60ad7 100644
--- a/packages/SettingsProvider/res/values-nb/strings.xml
+++ b/packages/SettingsProvider/res/values-nb/strings.xml
@@ -20,4 +20,10 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Lagring av innstillinger"</string>
+    <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsProvider/res/values-ne/strings.xml b/packages/SettingsProvider/res/values-ne/strings.xml
index af6ef62..8c4f8c8 100644
--- a/packages/SettingsProvider/res/values-ne/strings.xml
+++ b/packages/SettingsProvider/res/values-ne/strings.xml
@@ -20,4 +20,10 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"सेटिङहरू भण्डारण"</string>
+    <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsProvider/res/values-nl/strings.xml b/packages/SettingsProvider/res/values-nl/strings.xml
index 010fdb5..7ad4588 100644
--- a/packages/SettingsProvider/res/values-nl/strings.xml
+++ b/packages/SettingsProvider/res/values-nl/strings.xml
@@ -20,4 +20,10 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Opslagruimte voor instellingen"</string>
+    <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsProvider/res/values-or/strings.xml b/packages/SettingsProvider/res/values-or/strings.xml
index 04f68c8..1837219 100644
--- a/packages/SettingsProvider/res/values-or/strings.xml
+++ b/packages/SettingsProvider/res/values-or/strings.xml
@@ -20,4 +20,10 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"ସେଟିଙ୍ଗ ଷ୍ଟୋରେଜ୍‌"</string>
+    <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsProvider/res/values-pa/strings.xml b/packages/SettingsProvider/res/values-pa/strings.xml
index 1813bec..2961435 100644
--- a/packages/SettingsProvider/res/values-pa/strings.xml
+++ b/packages/SettingsProvider/res/values-pa/strings.xml
@@ -20,4 +20,10 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"ਸੈਟਿੰਗਾਂ ਸਟੋਰੇਜ"</string>
+    <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsProvider/res/values-pl/strings.xml b/packages/SettingsProvider/res/values-pl/strings.xml
index 9f81e63..9963aee 100644
--- a/packages/SettingsProvider/res/values-pl/strings.xml
+++ b/packages/SettingsProvider/res/values-pl/strings.xml
@@ -20,4 +20,10 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Pamięć ustawień"</string>
+    <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsProvider/res/values-pt-rBR/strings.xml b/packages/SettingsProvider/res/values-pt-rBR/strings.xml
index ade1746..e25e82e 100644
--- a/packages/SettingsProvider/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsProvider/res/values-pt-rBR/strings.xml
@@ -20,4 +20,10 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Armazenamento de configurações"</string>
+    <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsProvider/res/values-pt-rPT/strings.xml b/packages/SettingsProvider/res/values-pt-rPT/strings.xml
index c7dc9e6..3b95a31 100644
--- a/packages/SettingsProvider/res/values-pt-rPT/strings.xml
+++ b/packages/SettingsProvider/res/values-pt-rPT/strings.xml
@@ -20,4 +20,10 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Armazenamento de definições"</string>
+    <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsProvider/res/values-pt/strings.xml b/packages/SettingsProvider/res/values-pt/strings.xml
index ade1746..e25e82e 100644
--- a/packages/SettingsProvider/res/values-pt/strings.xml
+++ b/packages/SettingsProvider/res/values-pt/strings.xml
@@ -20,4 +20,10 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Armazenamento de configurações"</string>
+    <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsProvider/res/values-ro/strings.xml b/packages/SettingsProvider/res/values-ro/strings.xml
index 53e9429..5a5ac6d 100644
--- a/packages/SettingsProvider/res/values-ro/strings.xml
+++ b/packages/SettingsProvider/res/values-ro/strings.xml
@@ -20,4 +20,10 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Stocare setări"</string>
+    <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsProvider/res/values-ru/strings.xml b/packages/SettingsProvider/res/values-ru/strings.xml
index 4c15984..15ca313 100644
--- a/packages/SettingsProvider/res/values-ru/strings.xml
+++ b/packages/SettingsProvider/res/values-ru/strings.xml
@@ -20,4 +20,10 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Хранилище настроек"</string>
+    <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsProvider/res/values-si/strings.xml b/packages/SettingsProvider/res/values-si/strings.xml
index 24ef798..feff43c 100644
--- a/packages/SettingsProvider/res/values-si/strings.xml
+++ b/packages/SettingsProvider/res/values-si/strings.xml
@@ -20,4 +20,10 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"සැකසීම් ගබඩාව"</string>
+    <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsProvider/res/values-sk/strings.xml b/packages/SettingsProvider/res/values-sk/strings.xml
index 955c834..1207a94 100644
--- a/packages/SettingsProvider/res/values-sk/strings.xml
+++ b/packages/SettingsProvider/res/values-sk/strings.xml
@@ -20,4 +20,10 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Ukladací priestor nastavení"</string>
+    <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsProvider/res/values-sl/strings.xml b/packages/SettingsProvider/res/values-sl/strings.xml
index 3d7768d..28a9937 100644
--- a/packages/SettingsProvider/res/values-sl/strings.xml
+++ b/packages/SettingsProvider/res/values-sl/strings.xml
@@ -20,4 +20,10 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Shramba nastavitev"</string>
+    <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsProvider/res/values-sq/strings.xml b/packages/SettingsProvider/res/values-sq/strings.xml
index a8e66d5..977fe02 100644
--- a/packages/SettingsProvider/res/values-sq/strings.xml
+++ b/packages/SettingsProvider/res/values-sq/strings.xml
@@ -20,4 +20,10 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Hapësira ruajtëse e \"Cilësimeve\""</string>
+    <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsProvider/res/values-sr/strings.xml b/packages/SettingsProvider/res/values-sr/strings.xml
index 7082761..74b9dde 100644
--- a/packages/SettingsProvider/res/values-sr/strings.xml
+++ b/packages/SettingsProvider/res/values-sr/strings.xml
@@ -20,4 +20,10 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Подешавања складишта"</string>
+    <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsProvider/res/values-sv/strings.xml b/packages/SettingsProvider/res/values-sv/strings.xml
index b6de084..1444626 100644
--- a/packages/SettingsProvider/res/values-sv/strings.xml
+++ b/packages/SettingsProvider/res/values-sv/strings.xml
@@ -20,4 +20,10 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Lagring av inställningar"</string>
+    <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsProvider/res/values-sw/strings.xml b/packages/SettingsProvider/res/values-sw/strings.xml
index d17f60b..c244d88 100644
--- a/packages/SettingsProvider/res/values-sw/strings.xml
+++ b/packages/SettingsProvider/res/values-sw/strings.xml
@@ -20,4 +20,10 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Hifadhi ya Mipangilio"</string>
+    <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsProvider/res/values-ta/strings.xml b/packages/SettingsProvider/res/values-ta/strings.xml
index 7a86878..b26c875 100644
--- a/packages/SettingsProvider/res/values-ta/strings.xml
+++ b/packages/SettingsProvider/res/values-ta/strings.xml
@@ -20,4 +20,10 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"அமைப்புகளின் சேமிப்பிடம்"</string>
+    <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsProvider/res/values-te/strings.xml b/packages/SettingsProvider/res/values-te/strings.xml
index e51ba88..2a4971a 100644
--- a/packages/SettingsProvider/res/values-te/strings.xml
+++ b/packages/SettingsProvider/res/values-te/strings.xml
@@ -20,4 +20,10 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"సెట్టింగ్‌ల నిల్వ"</string>
+    <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsProvider/res/values-th/strings.xml b/packages/SettingsProvider/res/values-th/strings.xml
index ae8ba6a..db47654 100644
--- a/packages/SettingsProvider/res/values-th/strings.xml
+++ b/packages/SettingsProvider/res/values-th/strings.xml
@@ -20,4 +20,10 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"ที่เก็บข้อมูลการตั้งค่า"</string>
+    <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsProvider/res/values-tl/strings.xml b/packages/SettingsProvider/res/values-tl/strings.xml
index 0fe535e..71c6266 100644
--- a/packages/SettingsProvider/res/values-tl/strings.xml
+++ b/packages/SettingsProvider/res/values-tl/strings.xml
@@ -20,4 +20,10 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Storage ng Mga Setting"</string>
+    <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsProvider/res/values-tr/strings.xml b/packages/SettingsProvider/res/values-tr/strings.xml
index e99e99b..4737a1e 100644
--- a/packages/SettingsProvider/res/values-tr/strings.xml
+++ b/packages/SettingsProvider/res/values-tr/strings.xml
@@ -20,4 +20,10 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Ayarlar Deposu"</string>
+    <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsProvider/res/values-uk/strings.xml b/packages/SettingsProvider/res/values-uk/strings.xml
index 900dd07..2c77c6a61 100644
--- a/packages/SettingsProvider/res/values-uk/strings.xml
+++ b/packages/SettingsProvider/res/values-uk/strings.xml
@@ -20,4 +20,10 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Сховище налаштувань"</string>
+    <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsProvider/res/values-ur/strings.xml b/packages/SettingsProvider/res/values-ur/strings.xml
index e79249b..31694e0 100644
--- a/packages/SettingsProvider/res/values-ur/strings.xml
+++ b/packages/SettingsProvider/res/values-ur/strings.xml
@@ -20,4 +20,10 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"ترتیبات کا اسٹوریج"</string>
+    <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsProvider/res/values-uz/strings.xml b/packages/SettingsProvider/res/values-uz/strings.xml
index 38f0ce5..86a980e 100644
--- a/packages/SettingsProvider/res/values-uz/strings.xml
+++ b/packages/SettingsProvider/res/values-uz/strings.xml
@@ -20,4 +20,10 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Sozlamalar xotirasi"</string>
+    <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsProvider/res/values-vi/strings.xml b/packages/SettingsProvider/res/values-vi/strings.xml
index 015fbfd..6476927 100644
--- a/packages/SettingsProvider/res/values-vi/strings.xml
+++ b/packages/SettingsProvider/res/values-vi/strings.xml
@@ -20,4 +20,10 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Lưu trữ bộ nhớ"</string>
+    <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsProvider/res/values-zh-rCN/strings.xml b/packages/SettingsProvider/res/values-zh-rCN/strings.xml
index 11c5d6c..1395912 100644
--- a/packages/SettingsProvider/res/values-zh-rCN/strings.xml
+++ b/packages/SettingsProvider/res/values-zh-rCN/strings.xml
@@ -20,4 +20,10 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"设置存储"</string>
+    <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsProvider/res/values-zh-rHK/strings.xml b/packages/SettingsProvider/res/values-zh-rHK/strings.xml
index 977c9b9..2845264 100644
--- a/packages/SettingsProvider/res/values-zh-rHK/strings.xml
+++ b/packages/SettingsProvider/res/values-zh-rHK/strings.xml
@@ -20,4 +20,10 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"設定儲存空間"</string>
+    <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsProvider/res/values-zh-rTW/strings.xml b/packages/SettingsProvider/res/values-zh-rTW/strings.xml
index 977c9b9..2845264 100644
--- a/packages/SettingsProvider/res/values-zh-rTW/strings.xml
+++ b/packages/SettingsProvider/res/values-zh-rTW/strings.xml
@@ -20,4 +20,10 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"設定儲存空間"</string>
+    <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsProvider/res/values-zu/strings.xml b/packages/SettingsProvider/res/values-zu/strings.xml
index cb5a781..8c1d9e0 100644
--- a/packages/SettingsProvider/res/values-zu/strings.xml
+++ b/packages/SettingsProvider/res/values-zu/strings.xml
@@ -20,4 +20,10 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Izilungiselelo zesitoreji"</string>
+    <!-- no translation found for wifi_softap_config_change (5338670993556993667) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (7600005249167787750) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_detailed (2504664754843959730) -->
+    <skip />
 </resources>
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/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index 55a51da..33e0fd2 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -2248,12 +2248,6 @@
                 SecureSettingsProto.Notification.IN_CALL_NOTIFICATION_ENABLED);
         p.end(notificationToken);
 
-        final long packageVerifierToken = p.start(SecureSettingsProto.PACKAGE_VERIFIER);
-        dumpSetting(s, p,
-                Settings.Secure.PACKAGE_VERIFIER_USER_CONSENT,
-                SecureSettingsProto.PackageVerifier.USER_CONSENT);
-        p.end(packageVerifierToken);
-
         final long parentalControlToken = p.start(SecureSettingsProto.PARENTAL_CONTROL);
         dumpSetting(s, p,
                 Settings.Secure.PARENTAL_CONTROL_ENABLED,
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index f5d1ccf..0959de9 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -101,6 +101,7 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
@@ -383,6 +384,13 @@
                 break;
             }
 
+            case Settings.CALL_METHOD_SET_ALL_CONFIG: {
+                String prefix = getSettingPrefix(args);
+                Map<String, String> flags = getSettingFlags(args);
+                setAllConfigSettings(prefix, flags);
+                break;
+            }
+
             case Settings.CALL_METHOD_RESET_CONFIG: {
                 final int mode = getResetModeEnforcingPermission(args);
                 String prefix = getSettingPrefix(args);
@@ -1030,6 +1038,19 @@
                 MUTATION_OPERATION_INSERT, 0);
     }
 
+    private boolean setAllConfigSettings(String prefix, Map<String, String> keyValues) {
+        if (DEBUG) {
+            Slog.v(LOG_TAG, "setAllConfigSettings for prefix: " + prefix);
+        }
+
+        enforceWritePermission(Manifest.permission.WRITE_DEVICE_CONFIG);
+
+        synchronized (mLock) {
+            return mSettingsRegistry.setSettingsLocked(SETTINGS_TYPE_CONFIG, UserHandle.USER_SYSTEM,
+                    prefix, keyValues, resolveCallingPackage());
+        }
+    }
+
     private boolean deleteConfigSetting(String name) {
         if (DEBUG) {
             Slog.v(LOG_TAG, "deleteConfigSetting(" + name + ")");
@@ -2117,6 +2138,11 @@
         return (args != null) ? args.getString(Settings.CALL_METHOD_PREFIX_KEY) : null;
     }
 
+    private static Map<String, String> getSettingFlags(Bundle args) {
+        return (args != null) ? (HashMap) args.getSerializable(Settings.CALL_METHOD_FLAGS_KEY)
+                : Collections.emptyMap();
+    }
+
     private static boolean getSettingMakeDefault(Bundle args) {
         return (args != null) && args.getBoolean(Settings.CALL_METHOD_MAKE_DEFAULT_KEY);
     }
@@ -2485,7 +2511,7 @@
             final int key = makeKey(type, userId);
             SettingsState settingsState = peekSettingsStateLocked(key);
             if (settingsState == null) {
-                return new ArrayList<String>();
+                return new ArrayList<>();
             }
             return settingsState.getSettingNamesLocked();
         }
@@ -2645,6 +2671,22 @@
             return success;
         }
 
+        public boolean setSettingsLocked(int type, int userId, String prefix,
+                Map<String, String> keyValues, String packageName) {
+            final int key = makeKey(type, userId);
+
+            SettingsState settingsState = peekSettingsStateLocked(key);
+            if (settingsState != null) {
+                List<String> changedSettings =
+                        settingsState.setSettingsLocked(prefix, keyValues, packageName);
+                if (!changedSettings.isEmpty()) {
+                    notifyForConfigSettingsChangeLocked(key, prefix, changedSettings);
+                }
+            }
+
+            return settingsState != null;
+        }
+
         public boolean deleteSettingLocked(int type, int userId, String name, boolean forceNotify,
                 Set<String> criticalSettings) {
             final int key = makeKey(type, userId);
@@ -3043,6 +3085,28 @@
             mHandler.obtainMessage(MyHandler.MSG_NOTIFY_DATA_CHANGED).sendToTarget();
         }
 
+        private void notifyForConfigSettingsChangeLocked(int key, String prefix,
+                List<String> changedSettings) {
+
+            // Increment the generation first, so observers always see the new value
+            mGenerationRegistry.incrementGeneration(key);
+
+            StringBuilder stringBuilder = new StringBuilder(prefix);
+            for (int i = 0; i < changedSettings.size(); ++i) {
+                stringBuilder.append(changedSettings.get(i).split("/")[1]).append("/");
+            }
+
+            final long token = Binder.clearCallingIdentity();
+            try {
+                notifySettingChangeForRunningUsers(key, stringBuilder.toString());
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+
+            // Always notify that our data changed
+            mHandler.obtainMessage(MyHandler.MSG_NOTIFY_DATA_CHANGED).sendToTarget();
+        }
+
         private void maybeNotifyProfiles(int type, int userId, Uri uri, String name,
                 Collection<String> keysCloned) {
             if (keysCloned.contains(name)) {
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
index de6a3a8..4731e68 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
@@ -64,6 +64,7 @@
 import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Map;
 import java.util.Objects;
 
 /**
@@ -416,6 +417,57 @@
     }
 
     // The settings provider must hold its lock when calling here.
+    // Returns the list of keys which changed (added, updated, or deleted).
+    @GuardedBy("mLock")
+    public List<String> setSettingsLocked(String prefix, Map<String, String> keyValues,
+            String packageName) {
+        List<String> changedKeys = new ArrayList<>();
+        // Delete old keys with the prefix that are not part of the new set.
+        for (int i = 0; i < mSettings.keySet().size(); ++i) {
+            String key = mSettings.keyAt(i);
+            if (key.startsWith(prefix) && !keyValues.containsKey(key)) {
+                Setting oldState = mSettings.remove(key);
+
+                StatsLog.write(StatsLog.SETTING_CHANGED, key, /* value= */ "", /* newValue= */ "",
+                        oldState.value, /* tag */ "", false, getUserIdFromKey(mKey),
+                        StatsLog.SETTING_CHANGED__REASON__DELETED);
+                addHistoricalOperationLocked(HISTORICAL_OPERATION_DELETE, oldState);
+                changedKeys.add(key); // key was removed
+            }
+        }
+
+        // Update/add new keys
+        for (String key : keyValues.keySet()) {
+            String value = keyValues.get(key);
+            String oldValue = null;
+            Setting state = mSettings.get(key);
+            if (state == null) {
+                state = new Setting(key, value, false, packageName, null);
+                mSettings.put(key, state);
+                changedKeys.add(key); // key was added
+            } else if (state.value != value) {
+                oldValue = state.value;
+                state.update(value, false, packageName, null, true);
+                changedKeys.add(key); // key was updated
+            } else {
+                // this key/value already exists, no change and no logging necessary
+                continue;
+            }
+
+            StatsLog.write(StatsLog.SETTING_CHANGED, key, value, state.value, oldValue,
+                    /* tag */ null, /* make default */ false,
+                    getUserIdFromKey(mKey), StatsLog.SETTING_CHANGED__REASON__UPDATED);
+            addHistoricalOperationLocked(HISTORICAL_OPERATION_UPDATE, state);
+        }
+
+        if (!changedKeys.isEmpty()) {
+            scheduleWriteIfNeededLocked();
+        }
+
+        return changedKeys;
+    }
+
+    // The settings provider must hold its lock when calling here.
     public void persistSyncLocked() {
         mHandler.removeMessages(MyHandler.MSG_PERSIST_SETTINGS);
         doWriteState();
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/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
index 289ac80..7b022a2 100644
--- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
+++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
@@ -662,7 +662,6 @@
                  Settings.Secure.NIGHT_DISPLAY_LAST_ACTIVATED_TIME,
                  Settings.Secure.NUM_ROTATION_SUGGESTIONS_ACCEPTED,
                  Settings.Secure.ODI_CAPTIONS_ENABLED,
-                 Settings.Secure.PACKAGE_VERIFIER_USER_CONSENT,
                  Settings.Secure.PARENTAL_CONTROL_LAST_UPDATE,
                  Settings.Secure.PAYMENT_SERVICE_SEARCH_URI,
                  Settings.Secure.PRINT_SERVICE_SEARCH_URI,
diff --git a/packages/SystemUI/res/layout/notif_half_shelf.xml b/packages/SystemUI/res/layout/notif_half_shelf.xml
index 26c8872..d36c1a8 100644
--- a/packages/SystemUI/res/layout/notif_half_shelf.xml
+++ b/packages/SystemUI/res/layout/notif_half_shelf.xml
@@ -46,7 +46,9 @@
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
                 android:padding="8dp"
-                android:orientation="horizontal" >
+                android:orientation="horizontal"
+                android:clickable="true"
+                android:foreground="?android:attr/selectableItemBackground" >
 
                 <ImageView
                     android:id="@+id/icon"
diff --git a/packages/SystemUI/res/layout/notif_half_shelf_row.xml b/packages/SystemUI/res/layout/notif_half_shelf_row.xml
index b95d5e9..c863e02 100644
--- a/packages/SystemUI/res/layout/notif_half_shelf_row.xml
+++ b/packages/SystemUI/res/layout/notif_half_shelf_row.xml
@@ -20,7 +20,9 @@
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:padding="8dp"
-    android:orientation="horizontal" >
+    android:clickable="true"
+    android:orientation="horizontal"
+    android:foreground="?android:attr/selectableItemBackground" >
 
     <!-- This is where an icon would go *if we wanted one* **wink** -->
     <Space
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/src/com/android/systemui/broadcast/UserBroadcastDispatcher.kt b/packages/SystemUI/src/com/android/systemui/broadcast/UserBroadcastDispatcher.kt
index d50666c..b2942bb 100644
--- a/packages/SystemUI/src/com/android/systemui/broadcast/UserBroadcastDispatcher.kt
+++ b/packages/SystemUI/src/com/android/systemui/broadcast/UserBroadcastDispatcher.kt
@@ -28,6 +28,7 @@
 import android.util.ArraySet
 import android.util.Log
 import androidx.annotation.MainThread
+import androidx.annotation.VisibleForTesting
 import com.android.internal.util.Preconditions
 import com.android.systemui.Dumpable
 import java.io.FileDescriptor
@@ -78,6 +79,14 @@
     private val actionsToReceivers = ArrayMap<String, MutableSet<ReceiverData>>()
     private val receiverToReceiverData = ArrayMap<BroadcastReceiver, MutableSet<ReceiverData>>()
 
+    @VisibleForTesting
+    internal fun isReceiverReferenceHeld(receiver: BroadcastReceiver): Boolean {
+        return receiverToReceiverData.contains(receiver) ||
+                actionsToReceivers.any {
+            it.value.any { it.receiver == receiver }
+        }
+    }
+
     // Only call on BG thread as it reads from the maps
     private fun createFilter(): IntentFilter {
         Preconditions.checkState(bgHandler.looper.isCurrentThread,
@@ -142,7 +151,7 @@
         if (DEBUG) Log.w(TAG, "Unregister receiver: $receiver")
         val actions = receiverToReceiverData.getOrElse(receiver) { return }
                 .flatMap { it.filter.actionsIterator().asSequence().asIterable() }.toSet()
-        receiverToReceiverData.get(receiver)?.clear()
+        receiverToReceiverData.remove(receiver)?.clear()
         var changed = false
         actions.forEach { action ->
             actionsToReceivers.get(action)?.removeIf { it.receiver == receiver }
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
index 51c2ddc..b5845947 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
@@ -419,9 +419,7 @@
                                 new GlobalActionsPanelPlugin.Callbacks() {
                                     @Override
                                     public void dismissGlobalActionsMenu() {
-                                        if (mDialog != null) {
-                                            mDialog.dismiss();
-                                        }
+                                        dismissDialog();
                                     }
 
                                     @Override
@@ -916,6 +914,9 @@
 
     /** {@inheritDoc} */
     public void onDismiss(DialogInterface dialog) {
+        if (mDialog == dialog) {
+            mDialog = null;
+        }
         mWindowManagerFuncs.onGlobalActionsHidden();
         if (mShowSilentToggle) {
             try {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
index 7fb5207..ff34be0 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
@@ -90,7 +90,8 @@
     public QSCustomizer(Context context, AttributeSet attrs,
             LightBarController lightBarController,
             KeyguardStateController keyguardStateController,
-            ScreenLifecycle screenLifecycle) {
+            ScreenLifecycle screenLifecycle,
+            TileQueryHelper tileQueryHelper) {
         super(new ContextThemeWrapper(context, R.style.edit_theme), attrs);
 
         LayoutInflater.from(getContext()).inflate(R.layout.qs_customize_panel_content, this);
@@ -113,7 +114,8 @@
         mRecyclerView = findViewById(android.R.id.list);
         mTransparentView = findViewById(R.id.customizer_transparent_view);
         mTileAdapter = new TileAdapter(getContext());
-        mTileQueryHelper = new TileQueryHelper(context, mTileAdapter);
+        mTileQueryHelper = tileQueryHelper;
+        mTileQueryHelper.setListener(mTileAdapter);
         mRecyclerView.setAdapter(mTileAdapter);
         mTileAdapter.getItemTouchHelper().attachToRecyclerView(mRecyclerView);
         GridLayoutManager layout = new GridLayoutManager(getContext(), 3);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java b/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
index 7006249..0a9100f 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
@@ -33,8 +33,9 @@
 import android.util.ArraySet;
 import android.widget.Button;
 
-import com.android.systemui.Dependency;
 import com.android.systemui.R;
+import com.android.systemui.dagger.qualifiers.BgHandler;
+import com.android.systemui.dagger.qualifiers.MainHandler;
 import com.android.systemui.plugins.qs.QSTile;
 import com.android.systemui.plugins.qs.QSTile.State;
 import com.android.systemui.qs.QSTileHost;
@@ -47,6 +48,8 @@
 import java.util.Collection;
 import java.util.List;
 
+import javax.inject.Inject;
+
 public class TileQueryHelper {
     private static final String TAG = "TileQueryHelper";
 
@@ -55,15 +58,20 @@
     private final Handler mBgHandler;
     private final Handler mMainHandler;
     private final Context mContext;
-    private final TileStateListener mListener;
+    private TileStateListener mListener;
 
     private boolean mFinished;
 
-    public TileQueryHelper(Context context, TileStateListener listener) {
+    @Inject
+    public TileQueryHelper(Context context,
+            @MainHandler Handler mainHandler, @BgHandler Handler bgHandler) {
         mContext = context;
+        mMainHandler = mainHandler;
+        mBgHandler = bgHandler;
+    }
+
+    public void setListener(TileStateListener listener) {
         mListener = listener;
-        mBgHandler = new Handler(Dependency.get(Dependency.BG_LOOPER));
-        mMainHandler = Dependency.get(Dependency.MAIN_HANDLER);
     }
 
     public void queryTiles(QSTileHost host) {
@@ -178,7 +186,9 @@
     private void notifyTilesChanged(final boolean finished) {
         final ArrayList<TileInfo> tilesToReturn = new ArrayList<>(mTiles);
         mMainHandler.post(() -> {
-            mListener.onTilesChanged(tilesToReturn);
+            if (mListener != null) {
+                mListener.onTilesChanged(tilesToReturn);
+            }
             mFinished = finished;
         });
     }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/NfcTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/NfcTile.java
index 8bbfd24..f0140ba 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/NfcTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/NfcTile.java
@@ -132,7 +132,7 @@
     private NfcAdapter getAdapter() {
         if (mAdapter == null) {
             try {
-                mAdapter = NfcAdapter.getNfcAdapter(mContext);
+                mAdapter = NfcAdapter.getDefaultAdapter(mContext);
             } catch (UnsupportedOperationException e) {
                 mAdapter = null;
             }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ChannelEditorListView.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ChannelEditorListView.kt
index 6faf77e..983315e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ChannelEditorListView.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ChannelEditorListView.kt
@@ -129,6 +129,8 @@
         iconView = findViewById(R.id.icon)
         channelName = findViewById(R.id.app_name)
         switch = findViewById(R.id.toggle)
+
+        setOnClickListener { switch.toggle() }
     }
 }
 
@@ -156,6 +158,7 @@
                 controller.proposeEditForChannel(it, if (b) it.importance else IMPORTANCE_NONE)
             }
         }
+        setOnClickListener { switch.toggle() }
     }
 
     private fun updateViews() {
diff --git a/packages/SystemUI/src/com/android/systemui/wm/DisplayWindowController.java b/packages/SystemUI/src/com/android/systemui/wm/DisplayWindowController.java
index f3487fb..19fff79 100644
--- a/packages/SystemUI/src/com/android/systemui/wm/DisplayWindowController.java
+++ b/packages/SystemUI/src/com/android/systemui/wm/DisplayWindowController.java
@@ -16,8 +16,10 @@
 
 package com.android.systemui.wm;
 
+import android.content.res.Configuration;
 import android.os.Handler;
 import android.os.RemoteException;
+import android.util.Slog;
 import android.util.SparseArray;
 import android.view.IDisplayWindowListener;
 import android.view.IDisplayWindowRotationCallback;
@@ -40,6 +42,8 @@
  */
 @Singleton
 public class DisplayWindowController {
+    private static final String TAG = "DisplayWindowController";
+
     private final Handler mHandler;
 
     private final ArrayList<OnDisplayWindowRotationController> mRotationControllers =
@@ -84,8 +88,26 @@
                             DisplayRecord record = new DisplayRecord();
                             record.mDisplayId = displayId;
                             mDisplays.put(displayId, record);
-                            for (DisplayWindowListener l : mDisplayChangedListeners) {
-                                l.onDisplayAdded(displayId);
+                            for (int i = 0; i < mDisplayChangedListeners.size(); ++i) {
+                                mDisplayChangedListeners.get(i).onDisplayAdded(displayId);
+                            }
+                        }
+                    });
+                }
+
+                @Override
+                public void onDisplayConfigurationChanged(int displayId, Configuration newConfig) {
+                    mHandler.post(() -> {
+                        synchronized (mDisplays) {
+                            DisplayRecord dr = mDisplays.get(displayId);
+                            if (dr == null) {
+                                Slog.w(TAG, "Skipping Display Configuration change on non-added"
+                                        + " display.");
+                                return;
+                            }
+                            for (int i = 0; i < mDisplayChangedListeners.size(); ++i) {
+                                mDisplayChangedListeners.get(i).onDisplayConfigurationChanged(
+                                        displayId, newConfig);
                             }
                         }
                     });
@@ -118,8 +140,8 @@
     }
 
     /**
-     * Add a display window-container listener. It will get notified when displays are
-     * added/removed from the WM hierarchy.
+     * Add a display window-container listener. It will get notified whenever a display's
+     * configuration changes or when displays are added/removed from the WM hierarchy.
      */
     public void addDisplayWindowListener(DisplayWindowListener listener) {
         synchronized (mDisplays) {
@@ -165,7 +187,8 @@
     }
 
     /**
-     * Gets notified when a display is added/removed to the WM hierarchy.
+     * Gets notified when a display is added/removed to the WM hierarchy and when a display's
+     * window-configuration changes.
      *
      * @see IDisplayWindowListener
      */
@@ -176,6 +199,11 @@
         void onDisplayAdded(int displayId);
 
         /**
+         * Called when a display's window-container configuration changes.
+         */
+        void onDisplayConfigurationChanged(int displayId, Configuration newConfig);
+
+        /**
          * Called when a display is removed.
          */
         void onDisplayRemoved(int displayId);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/broadcast/UserBroadcastDispatcherTest.kt b/packages/SystemUI/tests/src/com/android/systemui/broadcast/UserBroadcastDispatcherTest.kt
index e838d9e..21ed155 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/broadcast/UserBroadcastDispatcherTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/broadcast/UserBroadcastDispatcherTest.kt
@@ -77,7 +77,7 @@
     private lateinit var argumentCaptor: ArgumentCaptor<IntentFilter>
 
     private lateinit var testableLooper: TestableLooper
-    private lateinit var universalBroadcastReceiver: UserBroadcastDispatcher
+    private lateinit var userBroadcastDispatcher: UserBroadcastDispatcher
     private lateinit var intentFilter: IntentFilter
     private lateinit var intentFilterOther: IntentFilter
     private lateinit var handler: Handler
@@ -88,9 +88,9 @@
         testableLooper = TestableLooper.get(this)
         handler = Handler(testableLooper.looper)
 
-        universalBroadcastReceiver = UserBroadcastDispatcher(
+        userBroadcastDispatcher = UserBroadcastDispatcher(
                 mockContext, USER_ID, handler, testableLooper.looper)
-        universalBroadcastReceiver.pendingResult = mPendingResult
+        userBroadcastDispatcher.pendingResult = mPendingResult
     }
 
     @Test
@@ -107,11 +107,11 @@
     fun testSingleReceiverRegistered() {
         intentFilter = IntentFilter(ACTION_1)
 
-        universalBroadcastReceiver.registerReceiver(
+        userBroadcastDispatcher.registerReceiver(
                 ReceiverData(broadcastReceiver, intentFilter, mockHandler, USER_HANDLE))
         testableLooper.processAllMessages()
 
-        assertTrue(universalBroadcastReceiver.isRegistered())
+        assertTrue(userBroadcastDispatcher.isRegistered())
         verify(mockContext).registerReceiverAsUser(
                 any(),
                 eq(USER_HANDLE),
@@ -127,19 +127,19 @@
     fun testSingleReceiverUnregistered() {
         intentFilter = IntentFilter(ACTION_1)
 
-        universalBroadcastReceiver.registerReceiver(
+        userBroadcastDispatcher.registerReceiver(
                 ReceiverData(broadcastReceiver, intentFilter, mockHandler, USER_HANDLE))
         testableLooper.processAllMessages()
         reset(mockContext)
 
-        assertTrue(universalBroadcastReceiver.isRegistered())
+        assertTrue(userBroadcastDispatcher.isRegistered())
 
-        universalBroadcastReceiver.unregisterReceiver(broadcastReceiver)
+        userBroadcastDispatcher.unregisterReceiver(broadcastReceiver)
         testableLooper.processAllMessages()
 
         verify(mockContext, atLeastOnce()).unregisterReceiver(any())
         verify(mockContext, never()).registerReceiverAsUser(any(), any(), any(), any(), any())
-        assertFalse(universalBroadcastReceiver.isRegistered())
+        assertFalse(userBroadcastDispatcher.isRegistered())
     }
 
     @Test
@@ -150,13 +150,13 @@
             addCategory(CATEGORY_2)
         }
 
-        universalBroadcastReceiver.registerReceiver(
+        userBroadcastDispatcher.registerReceiver(
                 ReceiverData(broadcastReceiver, intentFilter, mockHandler, USER_HANDLE))
-        universalBroadcastReceiver.registerReceiver(
+        userBroadcastDispatcher.registerReceiver(
                 ReceiverData(broadcastReceiverOther, intentFilterOther, mockHandler, USER_HANDLE))
 
         testableLooper.processAllMessages()
-        assertTrue(universalBroadcastReceiver.isRegistered())
+        assertTrue(userBroadcastDispatcher.isRegistered())
 
         verify(mockContext, times(2)).registerReceiverAsUser(
                 any(),
@@ -178,14 +178,14 @@
         intentFilter = IntentFilter(ACTION_1)
         intentFilterOther = IntentFilter(ACTION_2)
 
-        universalBroadcastReceiver.registerReceiver(
+        userBroadcastDispatcher.registerReceiver(
                 ReceiverData(broadcastReceiver, intentFilter, handler, USER_HANDLE))
-        universalBroadcastReceiver.registerReceiver(
+        userBroadcastDispatcher.registerReceiver(
                 ReceiverData(broadcastReceiverOther, intentFilterOther, handler, USER_HANDLE))
 
         val intent = Intent(ACTION_2)
 
-        universalBroadcastReceiver.onReceive(mockContext, intent)
+        userBroadcastDispatcher.onReceive(mockContext, intent)
         testableLooper.processAllMessages()
 
         verify(broadcastReceiver, never()).onReceive(any(), any())
@@ -197,14 +197,14 @@
         intentFilter = IntentFilter(ACTION_1)
         intentFilterOther = IntentFilter(ACTION_2)
 
-        universalBroadcastReceiver.registerReceiver(
+        userBroadcastDispatcher.registerReceiver(
                 ReceiverData(broadcastReceiver, intentFilter, handler, USER_HANDLE))
-        universalBroadcastReceiver.registerReceiver(
+        userBroadcastDispatcher.registerReceiver(
                 ReceiverData(broadcastReceiver, intentFilterOther, handler, USER_HANDLE))
 
         val intent = Intent(ACTION_2)
 
-        universalBroadcastReceiver.onReceive(mockContext, intent)
+        userBroadcastDispatcher.onReceive(mockContext, intent)
         testableLooper.processAllMessages()
 
         verify(broadcastReceiver).onReceive(mockContext, intent)
@@ -217,14 +217,14 @@
         intentFilterOther = IntentFilter(ACTION_1)
         intentFilterOther.addCategory(CATEGORY_2)
 
-        universalBroadcastReceiver.registerReceiver(
+        userBroadcastDispatcher.registerReceiver(
                 ReceiverData(broadcastReceiver, intentFilter, handler, USER_HANDLE))
-        universalBroadcastReceiver.registerReceiver(
+        userBroadcastDispatcher.registerReceiver(
                 ReceiverData(broadcastReceiverOther, intentFilterOther, handler, USER_HANDLE))
 
         val intent = Intent(ACTION_1)
 
-        universalBroadcastReceiver.onReceive(mockContext, intent)
+        userBroadcastDispatcher.onReceive(mockContext, intent)
         testableLooper.processAllMessages()
 
         verify(broadcastReceiver).onReceive(mockContext, intent)
@@ -234,15 +234,32 @@
     @Test
     fun testPendingResult() {
         intentFilter = IntentFilter(ACTION_1)
-        universalBroadcastReceiver.registerReceiver(
+        userBroadcastDispatcher.registerReceiver(
                 ReceiverData(broadcastReceiver, intentFilter, handler, USER_HANDLE))
 
         val intent = Intent(ACTION_1)
-        universalBroadcastReceiver.onReceive(mockContext, intent)
+        userBroadcastDispatcher.onReceive(mockContext, intent)
 
         testableLooper.processAllMessages()
 
         verify(broadcastReceiver).onReceive(mockContext, intent)
         verify(broadcastReceiver).pendingResult = mPendingResult
     }
+
+    @Test
+    fun testRemoveReceiverReferences() {
+        intentFilter = IntentFilter(ACTION_1)
+        userBroadcastDispatcher.registerReceiver(
+                ReceiverData(broadcastReceiver, intentFilter, handler, USER_HANDLE))
+
+        intentFilterOther = IntentFilter(ACTION_1)
+        intentFilterOther.addAction(ACTION_2)
+        userBroadcastDispatcher.registerReceiver(
+                ReceiverData(broadcastReceiverOther, intentFilterOther, handler, USER_HANDLE))
+
+        userBroadcastDispatcher.unregisterReceiver(broadcastReceiver)
+        testableLooper.processAllMessages()
+
+        assertFalse(userBroadcastDispatcher.isReceiverReferenceHeld(broadcastReceiver))
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileQueryHelperTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileQueryHelperTest.java
index 9e226f6..b41512c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileQueryHelperTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileQueryHelperTest.java
@@ -36,6 +36,8 @@
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
+import android.os.Handler;
+import android.os.Looper;
 import android.provider.Settings;
 import android.service.quicksettings.Tile;
 import android.testing.AndroidTestingRunner;
@@ -46,7 +48,6 @@
 
 import androidx.test.filters.SmallTest;
 
-import com.android.systemui.Dependency;
 import com.android.systemui.R;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.plugins.qs.QSTile;
@@ -99,12 +100,12 @@
     private QSTile.State mState;
     private TestableLooper mBGLooper;
     private TileQueryHelper mTileQueryHelper;
+    private Handler mMainHandler;
 
     @Before
     public void setup() {
         MockitoAnnotations.initMocks(this);
         mBGLooper = TestableLooper.get(this);
-        mDependency.injectTestDependency(Dependency.BG_LOOPER, mBGLooper.getLooper());
         mContext.setMockPackageManager(mPackageManager);
 
         mState = new QSTile.State();
@@ -122,7 +123,10 @@
                 }
         ).when(mQSTileHost).createTile(anyString());
 
-        mTileQueryHelper = new TileQueryHelper(mContext, mListener);
+        mMainHandler = new Handler(Looper.getMainLooper());
+        mTileQueryHelper = new TileQueryHelper(mContext, mMainHandler,
+                new Handler(mBGLooper.getLooper()));
+        mTileQueryHelper.setListener(mListener);
     }
 
     @Test
@@ -135,7 +139,7 @@
         mTileQueryHelper.queryTiles(mQSTileHost);
 
         mBGLooper.processAllMessages();
-        waitForIdleSync(Dependency.get(Dependency.MAIN_HANDLER));
+        waitForIdleSync(mMainHandler);
 
         assertTrue(mTileQueryHelper.isFinished());
     }
@@ -145,7 +149,7 @@
         mTileQueryHelper.queryTiles(mQSTileHost);
 
         mBGLooper.processAllMessages();
-        waitForIdleSync(Dependency.get(Dependency.MAIN_HANDLER));
+        waitForIdleSync(mMainHandler);
 
         verify(mListener, times(2)).onTilesChanged(any());
     }
@@ -160,7 +164,7 @@
         mTileQueryHelper.queryTiles(mQSTileHost);
 
         mBGLooper.processAllMessages();
-        waitForIdleSync(Dependency.get(Dependency.MAIN_HANDLER));
+        waitForIdleSync(mMainHandler);
 
         assertTrue(mTileQueryHelper.isFinished());
     }
@@ -175,7 +179,7 @@
         mTileQueryHelper.queryTiles(mQSTileHost);
 
         mBGLooper.processAllMessages();
-        waitForIdleSync(Dependency.get(Dependency.MAIN_HANDLER));
+        waitForIdleSync(mMainHandler);
 
         verify(mListener, atLeastOnce()).onTilesChanged(mCaptor.capture());
         List<String> specs = new ArrayList<>();
@@ -196,7 +200,7 @@
         mTileQueryHelper.queryTiles(mQSTileHost);
 
         mBGLooper.processAllMessages();
-        waitForIdleSync(Dependency.get(Dependency.MAIN_HANDLER));
+        waitForIdleSync(mMainHandler);
 
         verify(mListener, atLeastOnce()).onTilesChanged(mCaptor.capture());
         List<String> specs = new ArrayList<>();
@@ -217,7 +221,7 @@
         mTileQueryHelper.queryTiles(mQSTileHost);
 
         mBGLooper.processAllMessages();
-        waitForIdleSync(Dependency.get(Dependency.MAIN_HANDLER));
+        waitForIdleSync(mMainHandler);
 
         verify(mListener, atLeastOnce()).onTilesChanged(mCaptor.capture());
         List<String> specs = new ArrayList<>();
@@ -248,7 +252,7 @@
 
         mTileQueryHelper.queryTiles(mQSTileHost);
         mBGLooper.processAllMessages();
-        waitForIdleSync(Dependency.get(Dependency.MAIN_HANDLER));
+        waitForIdleSync(mMainHandler);
 
         verify(mListener, atLeastOnce()).onTilesChanged(mCaptor.capture());
         List<TileQueryHelper.TileInfo> tileInfos = mCaptor.getValue();
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/packages/Tethering/Android.bp b/packages/Tethering/Android.bp
index 61bfb92..7b35f4d 100644
--- a/packages/Tethering/Android.bp
+++ b/packages/Tethering/Android.bp
@@ -20,12 +20,14 @@
     srcs: [
         "src/**/*.java",
         ":framework-tethering-shared-srcs",
+        ":net-module-utils-srcs",
         ":services-tethering-shared-srcs",
         ":servicescore-tethering-src",
     ],
     static_libs: [
         "androidx.annotation_annotation",
         "netd_aidl_interface-java",
+        "netlink-client",
         "networkstack-aidl-interfaces-java",
         "android.hardware.tetheroffload.control-V1.0-java",
         "tethering-client",
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/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java
index cb858ac..339fc96 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java
@@ -1217,8 +1217,8 @@
                     if (mAccessibilityFocusedWindowId != windowId) {
                         clearAccessibilityFocusLocked(mAccessibilityFocusedWindowId);
                         setAccessibilityFocusedWindowLocked(windowId);
-                        mAccessibilityFocusNodeId = nodeId;
                     }
+                    mAccessibilityFocusNodeId = nodeId;
                 }
             } break;
 
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/content/pm/PackageManagerInternal.java b/services/core/java/android/content/pm/PackageManagerInternal.java
index dc24cff..e67d736 100644
--- a/services/core/java/android/content/pm/PackageManagerInternal.java
+++ b/services/core/java/android/content/pm/PackageManagerInternal.java
@@ -22,6 +22,7 @@
 import android.annotation.Nullable;
 import android.annotation.UserIdInt;
 import android.content.ComponentName;
+import android.content.ContentResolver;
 import android.content.Intent;
 import android.content.IntentSender;
 import android.content.pm.PackageManager.ApplicationInfoFlags;
@@ -244,12 +245,16 @@
 
     /**
      * Retrieve all activities that can be performed for the given intent.
+     * @param resolvedType the resolved type of the intent, which should be resolved via
+     * {@link Intent#resolveTypeIfNeeded(ContentResolver)} before passing to {@link PackageManager}
      * @param filterCallingUid The results will be filtered in the context of this UID instead
      * of the calling UID.
      * @see PackageManager#queryIntentActivities(Intent, int)
      */
-    public abstract List<ResolveInfo> queryIntentActivities(Intent intent,
-            @ResolveInfoFlags int flags, int filterCallingUid, int userId);
+    public abstract List<ResolveInfo> queryIntentActivities(
+            Intent intent, @Nullable String resolvedType, @ResolveInfoFlags int flags,
+            int filterCallingUid, int userId);
+
 
     /**
      * Retrieve all services that can be performed for the given intent.
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index a75d5d69..ce4cdc8 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -2186,6 +2186,11 @@
      */
     @VisibleForTesting
     public void systemReady() {
+        // Let PermissionMonitor#startMonitoring() running in the beginning of the systemReady
+        // before MultipathPolicyTracker.start(). Since mApps in PermissionMonitor needs to be
+        // populated first to ensure that listening network request which is sent by
+        // MultipathPolicyTracker won't be added NET_CAPABILITY_FOREGROUND capability.
+        mPermissionMonitor.startMonitoring();
         mProxyTracker.loadGlobalProxy();
         registerNetdEventCallback();
         mTethering.systemReady();
@@ -2206,8 +2211,6 @@
         mHandler.sendMessage(mHandler.obtainMessage(EVENT_CONFIGURE_ALWAYS_ON_NETWORKS));
 
         mHandler.sendMessage(mHandler.obtainMessage(EVENT_SYSTEM_READY));
-
-        mPermissionMonitor.startMonitoring();
     }
 
     /**
@@ -3185,7 +3188,7 @@
         if (!nai.networkCapabilities.hasTransport(TRANSPORT_VPN)) {
             updateAllVpnsCapabilities();
         }
-        rematchAllNetworksAndRequests(null, 0);
+        rematchAllNetworksAndRequests();
         mLingerMonitor.noteDisconnect(nai);
         if (nai.created) {
             // Tell netd to clean up the configuration for this network
@@ -3271,8 +3274,7 @@
                 }
             }
         }
-        rematchAllNetworksAndRequests(null, 0);
-        ensureRunningOnConnectivityServiceThread();
+        rematchAllNetworksAndRequests();
         if (nri.request.isRequest() && nri.mSatisfier == null) {
             sendUpdatedScoreToFactories(nri.request, null);
         }
@@ -3515,13 +3517,12 @@
         }
 
         if (accept != nai.networkMisc.acceptUnvalidated) {
-            int oldScore = nai.getCurrentScore();
             nai.networkMisc.acceptUnvalidated = accept;
             // If network becomes partial connectivity and user already accepted to use this
             // network, we should respect the user's option and don't need to popup the
             // PARTIAL_CONNECTIVITY notification to user again.
             nai.networkMisc.acceptPartialConnectivity = accept;
-            rematchAllNetworksAndRequests(nai, oldScore);
+            rematchAllNetworksAndRequests();
             sendUpdatedScoreToFactories(nai);
         }
 
@@ -3590,9 +3591,8 @@
             return;
         }
         if (!nai.avoidUnvalidated) {
-            int oldScore = nai.getCurrentScore();
             nai.avoidUnvalidated = true;
-            rematchAllNetworksAndRequests(nai, oldScore);
+            rematchAllNetworksAndRequests();
             sendUpdatedScoreToFactories(nai);
         }
     }
@@ -3693,7 +3693,7 @@
 
 
     private void rematchForAvoidBadWifiUpdate() {
-        rematchAllNetworksAndRequests(null, 0);
+        rematchAllNetworksAndRequests();
         for (NetworkAgentInfo nai: mNetworkAgentInfos.values()) {
             if (nai.networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
                 sendUpdatedScoreToFactories(nai);
@@ -5965,7 +5965,7 @@
         } else {
             // If the requestable capabilities have changed or the score changed, we can't have been
             // called by rematchNetworkAndRequests, so it's safe to start a rematch.
-            rematchAllNetworksAndRequests(nai, oldScore);
+            rematchAllNetworksAndRequests();
             notifyNetworkCallbacks(nai, ConnectivityManager.CALLBACK_CAP_CHANGED);
         }
 
@@ -6294,6 +6294,41 @@
         }
     }
 
+    private ArrayMap<NetworkRequestInfo, NetworkAgentInfo> computeRequestReassignmentForNetwork(
+            @NonNull final NetworkAgentInfo newNetwork) {
+        final int score = newNetwork.getCurrentScore();
+        final ArrayMap<NetworkRequestInfo, NetworkAgentInfo> reassignedRequests = new ArrayMap<>();
+        for (NetworkRequestInfo nri : mNetworkRequests.values()) {
+            // Process requests in the first pass and listens in the second pass. This allows us to
+            // change a network's capabilities depending on which requests it has. This is only
+            // correct if the change in capabilities doesn't affect whether the network satisfies
+            // requests or not, and doesn't affect the network's score.
+            if (nri.request.isListen()) continue;
+
+            final NetworkAgentInfo currentNetwork = nri.mSatisfier;
+            final boolean satisfies = newNetwork.satisfies(nri.request);
+            if (newNetwork == currentNetwork && satisfies) continue;
+
+            // check if it satisfies the NetworkCapabilities
+            if (VDBG) log("  checking if request is satisfied: " + nri.request);
+            if (satisfies) {
+                // next check if it's better than any current network we're using for
+                // this request
+                if (VDBG || DDBG) {
+                    log("currentScore = "
+                            + (currentNetwork != null ? currentNetwork.getCurrentScore() : 0)
+                            + ", newScore = " + score);
+                }
+                if (currentNetwork == null || currentNetwork.getCurrentScore() < score) {
+                    reassignedRequests.put(nri, newNetwork);
+                }
+            } else if (newNetwork.isSatisfyingRequest(nri.request.requestId)) {
+                reassignedRequests.put(nri, null);
+            }
+        }
+        return reassignedRequests;
+    }
+
     // Handles a network appearing or improving its score.
     //
     // - Evaluates all current NetworkRequests that can be
@@ -6307,10 +6342,6 @@
     // - Tears down newNetwork if it just became validated
     //   but turns out to be unneeded.
     //
-    // - If reapUnvalidatedNetworks==REAP, tears down unvalidated
-    //   networks that have no chance (i.e. even if validated)
-    //   of becoming the highest scoring network.
-    //
     // NOTE: This function only adds NetworkRequests that "newNetwork" could satisfy,
     // it does not remove NetworkRequests that other Networks could better satisfy.
     // If you need to handle decreases in score, use {@link rematchAllNetworksAndRequests}.
@@ -6318,11 +6349,8 @@
     // as it performs better by a factor of the number of Networks.
     //
     // @param newNetwork is the network to be matched against NetworkRequests.
-    // @param reapUnvalidatedNetworks indicates if an additional pass over all networks should be
-    //               performed to tear down unvalidated networks that have no chance (i.e. even if
-    //               validated) of becoming the highest scoring network.
-    private void rematchNetworkAndRequests(NetworkAgentInfo newNetwork,
-            ReapUnvalidatedNetworks reapUnvalidatedNetworks, long now) {
+    // @param now the time the rematch starts, as returned by SystemClock.elapsedRealtime();
+    private void rematchNetworkAndRequests(NetworkAgentInfo newNetwork, long now) {
         ensureRunningOnConnectivityServiceThread();
         if (!newNetwork.everConnected) return;
         boolean keep = newNetwork.isVPN();
@@ -6334,39 +6362,11 @@
 
         if (VDBG || DDBG) log("rematching " + newNetwork.name());
 
-        final ArrayMap<NetworkRequestInfo, NetworkAgentInfo> reassignedRequests = new ArrayMap<>();
+        final ArrayMap<NetworkRequestInfo, NetworkAgentInfo> reassignedRequests =
+                computeRequestReassignmentForNetwork(newNetwork);
 
         NetworkCapabilities nc = newNetwork.networkCapabilities;
         if (VDBG) log(" network has: " + nc);
-        for (NetworkRequestInfo nri : mNetworkRequests.values()) {
-            // Process requests in the first pass and listens in the second pass. This allows us to
-            // change a network's capabilities depending on which requests it has. This is only
-            // correct if the change in capabilities doesn't affect whether the network satisfies
-            // requests or not, and doesn't affect the network's score.
-            if (nri.request.isListen()) continue;
-
-            ensureRunningOnConnectivityServiceThread();
-            final NetworkAgentInfo currentNetwork = nri.mSatisfier;
-            final boolean satisfies = newNetwork.satisfies(nri.request);
-            if (newNetwork == currentNetwork && satisfies) continue;
-
-            // check if it satisfies the NetworkCapabilities
-            if (VDBG) log("  checking if request is satisfied: " + nri.request);
-            if (satisfies) {
-                // next check if it's better than any current network we're using for
-                // this request
-                if (VDBG || DDBG) {
-                    log("currentScore = " +
-                            (currentNetwork != null ? currentNetwork.getCurrentScore() : 0) +
-                            ", newScore = " + score);
-                }
-                if (currentNetwork == null || currentNetwork.getCurrentScore() < score) {
-                    reassignedRequests.put(nri, newNetwork);
-                }
-            } else if (newNetwork.isSatisfyingRequest(nri.request.requestId)) {
-                reassignedRequests.put(nri, null);
-            }
-        }
 
         // Find and migrate to this Network any NetworkRequests for
         // which this network is now the best.
@@ -6549,66 +6549,43 @@
                 mLegacyTypeTracker.add(TYPE_VPN, newNetwork);
             }
         }
-        if (reapUnvalidatedNetworks == ReapUnvalidatedNetworks.REAP) {
-            for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
-                if (unneeded(nai, UnneededFor.TEARDOWN)) {
-                    if (nai.getLingerExpiry() > 0) {
-                        // This network has active linger timers and no requests, but is not
-                        // lingering. Linger it.
-                        //
-                        // One way (the only way?) this can happen if this network is unvalidated
-                        // and became unneeded due to another network improving its score to the
-                        // point where this network will no longer be able to satisfy any requests
-                        // even if it validates.
-                        updateLingerState(nai, now);
-                    } else {
-                        if (DBG) log("Reaping " + nai.name());
-                        teardownUnneededNetwork(nai);
-                    }
-                }
-            }
-        }
     }
 
     /**
      * Attempt to rematch all Networks with NetworkRequests.  This may result in Networks
      * being disconnected.
-     * @param changed If only one Network's score or capabilities have been modified since the last
-     *         time this function was called, pass this Network in this argument, otherwise pass
-     *         null.
-     * @param oldScore If only one Network has been changed but its NetworkCapabilities have not
-     *         changed, pass in the Network's score (from getCurrentScore()) prior to the change via
-     *         this argument, otherwise pass {@code changed.getCurrentScore()} or 0 if
-     *         {@code changed} is {@code null}. This is because NetworkCapabilities influence a
-     *         network's score.
      */
-    private void rematchAllNetworksAndRequests(NetworkAgentInfo changed, int oldScore) {
-        // TODO: This may get slow.  The "changed" parameter is provided for future optimization
-        // to avoid the slowness.  It is not simply enough to process just "changed", for
-        // example in the case where "changed"'s score decreases and another network should begin
-        // satisfying a NetworkRequest that "changed" currently satisfies.
-
-        // Optimization: Only reprocess "changed" if its score improved.  This is safe because it
-        // can only add more NetworkRequests satisfied by "changed", and this is exactly what
-        // rematchNetworkAndRequests() handles.
+    private void rematchAllNetworksAndRequests() {
+        // TODO: This may be slow, and should be optimized. Unfortunately at this moment the
+        // processing is network-major instead of request-major (the code iterates through all
+        // networks, then for each it iterates for all requests), which is a problem for re-scoring
+        // requests. Once the code has switched to a request-major iteration style, this can
+        // be optimized to only do the processing needed.
         final long now = SystemClock.elapsedRealtime();
-        if (changed != null && oldScore < changed.getCurrentScore()) {
-            rematchNetworkAndRequests(changed, ReapUnvalidatedNetworks.REAP, now);
-        } else {
-            final NetworkAgentInfo[] nais = mNetworkAgentInfos.values().toArray(
-                    new NetworkAgentInfo[mNetworkAgentInfos.size()]);
-            // Rematch higher scoring networks first to prevent requests first matching a lower
-            // scoring network and then a higher scoring network, which could produce multiple
-            // callbacks and inadvertently unlinger networks.
-            Arrays.sort(nais);
-            for (NetworkAgentInfo nai : nais) {
-                rematchNetworkAndRequests(nai,
-                        // Only reap the last time through the loop.  Reaping before all rematching
-                        // is complete could incorrectly teardown a network that hasn't yet been
-                        // rematched.
-                        (nai != nais[nais.length-1]) ? ReapUnvalidatedNetworks.DONT_REAP
-                                : ReapUnvalidatedNetworks.REAP,
-                        now);
+        final NetworkAgentInfo[] nais = mNetworkAgentInfos.values().toArray(
+                new NetworkAgentInfo[mNetworkAgentInfos.size()]);
+        // Rematch higher scoring networks first to prevent requests first matching a lower
+        // scoring network and then a higher scoring network, which could produce multiple
+        // callbacks and inadvertently unlinger networks.
+        Arrays.sort(nais);
+        for (NetworkAgentInfo nai : nais) {
+            rematchNetworkAndRequests(nai, now);
+        }
+        for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
+            if (unneeded(nai, UnneededFor.TEARDOWN)) {
+                if (nai.getLingerExpiry() > 0) {
+                    // This network has active linger timers and no requests, but is not
+                    // lingering. Linger it.
+                    //
+                    // One way (the only way?) this can happen if this network is unvalidated
+                    // and became unneeded due to another network improving its score to the
+                    // point where this network will no longer be able to satisfy any requests
+                    // even if it validates.
+                    updateLingerState(nai, now);
+                } else {
+                    if (DBG) log("Reaping " + nai.name());
+                    teardownUnneededNetwork(nai);
+                }
             }
         }
     }
@@ -6707,8 +6684,7 @@
             }
 
             // Consider network even though it is not yet validated.
-            final long now = SystemClock.elapsedRealtime();
-            rematchNetworkAndRequests(networkAgent, ReapUnvalidatedNetworks.REAP, now);
+            rematchAllNetworksAndRequests();
 
             // This has to happen after matching the requests, because callbacks are just requests.
             notifyNetworkCallbacks(networkAgent, ConnectivityManager.CALLBACK_PRECHECK);
@@ -6729,7 +6705,7 @@
                 state == NetworkInfo.State.SUSPENDED)) {
             // going into or coming out of SUSPEND: re-score and notify
             if (networkAgent.getCurrentScore() != oldScore) {
-                rematchAllNetworksAndRequests(networkAgent, oldScore);
+                rematchAllNetworksAndRequests();
             }
             updateCapabilities(networkAgent.getCurrentScore(), networkAgent,
                     networkAgent.networkCapabilities);
@@ -6743,19 +6719,9 @@
     }
 
     private void updateNetworkScore(NetworkAgentInfo nai, NetworkScore ns) {
-        int score = ns.getIntExtension(NetworkScore.LEGACY_SCORE);
-        if (VDBG || DDBG) log("updateNetworkScore for " + nai.name() + " to " + score);
-        if (score < 0) {
-            loge("updateNetworkScore for " + nai.name() + " got a negative score (" + score +
-                    ").  Bumping score to min of 0");
-            score = 0;
-        }
-
-        final int oldScore = nai.getCurrentScore();
+        if (VDBG || DDBG) log("updateNetworkScore for " + nai.name() + " to " + ns);
         nai.setNetworkScore(ns);
-
-        rematchAllNetworksAndRequests(nai, oldScore);
-
+        rematchAllNetworksAndRequests();
         sendUpdatedScoreToFactories(nai);
     }
 
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index 34c5842..9ebe896 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -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/NetworkScoreService.java b/services/core/java/com/android/server/NetworkScoreService.java
index df5005e..b26ef92 100644
--- a/services/core/java/com/android/server/NetworkScoreService.java
+++ b/services/core/java/com/android/server/NetworkScoreService.java
@@ -58,12 +58,10 @@
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.content.PackageMonitor;
-import com.android.internal.os.TransferPipe;
 import com.android.internal.util.DumpUtils;
 import com.android.server.pm.permission.PermissionManagerServiceInternal;
 
 import java.io.FileDescriptor;
-import java.io.IOException;
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -903,17 +901,6 @@
             }
             writer.println("Current scorer: " + currentScorer);
 
-            sendCacheUpdateCallback(new BiConsumer<INetworkScoreCache, Object>() {
-                @Override
-                public void accept(INetworkScoreCache networkScoreCache, Object cookie) {
-                    try {
-                        TransferPipe.dumpAsync(networkScoreCache.asBinder(), fd, args);
-                    } catch (IOException | RemoteException e) {
-                        writer.println("Failed to dump score cache: " + e);
-                    }
-                }
-            }, getScoreCacheLists());
-
             synchronized (mServiceConnectionLock) {
                 if (mServiceConnection != null) {
                     mServiceConnection.dump(fd, writer, args);
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index dcc690f..a4bc3bd 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -80,6 +80,7 @@
 import android.os.IStoraged;
 import android.os.IVold;
 import android.os.IVoldListener;
+import android.os.IVoldMountCallback;
 import android.os.IVoldTaskListener;
 import android.os.Looper;
 import android.os.Message;
@@ -348,10 +349,6 @@
     @GuardedBy("mLock")
     private ArrayMap<String, CountDownLatch> mDiskScanLatches = new ArrayMap<>();
 
-    /** Map from volume ID to latches */
-    @GuardedBy("mLock")
-    private ArrayMap<String, CountDownLatch> mFuseVolumeReadyLatches = new ArrayMap<>();
-
     @GuardedBy("mLock")
     private IPackageMoveObserver mMoveCallback;
     @GuardedBy("mLock")
@@ -464,17 +461,6 @@
         }
     }
 
-    private CountDownLatch findOrCreateFuseVolumeReadyLatch(String volId) {
-        synchronized (mLock) {
-            CountDownLatch latch = mFuseVolumeReadyLatches.get(volId);
-            if (latch == null) {
-                latch = new CountDownLatch(1);
-                mFuseVolumeReadyLatches.put(volId, latch);
-            }
-            return latch;
-        }
-    }
-
     /** List of crypto types.
       * These must match CRYPT_TYPE_XXX in cryptfs.h AND their
       * corresponding commands in CommandListener.cpp */
@@ -612,7 +598,6 @@
     private static final int H_ABORT_IDLE_MAINT = 12;
     private static final int H_BOOT_COMPLETED = 13;
     private static final int H_COMPLETE_UNLOCK_USER = 14;
-    private static final int H_VOLUME_READY = 15;
 
     class StorageManagerServiceHandler extends Handler {
         public StorageManagerServiceHandler(Looper looper) {
@@ -673,22 +658,6 @@
                     }
                     break;
                 }
-                case H_VOLUME_READY: {
-                    final VolumeInfo vol = (VolumeInfo) msg.obj;
-                    try {
-                        mStorageSessionController.onVolumeReady(vol);
-
-                        synchronized (mLock) {
-                            CountDownLatch latch = mFuseVolumeReadyLatches.remove(vol.id);
-                            if (latch != null) {
-                                latch.countDown();
-                            }
-                        }
-                    } catch (IllegalStateException | ExternalStorageServiceException e) {
-                        Slog.i(TAG, "Failed to initialise volume " + vol, e);
-                    }
-                    break;
-                }
                 case H_VOLUME_MOUNT: {
                     final VolumeInfo vol = (VolumeInfo) msg.obj;
                     if (isMountDisallowed(vol)) {
@@ -1431,13 +1400,6 @@
             writeSettingsLocked();
         }
 
-        if (mIsFuseEnabled && newState == VolumeInfo.STATE_MOUNTED
-                && (vol.type == VolumeInfo.TYPE_PUBLIC || vol.type == VolumeInfo.TYPE_EMULATED)) {
-            Slog.i(TAG, "Initialising volume " + vol + " ...");
-            // TODO(b/144275217): Delay broadcasts till mount is really ready
-            mHandler.obtainMessage(H_VOLUME_READY, vol).sendToTarget();
-        }
-
         mCallbacks.notifyVolumeStateChanged(vol, oldState, newState);
 
         // Do not broadcast before boot has completed to avoid launching the
@@ -1912,33 +1874,29 @@
             throw new SecurityException("Mounting " + volId + " restricted by policy");
         }
 
-        CountDownLatch latch = null;
-        if (mIsFuseEnabled && StorageSessionController.isEmulatedOrPublic(vol)) {
-            latch = findOrCreateFuseVolumeReadyLatch(volId);
-        }
-
         mount(vol);
-
-        if (latch != null) {
-            try {
-                waitForLatch(latch, "mount " + volId, 3 * DateUtils.MINUTE_IN_MILLIS);
-            } catch (TimeoutException e) {
-                Slog.wtf(TAG, e);
-            } finally {
-                synchronized (mLock) {
-                    mFuseVolumeReadyLatches.remove(volId);
-                }
-            }
-        }
     }
 
     private void mount(VolumeInfo vol) {
         try {
             // TODO(b/135341433): Remove paranoid logging when FUSE is stable
             Slog.i(TAG, "Mounting volume " + vol);
-            FileDescriptor fd = mVold.mount(vol.id, vol.mountFlags, vol.mountUserId);
+            mVold.mount(vol.id, vol.mountFlags, vol.mountUserId, new IVoldMountCallback.Stub() {
+                    @Override
+                    public boolean onVolumeChecking(FileDescriptor deviceFd, String path,
+                            String internalPath) {
+                        vol.path = path;
+                        vol.internalPath = internalPath;
+                        try {
+                            mStorageSessionController.onVolumeMount(deviceFd, vol);
+                            return true;
+                        } catch (ExternalStorageServiceException e) {
+                            Slog.i(TAG, "Failed to mount volume " + vol, e);
+                            return false;
+                        }
+                    }
+                });
             Slog.i(TAG, "Mounted volume " + vol);
-            mStorageSessionController.onVolumeMount(fd, vol);
         } catch (Exception e) {
             Slog.wtf(TAG, e);
         }
@@ -2771,11 +2729,6 @@
      */
     @Override
     public boolean supportsCheckpoint() throws RemoteException {
-        // Only the system process is permitted to start checkpoints
-        if (Binder.getCallingUid() != android.os.Process.SYSTEM_UID) {
-            throw new SecurityException("no permission to check filesystem checkpoint support");
-        }
-
         return mVold.supportsCheckpoint();
     }
 
@@ -2926,12 +2879,6 @@
         enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
 
         if (StorageManager.isFileEncryptedNativeOrEmulated()) {
-            // When a user has secure lock screen, require secret to actually unlock.
-            // This check is mostly in place for emulation mode.
-            if (mLockPatternUtils.isSecure(userId) && ArrayUtils.isEmpty(secret)) {
-                throw new IllegalStateException("Secret required to unlock secure user " + userId);
-            }
-
             try {
                 mVold.unlockUserKey(userId, serialNumber, encodeBytes(token),
                         encodeBytes(secret));
@@ -3648,7 +3595,7 @@
             try {
                 mObbState.volId = mVold.createObb(mObbState.canonicalPath, binderKey,
                         mObbState.ownerGid);
-                mVold.mount(mObbState.volId, 0, -1);
+                mVold.mount(mObbState.volId, 0, -1, null);
 
                 if (DEBUG_OBB)
                     Slog.d(TAG, "Successfully mounted OBB " + mObbState.canonicalPath);
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 88d0e4b..5b7a814 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -568,6 +568,11 @@
     private static final int NATIVE_DUMP_TIMEOUT_MS = 2000; // 2 seconds;
     private static final int JAVA_DUMP_MINIMUM_SIZE = 100; // 100 bytes.
 
+    /**
+     * How long between a process kill and we actually receive its death recipient
+     */
+    private static final long PROC_KILL_TIMEOUT = 5000; // 5 seconds;
+
     OomAdjuster mOomAdjuster;
     final LowMemDetector mLowMemDetector;
 
@@ -3738,6 +3743,9 @@
                 "Dying app: " + app + ", pid: " + pid + ", thread: " + thread.asBinder());
             handleAppDiedLocked(app, false, true);
 
+            // Execute the callback if there is any.
+            doAppDiedCallbackLocked(app);
+
             if (doOomAdj) {
                 updateOomAdjLocked(OomAdjuster.OOM_ADJ_REASON_PROCESS_END);
             }
@@ -3749,6 +3757,10 @@
             reportUidInfoMessageLocked(TAG,
                     "Process " + app.processName + " (pid " + pid
                             + ") has died and restarted (pid " + app.pid + ").", app.info.uid);
+
+            // Execute the callback if there is any.
+            doAppDiedCallbackLocked(app);
+
             EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.userId, app.pid, app.processName);
         } else if (DEBUG_PROCESSES) {
             Slog.d(TAG_PROCESSES, "Received spurious death notification for thread "
@@ -3762,6 +3774,39 @@
         }
     }
 
+    @GuardedBy("this")
+    private void doAppDiedCallbackLocked(final ProcessRecord app) {
+        if (app.mAppDiedCallback != null) {
+            app.mAppDiedCallback.run();
+            app.mAppDiedCallback = null;
+        }
+    }
+
+    @GuardedBy("this")
+    private void waitForProcKillLocked(final ProcessRecord app, final String formatString,
+            final long startTime) {
+        app.mAppDiedCallback = () -> {
+            synchronized (ActivityManagerService.this) {
+                // called when this app receives appDiedLocked()
+                ActivityManagerService.this.notifyAll();
+            }
+        };
+        checkTime(startTime, String.format(formatString, "before appDied"));
+        long now = SystemClock.uptimeMillis();
+        long timeout = PROC_KILL_TIMEOUT + now;
+        while (app.mAppDiedCallback != null && timeout > now) {
+            try {
+                wait(timeout - now);
+            } catch (InterruptedException e) {
+            }
+            now = SystemClock.uptimeMillis();
+        }
+        checkTime(startTime, String.format(formatString, "after appDied"));
+        if (app.mAppDiedCallback != null) {
+            Slog.w(TAG, String.format(formatString, "waiting for app killing timed out"));
+        }
+    }
+
     /**
      * If a stack trace dump file is configured, dump process stack traces.
      * @param firstPids of dalvik VM processes to dump stack traces for first
@@ -6779,18 +6824,12 @@
 
                 // Note if killedByAm is also set, this means the provider process has just been
                 // killed by AM (in ProcessRecord.kill()), but appDiedLocked() hasn't been called
-                // yet. So we need to call appDiedLocked() here and let it clean up.
+                // yet. So we need to wait for appDiedLocked() here and let it clean up.
                 // (See the commit message on I2c4ba1e87c2d47f2013befff10c49b3dc337a9a7 to see
                 // how to test this case.)
                 if (cpr.proc.killed && cpr.proc.killedByAm) {
-                    checkTime(startTime, "getContentProviderImpl: before appDied (killedByAm)");
-                    final long iden = Binder.clearCallingIdentity();
-                    try {
-                        appDiedLocked(cpr.proc);
-                    } finally {
-                        Binder.restoreCallingIdentity(iden);
-                    }
-                    checkTime(startTime, "getContentProviderImpl: after appDied (killedByAm)");
+                    waitForProcKillLocked(cpr.proc, "getContentProviderImpl: %s (killedByAm)",
+                            startTime);
                 }
             }
 
@@ -6894,9 +6933,7 @@
                     Slog.i(TAG, "Existing provider " + cpr.name.flattenToShortString()
                             + " is crashing; detaching " + r);
                     boolean lastRef = decProviderCountLocked(conn, cpr, token, stable);
-                    checkTime(startTime, "getContentProviderImpl: before appDied");
-                    appDiedLocked(cpr.proc);
-                    checkTime(startTime, "getContentProviderImpl: after appDied");
+                    waitForProcKillLocked(cpr.proc, "getContentProviderImpl: %s", startTime);
                     if (!lastRef) {
                         // This wasn't the last ref our process had on
                         // the provider...  we have now been killed, bail.
diff --git a/services/core/java/com/android/server/am/CarUserSwitchingDialog.java b/services/core/java/com/android/server/am/CarUserSwitchingDialog.java
index c7de7b1..183e059 100644
--- a/services/core/java/com/android/server/am/CarUserSwitchingDialog.java
+++ b/services/core/java/com/android/server/am/CarUserSwitchingDialog.java
@@ -37,6 +37,7 @@
 import android.view.View;
 import android.widget.ImageView;
 import android.widget.TextView;
+
 import com.android.internal.R;
 
 
@@ -65,7 +66,9 @@
         setCancelable(false);
         Resources res = getContext().getResources();
         // Custom view due to alignment and font size requirements
-        getContext().setTheme(R.style.Theme_DeviceDefault_Light_Dialog_Alert_UserSwitchingDialog);
+        // TODO (b/145021634): disabled because it's delaying user switch by 3 seconds
+        // getContext()
+        // .setTheme(R.style.Theme_DeviceDefault_Light_Dialog_Alert_UserSwitchingDialog);
         View view = LayoutInflater.from(getContext()).inflate(
                 R.layout.car_user_switching_dialog,
                 null);
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index 30674db..0591704 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -306,7 +306,7 @@
     @GuardedBy("mService")
     void updateOomAdjLocked(String oomAdjReason) {
         final ProcessRecord topApp = mService.getTopAppLocked();
-        updateOomAdjLockedInner(oomAdjReason, topApp , null, null, true);
+        updateOomAdjLockedInner(oomAdjReason, topApp , null, null, true, true);
     }
 
     /**
@@ -361,8 +361,10 @@
         uids.clear();
         queue.clear();
 
-        // borrow the "containsCycle" flag to mark it being scanned
-        app.containsCycle = true;
+        // Track if any of them reachables could include a cycle
+        boolean containsCycle = false;
+        // Scan downstreams of the process record
+        app.mReachable = true;
         for (ProcessRecord pr = app; pr != null; pr = queue.poll()) {
             if (pr != app) {
                 processes.add(pr);
@@ -374,7 +376,7 @@
                 ConnectionRecord cr = pr.connections.valueAt(i);
                 ProcessRecord service = (cr.flags & ServiceInfo.FLAG_ISOLATED_PROCESS) != 0
                         ? cr.binding.service.isolatedProc : cr.binding.service.app;
-                if (service == null || service.containsCycle) {
+                if (service == null || service == pr || (containsCycle |= service.mReachable)) {
                     continue;
                 }
                 if ((cr.flags & (Context.BIND_WAIVE_PRIORITY
@@ -384,21 +386,21 @@
                     continue;
                 }
                 queue.offer(service);
-                service.containsCycle = true;
+                service.mReachable = true;
             }
             for (int i = pr.conProviders.size() - 1; i >= 0; i--) {
                 ContentProviderConnection cpc = pr.conProviders.get(i);
                 ProcessRecord provider = cpc.provider.proc;
-                if (provider == null || provider.containsCycle) {
+                if (provider == null || provider == pr || (containsCycle |= provider.mReachable)) {
                     continue;
                 }
                 queue.offer(provider);
-                provider.containsCycle = true;
+                provider.mReachable = true;
             }
         }
 
         // Reset the flag
-        app.containsCycle = false;
+        app.mReachable = false;
         int size = processes.size();
         if (size > 0) {
             // Reverse the process list, since the updateOomAdjLockedInner scans from the end of it.
@@ -409,7 +411,7 @@
             }
             mAdjSeq--;
             // Update these reachable processes
-            updateOomAdjLockedInner(oomAdjReason, topApp, processes, uids, false);
+            updateOomAdjLockedInner(oomAdjReason, topApp, processes, uids, containsCycle, false);
         } else if (app.getCurRawAdj() == ProcessList.UNKNOWN_ADJ) {
             // In case the app goes from non-cached to cached but it doesn't have other reachable
             // processes, its adj could be still unknown as of now, assign one.
@@ -430,7 +432,8 @@
      */
     @GuardedBy("mService")
     private void updateOomAdjLockedInner(String oomAdjReason, final ProcessRecord topApp,
-            ArrayList<ProcessRecord> processes, ActiveUids uids, boolean startProfiling) {
+            ArrayList<ProcessRecord> processes, ActiveUids uids, boolean potentialCycles,
+            boolean startProfiling) {
         if (startProfiling) {
             Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, oomAdjReason);
             mService.mOomAdjProfiler.oomAdjStarted();
@@ -474,11 +477,13 @@
         }
 
         boolean retryCycles = false;
+        boolean computeClients = fullUpdate || potentialCycles;
 
         // need to reset cycle state before calling computeOomAdjLocked because of service conns
         for (int i = numProc - 1; i >= 0; i--) {
             ProcessRecord app = activeProcesses.get(i);
             app.containsCycle = false;
+            app.mReachable = false;
             app.setCurRawProcState(PROCESS_STATE_CACHED_EMPTY);
             app.setCurRawAdj(ProcessList.UNKNOWN_ADJ);
             app.setCapability = PROCESS_CAPABILITY_NONE;
@@ -489,7 +494,7 @@
             if (!app.killedByAm && app.thread != null) {
                 app.procStateChanged = false;
                 computeOomAdjLocked(app, ProcessList.UNKNOWN_ADJ, topApp, fullUpdate, now, false,
-                        fullUpdate); // It won't enter cycle if not computing clients.
+                        computeClients); // It won't enter cycle if not computing clients.
                 // if any app encountered a cycle, we need to perform an additional loop later
                 retryCycles |= app.containsCycle;
                 // Keep the completedAdjSeq to up to date.
@@ -499,7 +504,7 @@
 
         assignCachedAdjIfNecessary(mProcessList.mLruProcesses);
 
-        if (fullUpdate) { // There won't be cycles if we didn't compute clients above.
+        if (computeClients) { // There won't be cycles if we didn't compute clients above.
             // Cycle strategy:
             // - Retry computing any process that has encountered a cycle.
             // - Continue retrying until no process was promoted.
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index 1e0693f..867571a 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -327,6 +327,11 @@
     int mCachedProcState = ActivityManager.PROCESS_STATE_CACHED_EMPTY;
     int mCachedSchedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
 
+    boolean mReachable; // Whether or not this process is reachable from given process
+
+    // A callback that should be executed on app died; after that it'll be set to null
+    Runnable mAppDiedCallback;
+
     void setStartParams(int startUid, HostingRecord hostingRecord, String seInfo,
             long startTime) {
         this.startUid = startUid;
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/compat/PlatformCompat.java b/services/core/java/com/android/server/compat/PlatformCompat.java
index ae5ad7e..311e24f 100644
--- a/services/core/java/com/android/server/compat/PlatformCompat.java
+++ b/services/core/java/com/android/server/compat/PlatformCompat.java
@@ -20,7 +20,7 @@
 import android.app.IActivityManager;
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
+import android.content.pm.PackageManagerInternal;
 import android.os.Binder;
 import android.os.RemoteException;
 import android.os.UserHandle;
@@ -32,6 +32,7 @@
 import com.android.internal.compat.CompatibilityChangeInfo;
 import com.android.internal.compat.IPlatformCompat;
 import com.android.internal.util.DumpUtils;
+import com.android.server.LocalServices;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -197,12 +198,8 @@
     }
 
     private ApplicationInfo getApplicationInfo(String packageName, int userId) {
-        try {
-            return mContext.getPackageManager().getApplicationInfoAsUser(packageName, 0, userId);
-        } catch (PackageManager.NameNotFoundException e) {
-            Slog.e(TAG, "No installed package " + packageName);
-        }
-        return null;
+        return LocalServices.getService(PackageManagerInternal.class).getApplicationInfo(
+                packageName, 0, userId, userId);
     }
 
     private void reportChange(long changeId, int uid, int state) {
@@ -210,11 +207,11 @@
     }
 
     private void killPackage(String packageName) {
-        int uid = -1;
-        try {
-            uid = mContext.getPackageManager().getPackageUid(packageName, 0);
-        } catch (PackageManager.NameNotFoundException e) {
-            Slog.w(TAG, "Didn't find package " + packageName + " on device.", e);
+        int uid = LocalServices.getService(PackageManagerInternal.class).getPackageUid(packageName,
+                    0, UserHandle.myUserId());
+
+        if (uid < 0) {
+            Slog.w(TAG, "Didn't find package " + packageName + " on device.");
             return;
         }
 
diff --git a/services/core/java/com/android/server/lights/LightsService.java b/services/core/java/com/android/server/lights/LightsService.java
index ac906bb..eaae2ed 100644
--- a/services/core/java/com/android/server/lights/LightsService.java
+++ b/services/core/java/com/android/server/lights/LightsService.java
@@ -84,8 +84,12 @@
                     if (DEBUG) {
                         Slog.d(TAG, "Using new setBrightness path!");
                     }
-                    SurfaceControl.setDisplayBrightness(mDisplayToken,
-                            (float) brightness / mSurfaceControlMaximumBrightness);
+                    if (brightness == 0) {
+                        SurfaceControl.setDisplayBrightness(mDisplayToken, -1.0f);
+                    } else {
+                        SurfaceControl.setDisplayBrightness(mDisplayToken,
+                                (float) (brightness - 1) / (mSurfaceControlMaximumBrightness - 1));
+                    }
                 } else {
                     int color = brightness & 0x000000ff;
                     color = 0xff000000 | (color << 16) | (color << 8) | color;
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 b60306b..d5f2d7e 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -2083,10 +2083,10 @@
 
             @Override
             public void updateAutogroupSummary(String key, boolean needsOngoingFlag) {
-                String pkg = null;
+                String pkg;
                 synchronized (mNotificationLock) {
                     NotificationRecord r = mNotificationsByKey.get(key);
-                    pkg = r.sbn.getPackageName();
+                    pkg = r != null && r.sbn != null ? r.sbn.getPackageName() : null;
                 }
                 boolean isAppForeground = pkg != null
                         && mActivityManager.getPackageImportance(pkg) == IMPORTANCE_FOREGROUND;
diff --git a/services/core/java/com/android/server/pm/BackgroundDexOptService.java b/services/core/java/com/android/server/pm/BackgroundDexOptService.java
index 08e55d3..c712431 100644
--- a/services/core/java/com/android/server/pm/BackgroundDexOptService.java
+++ b/services/core/java/com/android/server/pm/BackgroundDexOptService.java
@@ -34,8 +34,6 @@
 import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.os.storage.StorageManager;
-import android.provider.DeviceConfig;
-import android.text.TextUtils;
 import android.util.ArraySet;
 import android.util.Log;
 import android.util.StatsLog;
@@ -86,12 +84,6 @@
 
     // Used for calculating space threshold for downgrading unused apps.
     private static final int LOW_THRESHOLD_MULTIPLIER_FOR_DOWNGRADE = 2;
-    private static final int DEFAULT_INACTIVE_APP_THRESHOLD_DAYS = 10;
-
-    private static final String DOWNGRADE_UNUSED_APPS_ENABLED = "downgrade_unused_apps_enabled";
-    private static final String INACTIVE_APP_THRESHOLD_DAYS = "inactive_app_threshold_days";
-    private static final String LOW_STORAGE_MULTIPLIER_FOR_DOWNGRADE =
-            "low_storage_threshold_multiplier_for_downgrade";
 
     /**
      * Set of failed packages remembered across job runs.
@@ -111,6 +103,8 @@
     private final AtomicBoolean mExitPostBootUpdate = new AtomicBoolean(false);
 
     private final File mDataDir = Environment.getDataDirectory();
+    private static final long mDowngradeUnusedAppsThresholdInMillis =
+            getDowngradeUnusedAppsThresholdInMillis();
 
     public static void schedule(Context context) {
         if (isBackgroundDexoptDisabled()) {
@@ -352,14 +346,14 @@
             // Only downgrade apps when space is low on device.
             // Threshold is selected above the lowStorageThreshold so that we can pro-actively clean
             // up disk before user hits the actual lowStorageThreshold.
-            final long lowStorageThresholdForDowngrade = getLowThresholdMultiplierForDowngrade()
+            final long lowStorageThresholdForDowngrade = LOW_THRESHOLD_MULTIPLIER_FOR_DOWNGRADE
                     * lowStorageThreshold;
             boolean shouldDowngrade = shouldDowngrade(lowStorageThresholdForDowngrade);
             Log.d(TAG, "Should Downgrade " + shouldDowngrade);
             if (shouldDowngrade) {
                 Set<String> unusedPackages =
-                        pm.getUnusedPackages(getDowngradeUnusedAppsThresholdInMillis());
-                Log.d(TAG, "Unused Packages " +  String.join(",", unusedPackages));
+                        pm.getUnusedPackages(mDowngradeUnusedAppsThresholdInMillis);
+                Log.d(TAG, "Unsused Packages " +  String.join(",", unusedPackages));
 
                 if (!unusedPackages.isEmpty()) {
                     for (String pkg : unusedPackages) {
@@ -368,9 +362,12 @@
                             // Should be aborted by the scheduler.
                             return abortCode;
                         }
-                        if (downgradePackage(pm, pkg)) {
+                        if (downgradePackage(pm, pkg, /*isForPrimaryDex*/ true)) {
                             updatedPackages.add(pkg);
                         }
+                        if (supportSecondaryDex) {
+                            downgradePackage(pm, pkg, /*isForPrimaryDex*/ false);
+                        }
                     }
 
                     pkgs = new ArraySet<>(pkgs);
@@ -418,45 +415,39 @@
      * Try to downgrade the package to a smaller compilation filter.
      * eg. if the package is in speed-profile the package will be downgraded to verify.
      * @param pm PackageManagerService
-     * @param pkg The package to be downgraded
-     * @return true if the package was downgraded
+     * @param pkg The package to be downgraded.
+     * @param isForPrimaryDex. Apps can have several dex file, primary and secondary.
+     * @return true if the package was downgraded.
      */
-    private boolean downgradePackage(PackageManagerService pm, String pkg) {
+    private boolean downgradePackage(PackageManagerService pm, String pkg,
+            boolean isForPrimaryDex) {
         Log.d(TAG, "Downgrading " + pkg);
-        boolean downgradedPrimary = false;
+        boolean dex_opt_performed = false;
         int reason = PackageManagerService.REASON_INACTIVE_PACKAGE_DOWNGRADE;
         int dexoptFlags = DexoptOptions.DEXOPT_BOOT_COMPLETE
                 | DexoptOptions.DEXOPT_IDLE_BACKGROUND_JOB
                 | DexoptOptions.DEXOPT_DOWNGRADE;
-
         long package_size_before = getPackageSize(pm, pkg);
-        // An aggressive downgrade deletes the oat files.
-        boolean aggressive = false;
-        // This applies for system apps or if packages location is not a directory, i.e.
-        // monolithic install.
-        if (!pm.canHaveOatDir(pkg)) {
-            // For apps that don't have the oat directory, instead of downgrading,
-            // remove their compiler artifacts from dalvik cache.
-            pm.deleteOatArtifactsOfPackage(pkg);
-            aggressive = true;
-            downgradedPrimary = true;
-        } else {
-            downgradedPrimary = performDexOptPrimary(pm, pkg, reason, dexoptFlags);
 
-            if (supportSecondaryDex()) {
-                performDexOptSecondary(pm, pkg, reason, dexoptFlags);
+        if (isForPrimaryDex) {
+            // This applies for system apps or if packages location is not a directory, i.e.
+            // monolithic install.
+            if (!pm.canHaveOatDir(pkg)) {
+                // For apps that don't have the oat directory, instead of downgrading,
+                // remove their compiler artifacts from dalvik cache.
+                pm.deleteOatArtifactsOfPackage(pkg);
+            } else {
+                dex_opt_performed = performDexOptPrimary(pm, pkg, reason, dexoptFlags);
             }
+        } else {
+            dex_opt_performed = performDexOptSecondary(pm, pkg, reason, dexoptFlags);
         }
 
-        // This metric aims to log the storage savings when downgrading.
-        // The way disk size is measured using getPackageSize only looks at the primary apks.
-        // Any logs that are due to secondary dex files will show 0% size reduction and pollute
-        // the metrics.
-        if (downgradedPrimary) {
+        if (dex_opt_performed) {
             StatsLog.write(StatsLog.APP_DOWNGRADED, pkg, package_size_before,
-                    getPackageSize(pm, pkg), aggressive);
+                    getPackageSize(pm, pkg), /*aggressive=*/ false);
         }
-        return downgradedPrimary;
+        return dex_opt_performed;
     }
 
     private boolean supportSecondaryDex() {
@@ -480,7 +471,7 @@
      * concurrent jobs because PackageDexOptimizer.performDexOpt is synchronized.
      * @param pm An instance of PackageManagerService
      * @param pkg The package to be downgraded.
-     * @param isForPrimaryDex Apps can have several dex file, primary and secondary.
+     * @param isForPrimaryDex. Apps can have several dex file, primary and secondary.
      * @return true if the package was downgraded.
      */
     private boolean optimizePackage(PackageManagerService pm, String pkg,
@@ -597,6 +588,12 @@
         // the checks above. This check is not "live" - the value is determined by a background
         // restart with a period of ~1 minute.
         PackageManagerService pm = (PackageManagerService)ServiceManager.getService("package");
+        if (pm.isStorageLow()) {
+            if (DEBUG_DEXOPT) {
+                Log.i(TAG, "Low storage, skipping this run");
+            }
+            return false;
+        }
 
         final ArraySet<String> pkgs = pm.getOptimizablePackages();
         if (pkgs.isEmpty()) {
@@ -646,77 +643,17 @@
     }
 
     private static long getDowngradeUnusedAppsThresholdInMillis() {
-        long defaultValue = Long.MAX_VALUE;
-        if (isDowngradeFeatureEnabled()) {
-            return getInactiveAppsThresholdMillis();
-        }
         final String sysPropKey = "pm.dexopt.downgrade_after_inactive_days";
         String sysPropValue = SystemProperties.get(sysPropKey);
         if (sysPropValue == null || sysPropValue.isEmpty()) {
             Log.w(TAG, "SysProp " + sysPropKey + " not set");
-            return defaultValue;
+            return Long.MAX_VALUE;
         }
-        try {
-            return TimeUnit.DAYS.toMillis(Long.parseLong(sysPropValue));
-        } catch (NumberFormatException e) {
-            Log.w(TAG, "Couldn't parse long for pm.dexopt.downgrade_after_inactive_days: "
-                    + sysPropValue + ". Returning default value instead.");
-            return defaultValue;
-        }
+        return TimeUnit.DAYS.toMillis(Long.parseLong(sysPropValue));
     }
 
     private static boolean isBackgroundDexoptDisabled() {
         return SystemProperties.getBoolean("pm.dexopt.disable_bg_dexopt" /* key */,
                 false /* default */);
     }
-
-    private static boolean isDowngradeFeatureEnabled() {
-        // DeviceConfig enables the control of on device features via remotely configurable flags,
-        // compared to SystemProperties which is only a way of sharing info system-widely, but are
-        // not configurable on the server-side.
-        String downgradeUnusedAppsEnabledFlag =
-                DeviceConfig.getProperty(
-                        DeviceConfig.NAMESPACE_PACKAGE_MANAGER_SERVICE,
-                        DOWNGRADE_UNUSED_APPS_ENABLED);
-        return !TextUtils.isEmpty(downgradeUnusedAppsEnabledFlag)
-                && Boolean.parseBoolean(downgradeUnusedAppsEnabledFlag);
-    }
-
-    private static long getInactiveAppsThresholdMillis() {
-        long defaultValue = TimeUnit.DAYS.toMillis(DEFAULT_INACTIVE_APP_THRESHOLD_DAYS);
-        String inactiveAppThresholdDaysFlag =
-                DeviceConfig.getProperty(DeviceConfig.NAMESPACE_PACKAGE_MANAGER_SERVICE,
-                        INACTIVE_APP_THRESHOLD_DAYS);
-        if (!TextUtils.isEmpty(inactiveAppThresholdDaysFlag)) {
-            try {
-                return TimeUnit.DAYS.toMillis(Long.parseLong(inactiveAppThresholdDaysFlag));
-            } catch (NumberFormatException e) {
-                Log.w(TAG, "Couldn't parse long for " + INACTIVE_APP_THRESHOLD_DAYS + " flag: "
-                        + inactiveAppThresholdDaysFlag + ". Returning default value instead.");
-                return defaultValue;
-            }
-        }
-        return defaultValue;
-    }
-
-    private static int getLowThresholdMultiplierForDowngrade() {
-        int defaultValue = LOW_THRESHOLD_MULTIPLIER_FOR_DOWNGRADE;
-        if (isDowngradeFeatureEnabled()) {
-            String lowStorageThresholdMultiplierFlag =
-                    DeviceConfig.getProperty(DeviceConfig.NAMESPACE_PACKAGE_MANAGER_SERVICE,
-                            LOW_STORAGE_MULTIPLIER_FOR_DOWNGRADE);
-            if (!TextUtils.isEmpty(lowStorageThresholdMultiplierFlag)) {
-                try {
-                    return Integer.parseInt(lowStorageThresholdMultiplierFlag);
-                } catch (NumberFormatException e) {
-                    Log.w(TAG, "Couldn't parse long for "
-                            + LOW_STORAGE_MULTIPLIER_FOR_DOWNGRADE + " flag: "
-                            + lowStorageThresholdMultiplierFlag
-                            + ". Returning default value instead.");
-                    return defaultValue;
-                }
-            }
-        }
-        return defaultValue;
-    }
 }
diff --git a/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java b/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java
index d6108b7c..d2a6b42 100644
--- a/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java
+++ b/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java
@@ -202,6 +202,7 @@
             final List<ResolveInfo> apps =
                     mInjector.getPackageManagerInternal().queryIntentActivities(
                             launchIntent,
+                            launchIntent.resolveTypeIfNeeded(mContext.getContentResolver()),
                             MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE,
                             callingUid,
                             userId);
diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java
index bd95667..f7fd1b2 100644
--- a/services/core/java/com/android/server/pm/LauncherAppsService.java
+++ b/services/core/java/com/android/server/pm/LauncherAppsService.java
@@ -344,6 +344,7 @@
             final PackageManagerInternal pmInt =
                     LocalServices.getService(PackageManagerInternal.class);
             List<ResolveInfo> apps = pmInt.queryIntentActivities(intent,
+                    intent.resolveTypeIfNeeded(mContext.getContentResolver()),
                     PackageManager.MATCH_DIRECT_BOOT_AWARE
                             | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
                     callingUid, user.getIdentifier());
@@ -468,6 +469,7 @@
             matchIntent.addCategory(Intent.CATEGORY_LAUNCHER);
             matchIntent.setPackage(packageName);
             final List<ResolveInfo> infoList = pmInt.queryIntentActivities(matchIntent,
+                    matchIntent.resolveTypeIfNeeded(mContext.getContentResolver()),
                     PackageManager.MATCH_DISABLED_COMPONENTS, Binder.getCallingUid(),
                     getCallingUserId());
             final int size = infoList.size();
@@ -539,6 +541,7 @@
                 final PackageManagerInternal pmInt =
                         LocalServices.getService(PackageManagerInternal.class);
                 List<ResolveInfo> apps = pmInt.queryIntentActivities(intent,
+                        intent.resolveTypeIfNeeded(mContext.getContentResolver()),
                         PackageManager.MATCH_DIRECT_BOOT_AWARE
                                 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
                         callingUid, user.getIdentifier());
@@ -842,6 +845,7 @@
                 // as calling startActivityAsUser ignores the category and just
                 // resolves based on the component if present.
                 List<ResolveInfo> apps = pmInt.queryIntentActivities(launchIntent,
+                        launchIntent.resolveTypeIfNeeded(mContext.getContentResolver()),
                         PackageManager.MATCH_DIRECT_BOOT_AWARE
                                 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
                         callingUid, user.getIdentifier());
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index fa98c96..eebc8d7 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -13218,10 +13218,6 @@
 
         // Check if installing from ADB
         if ((installFlags & PackageManager.INSTALL_FROM_ADB) != 0) {
-            // Do not run verification in a test harness environment
-            if (ActivityManager.isRunningInTestHarness()) {
-                return false;
-            }
             if (isUserRestricted(userId, UserManager.ENSURE_VERIFY_APPS)) {
                 return true;
             }
@@ -22874,39 +22870,79 @@
             return pkg == null ? null : pkg.packageName;
         }
 
+        /**
+         * Only keep package names that refer to {@link PackageParser.Package#isSystem system}
+         * packages.
+         *
+         * @param pkgNames The packages to filter
+         *
+         * @return The filtered packages
+         */
+        private @NonNull String[] filterOnlySystemPackages(@Nullable String... pkgNames) {
+            if (pkgNames == null) {
+                return ArrayUtils.emptyArray(String.class);
+            }
+
+            ArrayList<String> systemPackageNames = new ArrayList<>(pkgNames.length);
+
+            for (String pkgName: pkgNames) {
+                synchronized (mPackages) {
+                    if (pkgName == null) {
+                        continue;
+                    }
+
+                    PackageParser.Package pkg = getPackage(pkgName);
+                    if (pkg == null) {
+                        Log.w(TAG, "Could not find package " + pkgName);
+                        continue;
+                    }
+
+                    if (!pkg.isSystem()) {
+                        Log.w(TAG, pkgName + " is not system");
+                        continue;
+                    }
+
+                    systemPackageNames.add(pkgName);
+                }
+            }
+
+            return systemPackageNames.toArray(new String[]{});
+        }
+
         @Override
         public @NonNull String[] getKnownPackageNames(int knownPackage, int userId) {
-            switch(knownPackage) {
+            switch (knownPackage) {
                 case PackageManagerInternal.PACKAGE_BROWSER:
                     return new String[]{mPermissionManager.getDefaultBrowser(userId)};
                 case PackageManagerInternal.PACKAGE_INSTALLER:
-                    return new String[]{mRequiredInstallerPackage};
+                    return filterOnlySystemPackages(mRequiredInstallerPackage);
                 case PackageManagerInternal.PACKAGE_SETUP_WIZARD:
-                    return new String[]{mSetupWizardPackage};
+                    return filterOnlySystemPackages(mSetupWizardPackage);
                 case PackageManagerInternal.PACKAGE_SYSTEM:
                     return new String[]{"android"};
                 case PackageManagerInternal.PACKAGE_VERIFIER:
-                    return new String[]{mRequiredVerifierPackage};
+                    return filterOnlySystemPackages(mRequiredVerifierPackage);
                 case PackageManagerInternal.PACKAGE_SYSTEM_TEXT_CLASSIFIER:
-                    return new String[]{mSystemTextClassifierPackage};
+                    return filterOnlySystemPackages(mSystemTextClassifierPackage);
                 case PackageManagerInternal.PACKAGE_PERMISSION_CONTROLLER:
-                    return new String[]{mRequiredPermissionControllerPackage};
+                    return filterOnlySystemPackages(mRequiredPermissionControllerPackage);
                 case PackageManagerInternal.PACKAGE_WELLBEING:
-                    return new String[]{mWellbeingPackage};
+                    return filterOnlySystemPackages(mWellbeingPackage);
                 case PackageManagerInternal.PACKAGE_DOCUMENTER:
-                    return new String[]{mDocumenterPackage};
+                    return filterOnlySystemPackages(mDocumenterPackage);
                 case PackageManagerInternal.PACKAGE_CONFIGURATOR:
-                    return new String[]{mConfiguratorPackage};
+                    return filterOnlySystemPackages(mConfiguratorPackage);
                 case PackageManagerInternal.PACKAGE_INCIDENT_REPORT_APPROVER:
-                    return new String[]{mIncidentReportApproverPackage};
+                    return filterOnlySystemPackages(mIncidentReportApproverPackage);
                 case PackageManagerInternal.PACKAGE_APP_PREDICTOR:
-                    return new String[]{mAppPredictionServicePackage};
+                    return filterOnlySystemPackages(mAppPredictionServicePackage);
                 case PackageManagerInternal.PACKAGE_TELEPHONY:
-                    return mTelephonyPackages;
+                    return filterOnlySystemPackages(mTelephonyPackages);
                 case PackageManagerInternal.PACKAGE_WIFI:
-                    return new String[]{mWifiPackage};
+                    return filterOnlySystemPackages(mWifiPackage);
+                default:
+                    return ArrayUtils.emptyArray(String.class);
             }
-            return ArrayUtils.emptyArray(String.class);
         }
 
         @Override
@@ -23061,8 +23097,7 @@
 
         @Override
         public List<ResolveInfo> queryIntentActivities(
-                Intent intent, int flags, int filterCallingUid, int userId) {
-            final String resolvedType = intent.resolveTypeIfNeeded(mContext.getContentResolver());
+                Intent intent, String resolvedType, int flags, int filterCallingUid, int userId) {
             return PackageManagerService.this
                     .queryIntentActivitiesInternal(intent, resolvedType, flags, filterCallingUid,
                             userId, false /*resolveForStart*/, true /*allowDynamicSplits*/);
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 5f3650c..69c7cf2 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -3348,7 +3348,8 @@
             int flags, ComponentName cn, String scheme, PatternMatcher ssp,
             IntentFilter.AuthorityEntry auth, PatternMatcher path, int userId) {
         final List<ResolveInfo> ri =
-                pmInternal.queryIntentActivities(intent, flags, Binder.getCallingUid(), 0);
+                pmInternal.queryIntentActivities(
+                        intent, intent.getType(), flags, Binder.getCallingUid(), 0);
         if (PackageManagerService.DEBUG_PREFERRED) {
             Log.d(TAG, "Queried " + intent + " results: " + ri);
         }
diff --git a/services/core/java/com/android/server/pm/StagingManager.java b/services/core/java/com/android/server/pm/StagingManager.java
index 3390ca7..5bb42d4 100644
--- a/services/core/java/com/android/server/pm/StagingManager.java
+++ b/services/core/java/com/android/server/pm/StagingManager.java
@@ -45,6 +45,7 @@
 import android.os.PowerManager;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.os.storage.StorageManager;
 import android.util.IntArray;
 import android.util.Slog;
 import android.util.SparseArray;
@@ -75,6 +76,7 @@
     private final PackageInstallerService mPi;
     private final ApexManager mApexManager;
     private final PowerManager mPowerManager;
+    private final Context mContext;
     private final PreRebootVerificationHandler mPreRebootVerificationHandler;
 
     @GuardedBy("mStagedSessions")
@@ -83,6 +85,7 @@
     StagingManager(PackageInstallerService pi, ApexManager am, Context context) {
         mPi = pi;
         mApexManager = am;
+        mContext = context;
         mPowerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
         mPreRebootVerificationHandler = new PreRebootVerificationHandler(
                 BackgroundThread.get().getLooper());
@@ -539,6 +542,10 @@
         mPreRebootVerificationHandler.startPreRebootVerification(session.sessionId);
     }
 
+    private int parentOrOwnSessionId(PackageInstallerSession session) {
+        return session.hasParentSessionId() ? session.getParentSessionId() : session.sessionId;
+    }
+
     /**
      * <p> Check if the session provided is non-overlapping with the active staged sessions.
      *
@@ -561,6 +568,9 @@
                     "Cannot stage session " + session.sessionId + " with package name null");
         }
 
+        boolean supportsCheckpoint = ((StorageManager) mContext.getSystemService(
+                Context.STORAGE_SERVICE)).isCheckpointSupported();
+
         synchronized (mStagedSessions) {
             for (int i = 0; i < mStagedSessions.size(); i++) {
                 final PackageInstallerSession stagedSession = mStagedSessions.valueAt(i);
@@ -601,7 +611,17 @@
                                     + stagedSession.sessionId, null);
                 }
 
-                // TODO(b/141843321): Add support for staging multiple sessions in apexd
+                // Staging multiple root sessions is not allowed if device doesn't support
+                // checkpoint. If session and stagedSession do not have common ancestor, they are
+                // from two different root sessions.
+                if (!supportsCheckpoint
+                        && parentOrOwnSessionId(session) != parentOrOwnSessionId(stagedSession)) {
+                    throw new PackageManagerException(
+                            PackageManager.INSTALL_FAILED_OTHER_STAGED_SESSION_IN_PROGRESS,
+                            "Cannot stage multiple sessions without checkpoint support", null);
+                }
+
+                // TODO:b/141843321 Add support for staging multiple sessions in apexd
                 // Since apexd doesn't support multiple staged sessions yet, we have to careful how
                 // we handle apex sessions. We want to allow a set of apex sessions under the same
                 // parent to be staged when there is no previously staged apex sessions.
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 5e1d93f..3e528f4 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -3334,27 +3334,17 @@
             return;
         }
         Bundle args = null;
-        if (deviceId > Integer.MIN_VALUE) {
+        if (deviceId > Integer.MIN_VALUE || hint != null) {
             args = new Bundle();
-            args.putInt(Intent.EXTRA_ASSIST_INPUT_DEVICE_ID, deviceId);
-        }
-        if ((mContext.getResources().getConfiguration().uiMode
-                & Configuration.UI_MODE_TYPE_MASK) == Configuration.UI_MODE_TYPE_TELEVISION) {
-            // On TV, use legacy handling until assistants are implemented in the proper way.
-            ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
-                    .launchLegacyAssist(hint, mCurrentUserId, args);
-        } else {
+            if (deviceId > Integer.MIN_VALUE) {
+                args.putInt(Intent.EXTRA_ASSIST_INPUT_DEVICE_ID, deviceId);
+            }
             if (hint != null) {
-                if (args == null) {
-                    args = new Bundle();
-                }
                 args.putBoolean(hint, true);
             }
-            StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
-            if (statusbar != null) {
-                statusbar.startAssist(args);
-            }
         }
+        ((SearchManager) mContext.createContextAsUser(UserHandle.of(mCurrentUserId), 0)
+                .getSystemService(Context.SEARCH_SERVICE)).launchAssist(args);
     }
 
     /** Launches ACTION_VOICE_ASSIST. Does nothing on keyguard. */
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/rollback/RollbackManagerServiceImpl.java b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
index 198bb14..01f29dc 100644
--- a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
+++ b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
@@ -49,6 +49,7 @@
 import android.provider.DeviceConfig;
 import android.util.ArraySet;
 import android.util.IntArray;
+import android.util.LongArrayQueue;
 import android.util.Slog;
 import android.util.SparseBooleanArray;
 
@@ -126,6 +127,11 @@
     private final RollbackPackageHealthObserver mPackageHealthObserver;
     private final AppDataRollbackHelper mAppDataRollbackHelper;
 
+    // The # of milli-seconds to sleep for each received ACTION_PACKAGE_ENABLE_ROLLBACK.
+    // Used by #blockRollbackManager to test timeout in enabling rollbacks.
+    // Accessed on the handler thread only.
+    private final LongArrayQueue mSleepDuration = new LongArrayQueue();
+
     // This field stores the difference in Millis between the uptime (millis since device
     // has booted) and current time (device wall clock) - it's used to update rollback
     // timestamps when the time is changed, by the user or by change of timezone.
@@ -182,6 +188,8 @@
 
                     File newPackageCodePath = new File(intent.getData().getPath());
 
+                    queueSleepIfNeeded();
+
                     getHandler().post(() -> {
                         boolean success =
                                 enableRollback(installFlags, newPackageCodePath, user, token);
@@ -414,6 +422,19 @@
                 Manifest.permission.TEST_MANAGE_ROLLBACKS,
                 "blockRollbackManager");
         getHandler().post(() -> {
+            mSleepDuration.addLast(millis);
+        });
+    }
+
+    private void queueSleepIfNeeded() {
+        if (mSleepDuration.size() == 0) {
+            return;
+        }
+        long millis = mSleepDuration.removeFirst();
+        if (millis <= 0) {
+            return;
+        }
+        getHandler().post(() -> {
             try {
                 Thread.sleep(millis);
             } catch (InterruptedException e) {
@@ -1034,6 +1055,9 @@
                     makeRollbackAvailable(rollback);
                 }
             }
+
+            // Clear the queue so it will never be leaked to next tests.
+            mSleepDuration.clear();
         }
     }
 
diff --git a/services/core/java/com/android/server/search/SearchManagerService.java b/services/core/java/com/android/server/search/SearchManagerService.java
index bc1a12f..1494edf 100644
--- a/services/core/java/com/android/server/search/SearchManagerService.java
+++ b/services/core/java/com/android/server/search/SearchManagerService.java
@@ -18,7 +18,6 @@
 
 import android.app.ActivityManager;
 import android.app.ActivityTaskManager;
-import android.app.IActivityManager;
 import android.app.IActivityTaskManager;
 import android.app.ISearchManager;
 import android.app.SearchManager;
@@ -29,6 +28,7 @@
 import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
+import android.content.res.Configuration;
 import android.database.ContentObserver;
 import android.os.Binder;
 import android.os.Bundle;
@@ -265,11 +265,17 @@
     }
 
     @Override
-    public void launchAssist(Bundle args) {
-        StatusBarManagerInternal statusBarManager =
-                LocalServices.getService(StatusBarManagerInternal.class);
-        if (statusBarManager != null) {
-            statusBarManager.startAssist(args);
+    public void launchAssist(int userHandle, Bundle args) {
+        if ((mContext.getResources().getConfiguration().uiMode
+                & Configuration.UI_MODE_TYPE_MASK) == Configuration.UI_MODE_TYPE_TELEVISION) {
+            // On TV, use legacy handling until assistants are implemented in the proper way.
+            launchLegacyAssist(null, userHandle, args);
+        } else {
+            StatusBarManagerInternal statusBarManager =
+                    LocalServices.getService(StatusBarManagerInternal.class);
+            if (statusBarManager != null) {
+                statusBarManager.startAssist(args);
+            }
         }
     }
 
@@ -298,8 +304,7 @@
         return null;
     }
 
-    @Override
-    public boolean launchLegacyAssist(String hint, int userHandle, Bundle args) {
+    private boolean launchLegacyAssist(String hint, int userHandle, Bundle args) {
         ComponentName comp = getLegacyAssistComponent(userHandle);
         if (comp == null) {
             return false;
diff --git a/services/core/java/com/android/server/storage/StorageSessionController.java b/services/core/java/com/android/server/storage/StorageSessionController.java
index 72a1b9d..d76836f 100644
--- a/services/core/java/com/android/server/storage/StorageSessionController.java
+++ b/services/core/java/com/android/server/storage/StorageSessionController.java
@@ -69,15 +69,21 @@
     }
 
     /**
-     * Creates a storage session associated with {@code deviceFd} for {@code vol}. Sessions can be
-     * started with {@link #onVolumeReady} and removed with {@link #onVolumeUnmount} or
-     * {@link #onVolumeRemove}.
+     * Creates and starts a storage session associated with {@code deviceFd} for {@code vol}.
+     * Sessions can be started with {@link #onVolumeReady} and removed with {@link #onVolumeUnmount}
+     * or {@link #onVolumeRemove}.
+     *
+     * Throws an {@link IllegalStateException} if a session for {@code vol} has already been created
      *
      * Does nothing if {@link #shouldHandle} is {@code false}
      *
+     * Blocks until the session is started or fails
+     *
+     * @throws ExternalStorageServiceException if the session fails to start
      * @throws IllegalStateException if a session has already been created for {@code vol}
      */
-    public void onVolumeMount(FileDescriptor deviceFd, VolumeInfo vol) {
+    public void onVolumeMount(FileDescriptor deviceFd, VolumeInfo vol)
+            throws ExternalStorageServiceException {
         if (!shouldHandle(vol)) {
             return;
         }
@@ -87,71 +93,22 @@
         String sessionId = vol.getId();
         int userId = vol.getMountUserId();
 
-        if (deviceFd == null) {
-            Slog.w(TAG, "Null fd. Session not started for vol: " + vol);
-            return;
-        }
-
-        // Get realpath for the fd, paths that are not /dev/null need additional
-        // setup by the ExternalStorageService before they can be ready
-        String realPath;
-        try {
-            realPath = ParcelFileDescriptor.getFile(deviceFd).getPath();
-        } catch (IOException e) {
-            Slog.wtf(TAG, "Could not get real path from fd: " + deviceFd, e);
-            return;
-        }
-
-        if ("/dev/null".equals(realPath)) {
-            Slog.i(TAG, "Volume ready for use with id: " + sessionId);
-            return;
-        }
-
+        StorageUserConnection connection = null;
         synchronized (mLock) {
-            StorageUserConnection connection = mConnections.get(userId);
+            connection = mConnections.get(userId);
             if (connection == null) {
+                Slog.i(TAG, "Creating connection for user: " + userId);
                 connection = new StorageUserConnection(mContext, userId, this);
                 mConnections.put(userId, connection);
             }
             Slog.i(TAG, "Creating session with id: " + sessionId);
-            connection.createSession(sessionId, new ParcelFileDescriptor(deviceFd));
-        }
-    }
-
-    /**
-     * Starts a storage session associated with {@code vol} after {@link #onVolumeMount}.
-     *
-     * Subsequent calls will attempt to start the storage session, but does nothing if already
-     * started. If the user associated with {@code vol} is not yet ready, all pending sesssions
-     * can be restarted with {@link onUnlockUser}.
-     *
-     * Does nothing if {@link #shouldHandle} is {@code false}
-     *
-     * Blocks until the session is started or fails
-     *
-     * @throws ExternalStorageServiceException if the session fails to start
-     */
-    public void onVolumeReady(VolumeInfo vol) throws ExternalStorageServiceException {
-        if (!shouldHandle(vol)) {
-            return;
+            connection.createSession(sessionId, new ParcelFileDescriptor(deviceFd),
+                    vol.getPath().getPath(), vol.getInternalPath().getPath());
         }
 
-        Slog.i(TAG, "On volume ready " + vol);
-        String sessionId = vol.getId();
-
-        StorageUserConnection connection = null;
-        synchronized (mLock) {
-            connection = mConnections.get(vol.getMountUserId());
-            if (connection == null) {
-                Slog.i(TAG, "Volume ready but no associated connection");
-                return;
-            }
-        }
-
-        connection.initSession(sessionId, vol.getPath().getPath(),
-                vol.getInternalPath().getPath());
-
-        if (isReady()) {
+        // At boot, a volume can be mounted before user is unlocked, in that case, we create it
+        // above and save it so that we can restart all sessions when the user is unlocked
+        if (mExternalStorageServiceComponent != null) {
             connection.startSession(sessionId);
         } else {
             Slog.i(TAG, "Controller not initialised, session not started " + sessionId);
@@ -205,14 +162,10 @@
         if (connection != null) {
             String sessionId = vol.getId();
 
-            if (isReady()) {
-                try {
-                    connection.removeSessionAndWait(sessionId);
-                } catch (ExternalStorageServiceException e) {
-                    Slog.e(TAG, "Failed to end session for vol with id: " + sessionId, e);
-                }
-            } else {
-                Slog.i(TAG, "Controller not initialised, session not ended " + sessionId);
+            try {
+                connection.removeSessionAndWait(sessionId);
+            } catch (ExternalStorageServiceException e) {
+                Slog.e(TAG, "Failed to end session for vol with id: " + sessionId, e);
             }
         }
     }
@@ -232,7 +185,7 @@
 
         Slog.i(TAG, "On user unlock " + userId);
         if (userId == 0) {
-            init();
+            initExternalStorageServiceComponent();
         }
 
         StorageUserConnection connection = null;
@@ -259,13 +212,6 @@
             return;
         }
 
-        if (!isReady()) {
-            synchronized (mLock) {
-                mConnections.clear();
-            }
-            return;
-        }
-
         SparseArray<StorageUserConnection> connections = new SparseArray();
         synchronized (mLock) {
             mIsResetting = true;
@@ -311,7 +257,7 @@
         }
     }
 
-    private void init() throws ExternalStorageServiceException {
+    private void initExternalStorageServiceComponent() throws ExternalStorageServiceException {
         Slog.i(TAG, "Initialialising...");
         ProviderInfo provider = mContext.getPackageManager().resolveContentProvider(
                 MediaStore.AUTHORITY, PackageManager.MATCH_DIRECT_BOOT_AWARE
@@ -415,8 +361,4 @@
     private boolean shouldHandle(@Nullable VolumeInfo vol) {
         return mIsFuseEnabled && !mIsResetting && (vol == null || isEmulatedOrPublic(vol));
     }
-
-    private boolean isReady() {
-        return mExternalStorageServiceComponent != null;
-    }
 }
diff --git a/services/core/java/com/android/server/storage/StorageUserConnection.java b/services/core/java/com/android/server/storage/StorageUserConnection.java
index 24b56a4..7c47730 100644
--- a/services/core/java/com/android/server/storage/StorageUserConnection.java
+++ b/services/core/java/com/android/server/storage/StorageUserConnection.java
@@ -75,46 +75,20 @@
     /**
      * Creates and stores a storage {@link Session}.
      *
-     * Created sessions must be initialised with {@link #initSession} before starting with
-     * {@link #startSession}.
-     *
      * They must also be cleaned up with {@link #removeSession}.
      *
      * @throws IllegalArgumentException if a {@code Session} with {@code sessionId} already exists
      */
-    public void createSession(String sessionId, ParcelFileDescriptor pfd) {
+    public void createSession(String sessionId, ParcelFileDescriptor pfd, String upperPath,
+            String lowerPath) {
         Preconditions.checkNotNull(sessionId);
         Preconditions.checkNotNull(pfd);
+        Preconditions.checkNotNull(upperPath);
+        Preconditions.checkNotNull(lowerPath);
 
         synchronized (mLock) {
             Preconditions.checkArgument(!mSessions.containsKey(sessionId));
-            mSessions.put(sessionId, new Session(sessionId, pfd));
-        }
-    }
-
-    /**
-     * Initialise a storage {@link Session}.
-     *
-     * Initialised sessions can be started with {@link #startSession}.
-     *
-     * They must also be cleaned up with {@link #removeSession}.
-     *
-     * @throws IllegalArgumentException if {@code sessionId} does not exist or is initialised
-     */
-    public void initSession(String sessionId, String upperPath, String lowerPath) {
-        synchronized (mLock) {
-            Session session = mSessions.get(sessionId);
-            if (session == null) {
-                throw new IllegalStateException("Failed to initialise non existent session. Id: "
-                        + sessionId + ". Upper path: " + upperPath + ". Lower path: " + lowerPath);
-            } else if (session.isInitialisedLocked()) {
-                throw new IllegalStateException("Already initialised session. Id: "
-                        + sessionId + ". Upper path: " + upperPath + ". Lower path: " + lowerPath);
-            } else {
-                session.upperPath = upperPath;
-                session.lowerPath = lowerPath;
-                Slog.i(TAG, "Initialised session: " + session);
-            }
+            mSessions.put(sessionId, new Session(sessionId, pfd, upperPath, lowerPath));
         }
     }
 
@@ -440,14 +414,14 @@
     private static final class Session implements AutoCloseable {
         public final String sessionId;
         public final ParcelFileDescriptor pfd;
-        @GuardedBy("mLock")
-        public String lowerPath;
-        @GuardedBy("mLock")
-        public String upperPath;
+        public final String lowerPath;
+        public final String upperPath;
 
-        Session(String sessionId, ParcelFileDescriptor pfd) {
+        Session(String sessionId, ParcelFileDescriptor pfd, String upperPath, String lowerPath) {
             this.sessionId = sessionId;
             this.pfd = pfd;
+            this.upperPath = upperPath;
+            this.lowerPath = lowerPath;
         }
 
         @Override
diff --git a/services/core/java/com/android/server/updates/EmergencyNumberDbInstallReceiver.java b/services/core/java/com/android/server/updates/EmergencyNumberDbInstallReceiver.java
index cb0b45c..c78a8e6 100644
--- a/services/core/java/com/android/server/updates/EmergencyNumberDbInstallReceiver.java
+++ b/services/core/java/com/android/server/updates/EmergencyNumberDbInstallReceiver.java
@@ -37,9 +37,8 @@
         Slog.i(TAG, "Emergency number database is updated in file partition");
 
         // Notify EmergencyNumberTracker for emergency number installation complete.
-        Intent notifyInstallComplete = new Intent(
-                TelephonyManager.ACTION_OTA_EMERGENCY_NUMBER_DB_INSTALLED);
-        context.sendBroadcast(
-                notifyInstallComplete, android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
+        TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(
+                Context.TELEPHONY_SERVICE);
+        telephonyManager.notifyOtaEmergencyNumberDbInstalled();
     }
 }
diff --git a/services/core/java/com/android/server/wm/ActivityDisplay.java b/services/core/java/com/android/server/wm/ActivityDisplay.java
index ebfc65e..be7dfe5 100644
--- a/services/core/java/com/android/server/wm/ActivityDisplay.java
+++ b/services/core/java/com/android/server/wm/ActivityDisplay.java
@@ -1080,6 +1080,8 @@
                         ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND);
                 mService.mH.sendMessage(msg);
             }
+            mService.mWindowManager.mDisplayNotificationController.dispatchDisplayChanged(
+                    this, getConfiguration());
         }
         return changes;
     }
@@ -1408,7 +1410,7 @@
             boolean preserveWindows, boolean notifyClients) {
         for (int stackNdx = getChildCount() - 1; stackNdx >= 0; --stackNdx) {
             final ActivityStack stack = getChildAt(stackNdx);
-            stack.ensureActivitiesVisibleLocked(starting, configChanges, preserveWindows,
+            stack.ensureActivitiesVisible(starting, configChanges, preserveWindows,
                     notifyClients);
         }
     }
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index f24fa07..e16f3fc 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -121,6 +121,7 @@
 import static com.android.server.am.ActivityRecordProto.STATE;
 import static com.android.server.am.ActivityRecordProto.TRANSLUCENT;
 import static com.android.server.am.ActivityRecordProto.VISIBLE;
+import static com.android.server.am.ActivityRecordProto.VISIBLE_REQUESTED;
 import static com.android.server.am.EventLogTags.AM_RELAUNCH_ACTIVITY;
 import static com.android.server.am.EventLogTags.AM_RELAUNCH_RESUME_ACTIVITY;
 import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
@@ -172,11 +173,10 @@
 import static com.android.server.wm.ActivityTaskManagerService.getInputDispatchingTimeoutLocked;
 import static com.android.server.wm.AppWindowTokenProto.ALL_DRAWN;
 import static com.android.server.wm.AppWindowTokenProto.APP_STOPPED;
-import static com.android.server.wm.AppWindowTokenProto.CLIENT_HIDDEN;
+import static com.android.server.wm.AppWindowTokenProto.CLIENT_VISIBLE;
 import static com.android.server.wm.AppWindowTokenProto.DEFER_HIDING_CLIENT;
 import static com.android.server.wm.AppWindowTokenProto.FILLS_PARENT;
 import static com.android.server.wm.AppWindowTokenProto.FROZEN_BOUNDS;
-import static com.android.server.wm.AppWindowTokenProto.HIDDEN_SET_FROM_TRANSFERRED_STARTING_WINDOW;
 import static com.android.server.wm.AppWindowTokenProto.IS_ANIMATING;
 import static com.android.server.wm.AppWindowTokenProto.IS_WAITING_FOR_TRANSITION_START;
 import static com.android.server.wm.AppWindowTokenProto.LAST_ALL_DRAWN;
@@ -190,7 +190,7 @@
 import static com.android.server.wm.AppWindowTokenProto.STARTING_MOVED;
 import static com.android.server.wm.AppWindowTokenProto.STARTING_WINDOW;
 import static com.android.server.wm.AppWindowTokenProto.THUMBNAIL;
-import static com.android.server.wm.AppWindowTokenProto.VISIBLE_REQUESTED;
+import static com.android.server.wm.AppWindowTokenProto.VISIBLE_SET_FROM_TRANSFERRED_STARTING_WINDOW;
 import static com.android.server.wm.AppWindowTokenProto.WINDOW_TOKEN;
 import static com.android.server.wm.IdentifierProto.HASH_CODE;
 import static com.android.server.wm.IdentifierProto.TITLE;
@@ -333,6 +333,9 @@
 import java.util.HashSet;
 import java.util.List;
 import java.util.Objects;
+import java.util.function.Consumer;
+import java.util.function.Function;
+import java.util.function.Predicate;
 
 /**
  * An entry in the history stack, representing an activity.
@@ -461,15 +464,16 @@
     private boolean keysPaused;     // has key dispatching been paused for it?
     int launchMode;         // the launch mode activity attribute.
     int lockTaskLaunchMode; // the lockTaskMode manifest attribute, subject to override
+    private boolean mVisible;        // Should this token's windows be visible?
     boolean visibleIgnoringKeyguard; // is this activity visible, ignoring the fact that Keyguard
                                      // might hide this activity?
-    // True if the hidden state of this token was forced to false due to a transferred starting
+    // True if the visible state of this token was forced to true due to a transferred starting
     // window.
-    private boolean mHiddenSetFromTransferredStartingWindow;
-    // TODO: figureout how to consolidate with the same variable in ActivityRecord.
+    private boolean mVisibleSetFromTransferredStartingWindow;
+    // TODO: figure out how to consolidate with the same variable in ActivityRecord.
     private boolean mDeferHidingClient; // If true we told WM to defer reporting to the client
                                         // process that it is hidden.
-    private boolean mLastDeferHidingClient; // If true we will defer setting mClientHidden to true
+    private boolean mLastDeferHidingClient; // If true we will defer setting mClientVisible to false
                                            // and reporting to the client that it is hidden.
     boolean sleeping;       // have we told the activity to sleep?
     boolean nowVisible;     // is this activity's window visible?
@@ -534,8 +538,8 @@
 
     private Task mLastParent;
 
-    // Have we told the window clients to hide themselves?
-    private boolean mClientHidden;
+    // Have we told the window clients to show themselves?
+    private boolean mClientVisible;
 
     boolean firstWindowDrawn;
     // Last drawn state we reported to the app token.
@@ -849,13 +853,14 @@
             pw.println(requestedVrComponent);
         }
         super.dump(pw, prefix, dumpAll);
+        pw.print(" visible="); pw.print(mVisible);
         if (appToken != null) {
             pw.println(prefix + "app=true mVoiceInteraction=" + mVoiceInteraction);
         }
         pw.print(prefix); pw.print(" mOccludesParent="); pw.print(mOccludesParent);
         pw.print(" mOrientation="); pw.println(mOrientation);
         pw.println(prefix + "mVisibleRequested=" + mVisibleRequested
-                + " mClientHidden=" + mClientHidden
+                + " mClientVisible=" + mClientVisible
                 + ((mDeferHidingClient) ? " mDeferHidingClient=" + mDeferHidingClient : "")
                 + " reportedDrawn=" + reportedDrawn + " reportedVisible=" + reportedVisible);
         if (paused) {
@@ -879,13 +884,13 @@
             pw.print(" mIsExiting="); pw.println(mIsExiting);
         }
         if (startingWindow != null || startingSurface != null
-                || startingDisplayed || startingMoved || mHiddenSetFromTransferredStartingWindow) {
+                || startingDisplayed || startingMoved || mVisibleSetFromTransferredStartingWindow) {
             pw.print(prefix); pw.print("startingWindow="); pw.print(startingWindow);
             pw.print(" startingSurface="); pw.print(startingSurface);
             pw.print(" startingDisplayed="); pw.print(startingDisplayed);
             pw.print(" startingMoved="); pw.print(startingMoved);
             pw.println(" mHiddenSetFromTransferredStartingWindow="
-                    + mHiddenSetFromTransferredStartingWindow);
+                    + mVisibleSetFromTransferredStartingWindow);
         }
         if (!mFrozenBounds.isEmpty()) {
             pw.print(prefix); pw.print("mFrozenBounds="); pw.println(mFrozenBounds);
@@ -1481,7 +1486,7 @@
         }
 
         // Application tokens start out hidden.
-        setHidden(true);
+        setVisible(false);
         mVisibleRequested = false;
 
         ColorDisplayService.ColorDisplayServiceInternal cds = LocalServices.getService(
@@ -1513,6 +1518,7 @@
         inHistory = false;
         nowVisible = false;
         mDrawn = false;
+        mClientVisible = true;
         idle = false;
         hasBeenLaunched = false;
         mStackSupervisor = supervisor;
@@ -1581,6 +1587,12 @@
         return this;
     }
 
+    @Override
+    boolean hasActivity() {
+        // I am an activity!
+        return true;
+    }
+
     void setProcess(WindowProcessController proc) {
         app = proc;
         final ActivityRecord root = task != null ? task.getRootActivity() : null;
@@ -3198,7 +3210,7 @@
                         "Removing starting %s from %s", tStartingWindow, fromActivity);
                 fromActivity.removeChild(tStartingWindow);
                 fromActivity.postWindowRemoveStartingWindowCleanup(tStartingWindow);
-                fromActivity.mHiddenSetFromTransferredStartingWindow = false;
+                fromActivity.mVisibleSetFromTransferredStartingWindow = false;
                 addWindow(tStartingWindow);
 
                 // Propagate other interesting state between the tokens. If the old token is displayed,
@@ -3211,12 +3223,12 @@
                 if (fromActivity.firstWindowDrawn) {
                     firstWindowDrawn = true;
                 }
-                if (!fromActivity.isHidden()) {
-                    setHidden(false);
+                if (fromActivity.isVisible()) {
+                    setVisible(true);
                     mVisibleRequested = true;
-                    mHiddenSetFromTransferredStartingWindow = true;
+                    mVisibleSetFromTransferredStartingWindow = true;
                 }
-                setClientHidden(fromActivity.mClientHidden);
+                setClientVisible(fromActivity.mClientVisible);
 
                 transferAnimation(fromActivity);
 
@@ -3418,11 +3430,21 @@
     }
 
     @Override
-    boolean forAllActivities(ToBooleanFunction<ActivityRecord> callback) {
+    boolean forAllActivities(Function<ActivityRecord, Boolean> callback) {
         return callback.apply(this);
     }
 
     @Override
+    void forAllActivities(Consumer<ActivityRecord> callback, boolean traverseTopToBottom) {
+        callback.accept(this);
+    }
+
+    @Override
+    ActivityRecord getActivity(Predicate<ActivityRecord> callback, boolean traverseTopToBottom) {
+        return callback.test(this) ? this : null;
+    }
+
+    @Override
     protected void setLayer(Transaction t, int layer) {
         if (!mSurfaceAnimator.hasLeash()) {
             t.setLayer(mSurfaceControl, layer);
@@ -3828,7 +3850,14 @@
     boolean isVisible() {
         // If the activity isn't hidden then it is considered visible and there is no need to check
         // its children windows to see if they are visible.
-        return !isHidden();
+        return mVisible;
+    }
+
+    void setVisible(boolean visible) {
+        if (visible != mVisible) {
+            mVisible = visible;
+            scheduleAnimation();
+        }
     }
 
     void setVisibility(boolean visible) {
@@ -3864,14 +3893,14 @@
                 // We previously deferred telling the client to hide itself when visibility was
                 // initially set to false. Now we would like it to hide, so go ahead and set it.
                 mLastDeferHidingClient = deferHidingClient;
-                setClientHidden(true);
+                setClientVisible(false);
             }
             return;
         }
 
         ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
-                "setAppVisibility(%s, visible=%b): %s hidden=%b mVisibleRequested=%b Callers=%s",
-                appToken, visible, appTransition, isHidden(), mVisibleRequested,
+                "setAppVisibility(%s, visible=%b): %s visible=%b mVisibleRequested=%b Callers=%s",
+                appToken, visible, appTransition, isVisible(), mVisibleRequested,
                 Debug.getCallers(6));
 
         final DisplayContent displayContent = getDisplayContent();
@@ -3901,15 +3930,15 @@
             startingMoved = false;
             // If the token is currently hidden (should be the common case), or has been
             // stopped, then we need to set up to wait for its windows to be ready.
-            if (isHidden() || mAppStopped) {
+            if (!isVisible() || mAppStopped) {
                 clearAllDrawn();
 
                 // If the app was already visible, don't reset the waitingToShow state.
-                if (isHidden()) {
+                if (!isVisible()) {
                     waitingToShow = true;
 
                     // If the client isn't hidden, we don't need to reset the drawing state.
-                    if (isClientHidden()) {
+                    if (!isClientVisible()) {
                         // Let's reset the draw state in order to prevent the starting window to be
                         // immediately dismissed when the app still has the surface.
                         forAllWindows(w -> {
@@ -3929,7 +3958,7 @@
             // we still need to tell the client to make its windows visible so they get drawn.
             // Otherwise, we will wait on performing the transition until all windows have been
             // drawn, they never will be, and we are sad.
-            setClientHidden(false);
+            setClientVisible(true);
 
             requestUpdateWallpaperIfNeeded();
 
@@ -3975,9 +4004,9 @@
             boolean visible, int transit, boolean performLayout, boolean isVoiceInteraction) {
 
         boolean delayed = false;
-        // Reset the state of mHiddenSetFromTransferredStartingWindow since visibility is actually
+        // Reset the state of mVisibleSetFromTransferredStartingWindow since visibility is actually
         // been set by the app now.
-        mHiddenSetFromTransferredStartingWindow = false;
+        mVisibleSetFromTransferredStartingWindow = false;
 
         // Allow for state changes and animation to be applied if:
         // * token is transitioning visibility state
@@ -3987,7 +4016,7 @@
         // * or the token is the opening app and visible while opening task behind existing one.
         final DisplayContent displayContent = getDisplayContent();
         boolean visibilityChanged = false;
-        if (isHidden() == visible || (isHidden() && mIsExiting)
+        if (isVisible() != visible || (!isVisible() && mIsExiting)
                 || (visible && waitingForReplacement())
                 || (visible && displayContent.mOpeningApps.contains(this)
                 && displayContent.mAppTransition.getAppTransition() == TRANSIT_TASK_OPEN_BEHIND)) {
@@ -3995,7 +4024,7 @@
                     mWmService.mAccessibilityController;
             boolean changed = false;
             ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
-                    "Changing app %s hidden=%b performLayout=%b", this, isHidden(),
+                    "Changing app %s visible=%b performLayout=%b", this, isVisible(),
                     performLayout);
 
             boolean runningAppAnimation = false;
@@ -4020,7 +4049,7 @@
                 changed |= win.onAppVisibilityChanged(visible, runningAppAnimation);
             }
 
-            setHidden(!visible);
+            setVisible(visible);
             mVisibleRequested = visible;
             visibilityChanged = true;
             if (!visible) {
@@ -4039,8 +4068,8 @@
             }
 
             ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
-                    "commitVisibility: %s: hidden=%b visibleRequested=%b", this,
-                    isHidden(), mVisibleRequested);
+                    "commitVisibility: %s: visible=%b visibleRequested=%b", this,
+                    isVisible(), mVisibleRequested);
 
             if (changed) {
                 displayContent.getInputMonitor().setUpdateInputWindowsNeededLw();
@@ -4077,7 +4106,7 @@
             // If we're becoming invisible, update the client visibility if we are not running an
             // animation. Otherwise, we'll update client visibility in onAnimationFinished.
             if (visible || !isAnimating()) {
-                setClientHidden(!visible);
+                setClientVisible(visible);
             }
 
             if (!displayContent.mClosingApps.contains(this)
@@ -4104,7 +4133,7 @@
             // no animation but there will still be a transition set.
             // We still need to delay hiding the surface such that it
             // can be synchronized with showing the next surface in the transition.
-            if (isHidden() && !delayed && !displayContent.mAppTransition.isTransitionSet()) {
+            if (!isVisible() && !delayed && !displayContent.mAppTransition.isTransitionSet()) {
                 SurfaceControl.openTransaction();
                 for (int i = mChildren.size() - 1; i >= 0; i--) {
                     mChildren.get(i).mWinAnimator.hide("immediately hidden");
@@ -4116,12 +4145,6 @@
         return delayed;
     }
 
-    @Override
-    void setHidden(boolean hidden) {
-        super.setHidden(hidden);
-        scheduleAnimation();
-    }
-
     /**
      * See {@link Activity#setDisablePreviewScreenshots}.
      */
@@ -4550,7 +4573,7 @@
         // If the activity is stopped, stopping, cycle to an active state. We avoid doing
         // this when there is an activity waiting to become translucent as the extra binder
         // calls will lead to noticeable jank. A later call to
-        // ActivityStack#ensureActivitiesVisibleLocked will bring the activity to a proper
+        // ActivityStack#ensureActivitiesVisible will bring the activity to a proper
         // active state.
         if (!isState(STARTED, RESUMED, PAUSED, STOPPED, STOPPING)
                 || getActivityStack().mTranslucentActivityWaiting != null) {
@@ -4882,8 +4905,8 @@
 
     void startFreezingScreen() {
         ProtoLog.i(WM_DEBUG_ORIENTATION,
-                "Set freezing of %s: hidden=%b freezing=%b visibleRequested=%b. %s",
-                appToken, isHidden(), mFreezingScreen, mVisibleRequested,
+                "Set freezing of %s: visible=%b freezing=%b visibleRequested=%b. %s",
+                appToken, isVisible(), mFreezingScreen, mVisibleRequested,
                 new RuntimeException().fillInStackTrace());
         if (mVisibleRequested) {
             if (!mFreezingScreen) {
@@ -4921,8 +4944,8 @@
                 return;
             }
             ProtoLog.v(WM_DEBUG_ORIENTATION,
-                        "Clear freezing of %s: hidden=%b freezing=%b", appToken,
-                                isHidden(), isFreezingScreen());
+                        "Clear freezing of %s: visible=%b freezing=%b", appToken,
+                                isVisible(), isFreezingScreen());
             stopFreezingScreen(true, force);
         }
     }
@@ -5082,7 +5105,7 @@
         boolean nowGone = mReportedVisibilityResults.nowGone;
 
         boolean nowDrawn = numInteresting > 0 && numDrawn >= numInteresting;
-        boolean nowVisible = numInteresting > 0 && numVisible >= numInteresting && !isHidden();
+        boolean nowVisible = numInteresting > 0 && numVisible >= numInteresting && isVisible();
         if (!nowGone) {
             // If the app is not yet gone, then it can only become visible/drawn.
             if (!nowDrawn) {
@@ -5110,18 +5133,18 @@
         }
     }
 
-    boolean isClientHidden() {
-        return mClientHidden;
+    boolean isClientVisible() {
+        return mClientVisible;
     }
 
-    void setClientHidden(boolean hideClient) {
-        if (mClientHidden == hideClient || (hideClient && mDeferHidingClient)) {
+    void setClientVisible(boolean clientVisible) {
+        if (mClientVisible == clientVisible || (!clientVisible && mDeferHidingClient)) {
             return;
         }
         ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
-                "setClientHidden: %s clientHidden=%b Callers=%s", this, hideClient,
+                "setClientVisible: %s clientVisible=%b Callers=%s", this, clientVisible,
                 Debug.getCallers(5));
-        mClientHidden = hideClient;
+        mClientVisible = clientVisible;
         sendAppVisibilityToClients();
     }
 
@@ -5443,11 +5466,11 @@
             // well there is no point now.
             ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Nulling last startingData");
             mStartingData = null;
-            if (mHiddenSetFromTransferredStartingWindow) {
-                // We set the hidden state to false for the token from a transferred starting window.
-                // We now reset it back to true since the starting window was the last window in the
-                // token.
-                setHidden(true);
+            if (mVisibleSetFromTransferredStartingWindow) {
+                // We set the visible state to true for the token from a transferred starting
+                // window. We now reset it back to false since the starting window was the last
+                // window in the token.
+                setVisible(false);
             }
         } else if (mChildren.size() == 1 && startingSurface != null && !isRelaunching()) {
             // If this is the last window except for a starting transition window,
@@ -5785,7 +5808,7 @@
 
     @Override
     void prepareSurfaces() {
-        final boolean show = !isHidden() || isAnimating();
+        final boolean show = isVisible() || isAnimating();
 
         if (mSurfaceControl != null) {
             if (show && !mLastSurfaceShowing) {
@@ -5904,7 +5927,7 @@
                 "AppWindowToken");
 
         clearThumbnail();
-        setClientHidden(isHidden() && !mVisibleRequested);
+        setClientVisible(isVisible() || mVisibleRequested);
 
         getDisplayContent().computeImeTargetIfNeeded(this);
 
@@ -6216,9 +6239,6 @@
         // relatively fixed.
         overrideConfig.colorMode = fullConfig.colorMode;
         overrideConfig.densityDpi = fullConfig.densityDpi;
-        overrideConfig.screenLayout = fullConfig.screenLayout
-                & (Configuration.SCREENLAYOUT_LONG_MASK
-                        | Configuration.SCREENLAYOUT_SIZE_MASK);
         // The smallest screen width is the short side of screen bounds. Because the bounds
         // and density won't be changed, smallestScreenWidthDp is also fixed.
         overrideConfig.smallestScreenWidthDp = fullConfig.smallestScreenWidthDp;
@@ -6353,6 +6373,10 @@
         // Use resolvedBounds to compute other override configurations such as appBounds
         task.computeConfigResourceOverrides(resolvedConfig, newParentConfiguration,
                 mCompatDisplayInsets);
+        // Use current screen layout as source because the size of app is independent to parent.
+        resolvedConfig.screenLayout = Task.computeScreenLayoutOverride(
+                getConfiguration().screenLayout, resolvedConfig.screenWidthDp,
+                resolvedConfig.screenHeightDp);
 
         // Use parent orientation if it cannot be decided by bounds, so the activity can fit inside
         // the parent bounds appropriately.
@@ -7287,12 +7311,13 @@
         writeToProto(proto, APP_WINDOW_TOKEN, WindowTraceLogLevel.ALL);
         writeIdentifierToProto(proto, IDENTIFIER);
         proto.write(STATE, mState.toString());
-        proto.write(VISIBLE, mVisibleRequested);
+        proto.write(VISIBLE_REQUESTED, mVisibleRequested);
         proto.write(FRONT_OF_TASK, isRootOfTask());
         if (hasProcess()) {
             proto.write(PROC_ID, app.getPid());
         }
         proto.write(TRANSLUCENT, !occludesParent());
+        proto.write(VISIBLE, mVisible);
     }
 
     public void writeToProto(ProtoOutputStream proto, long fieldId) {
@@ -7323,8 +7348,8 @@
         }
         proto.write(FILLS_PARENT, mOccludesParent);
         proto.write(APP_STOPPED, mAppStopped);
-        proto.write(VISIBLE_REQUESTED, mVisibleRequested);
-        proto.write(CLIENT_HIDDEN, mClientHidden);
+        proto.write(com.android.server.wm.AppWindowTokenProto.VISIBLE_REQUESTED, mVisibleRequested);
+        proto.write(CLIENT_VISIBLE, mClientVisible);
         proto.write(DEFER_HIDING_CLIENT, mDeferHidingClient);
         proto.write(REPORTED_DRAWN, reportedDrawn);
         proto.write(REPORTED_VISIBLE, reportedVisible);
@@ -7337,11 +7362,12 @@
         }
         proto.write(STARTING_DISPLAYED, startingDisplayed);
         proto.write(STARTING_MOVED, startingMoved);
-        proto.write(HIDDEN_SET_FROM_TRANSFERRED_STARTING_WINDOW,
-                mHiddenSetFromTransferredStartingWindow);
+        proto.write(VISIBLE_SET_FROM_TRANSFERRED_STARTING_WINDOW,
+                mVisibleSetFromTransferredStartingWindow);
         for (Rect bounds : mFrozenBounds) {
             bounds.writeToProto(proto, FROZEN_BOUNDS);
         }
+        proto.write(com.android.server.wm.AppWindowTokenProto.VISIBLE, mVisible);
         proto.end(token);
     }
 
diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java
index ac94125..f1c47eb 100644
--- a/services/core/java/com/android/server/wm/ActivityStack.java
+++ b/services/core/java/com/android/server/wm/ActivityStack.java
@@ -62,7 +62,6 @@
 import static com.android.server.am.ActivityStackProto.FULLSCREEN;
 import static com.android.server.am.ActivityStackProto.RESUMED_ACTIVITY;
 import static com.android.server.am.ActivityStackProto.STACK;
-import static com.android.server.wm.ActivityRecord.FINISH_RESULT_REMOVED;
 import static com.android.server.wm.ActivityStack.ActivityState.PAUSED;
 import static com.android.server.wm.ActivityStack.ActivityState.PAUSING;
 import static com.android.server.wm.ActivityStack.ActivityState.RESUMED;
@@ -119,7 +118,6 @@
 import static com.android.server.wm.StackProto.FILLS_PARENT;
 import static com.android.server.wm.StackProto.MINIMIZE_AMOUNT;
 import static com.android.server.wm.StackProto.WINDOW_CONTAINER;
-import static com.android.server.wm.Task.REPARENT_LEAVE_STACK_IN_PLACE;
 import static com.android.server.wm.WindowContainer.AnimationFlags.CHILDREN;
 import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_MOVEMENT;
@@ -203,7 +201,7 @@
 class ActivityStack extends WindowContainer<Task> implements BoundsAnimationTarget,
         ConfigurationContainerListener {
     private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityStack" : TAG_ATM;
-    private static final String TAG_ADD_REMOVE = TAG + POSTFIX_ADD_REMOVE;
+    static final String TAG_ADD_REMOVE = TAG + POSTFIX_ADD_REMOVE;
     private static final String TAG_APP = TAG + POSTFIX_APP;
     private static final String TAG_CLEANUP = TAG + POSTFIX_CLEANUP;
     private static final String TAG_PAUSE = TAG + POSTFIX_PAUSE;
@@ -212,10 +210,10 @@
     private static final String TAG_STACK = TAG + POSTFIX_STACK;
     private static final String TAG_STATES = TAG + POSTFIX_STATES;
     private static final String TAG_SWITCH = TAG + POSTFIX_SWITCH;
-    private static final String TAG_TASKS = TAG + POSTFIX_TASKS;
+    static final String TAG_TASKS = TAG + POSTFIX_TASKS;
     private static final String TAG_TRANSITION = TAG + POSTFIX_TRANSITION;
     private static final String TAG_USER_LEAVING = TAG + POSTFIX_USER_LEAVING;
-    private static final String TAG_VISIBILITY = TAG + POSTFIX_VISIBILITY;
+    static final String TAG_VISIBILITY = TAG + POSTFIX_VISIBILITY;
 
     // Ticks during which we check progress while waiting for an app to launch.
     private static final int LAUNCH_TICK = 500;
@@ -516,6 +514,10 @@
         }
     }
 
+    private static final ResetTargetTaskHelper sResetTargetTaskHelper = new ResetTargetTaskHelper();
+    private final EnsureActivitiesVisibleHelper mEnsureActivitiesVisibleHelper =
+            new EnsureActivitiesVisibleHelper(this);
+
     int numActivities() {
         int count = 0;
         for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
@@ -1492,8 +1494,7 @@
 
     void goToSleep() {
         // Ensure visibility without updating configuration, as activities are about to sleep.
-        ensureActivitiesVisibleLocked(null /* starting */, 0 /* configChanges */,
-                !PRESERVE_WINDOWS);
+        ensureActivitiesVisible(null /* starting */, 0 /* configChanges */, !PRESERVE_WINDOWS);
 
         // Make sure any paused or stopped but visible activities are now sleeping.
         // This ensures that the activity's onStop() is called.
@@ -1979,127 +1980,25 @@
      * Make sure that all activities that need to be visible in the stack (that is, they
      * currently can be seen by the user) actually are and update their configuration.
      */
-    final void ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges,
+    void ensureActivitiesVisible(ActivityRecord starting, int configChanges,
             boolean preserveWindows) {
-        ensureActivitiesVisibleLocked(starting, configChanges, preserveWindows,
-                true /* notifyClients */);
+        ensureActivitiesVisible(starting, configChanges, preserveWindows, true /* notifyClients */);
     }
 
     /**
      * Ensure visibility with an option to also update the configuration of visible activities.
-     * @see #ensureActivitiesVisibleLocked(ActivityRecord, int, boolean)
+     * @see #ensureActivitiesVisible(ActivityRecord, int, boolean)
      * @see RootActivityContainer#ensureActivitiesVisible(ActivityRecord, int, boolean)
      */
     // TODO: Should be re-worked based on the fact that each task as a stack in most cases.
-    final void ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges,
+    void ensureActivitiesVisible(ActivityRecord starting, int configChanges,
             boolean preserveWindows, boolean notifyClients) {
         mTopActivityOccludesKeyguard = false;
         mTopDismissingKeyguardActivity = null;
         mStackSupervisor.getKeyguardController().beginActivityVisibilityUpdate();
         try {
-            ActivityRecord top = topRunningActivityLocked();
-            if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "ensureActivitiesVisible behind " + top
-                    + " configChanges=0x" + Integer.toHexString(configChanges));
-            if (top != null) {
-                checkTranslucentActivityWaiting(top);
-            }
-
-            // If the top activity is not fullscreen, then we need to
-            // make sure any activities under it are now visible.
-            boolean aboveTop = top != null;
-            final boolean stackShouldBeVisible = shouldBeVisible(starting);
-            boolean behindFullscreenActivity = !stackShouldBeVisible;
-            // We should not resume activities that being launched behind because these
-            // activities are actually behind other fullscreen activities, but still required
-            // to be visible (such as performing Recents animation).
-            final boolean resumeTopActivity = isFocusable() && isInStackLocked(starting) == null
-                    && top != null && !top.mLaunchTaskBehind;
-            for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
-                final Task task = getChildAt(taskNdx);
-                for (int activityNdx = task.getChildCount() - 1; activityNdx >= 0; --activityNdx) {
-                    final ActivityRecord r = task.getChildAt(activityNdx);
-                    final boolean isTop = r == top;
-                    if (aboveTop && !isTop) {
-                        continue;
-                    }
-                    aboveTop = false;
-
-                    final boolean reallyVisible = r.shouldBeVisible(behindFullscreenActivity,
-                            false /* ignoringKeyguard */);
-                    // Check whether activity should be visible without Keyguard influence
-                    if (r.visibleIgnoringKeyguard) {
-                        if (r.occludesParent()) {
-                            // At this point, nothing else needs to be shown in this task.
-                            if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Fullscreen: at " + r
-                                    + " stackVisible=" + stackShouldBeVisible
-                                    + " behindFullscreen=" + behindFullscreenActivity);
-                            behindFullscreenActivity = true;
-                        } else {
-                            behindFullscreenActivity = false;
-                        }
-                    }
-
-                    if (reallyVisible) {
-                        if (r.finishing) {
-                            continue;
-                        }
-                        if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Make visible? " + r
-                                + " finishing=" + r.finishing + " state=" + r.getState());
-                        // First: if this is not the current activity being started, make
-                        // sure it matches the current configuration.
-                        if (r != starting && notifyClients) {
-                            r.ensureActivityConfiguration(0 /* globalChanges */, preserveWindows,
-                                    true /* ignoreVisibility */);
-                        }
-
-                        if (!r.attachedToProcess()) {
-                            makeVisibleAndRestartIfNeeded(starting, configChanges, isTop,
-                                    resumeTopActivity && isTop, r);
-                        } else if (r.mVisibleRequested) {
-                            // If this activity is already visible, then there is nothing to do here.
-                            if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY,
-                                    "Skipping: already visible at " + r);
-
-                            if (r.mClientVisibilityDeferred && notifyClients) {
-                                r.makeClientVisible();
-                            }
-
-                            r.handleAlreadyVisible();
-                            if (notifyClients) {
-                                r.makeActiveIfNeeded(starting);
-                            }
-                        } else {
-                            r.makeVisibleIfNeeded(starting, notifyClients);
-                        }
-                        // Aggregate current change flags.
-                        configChanges |= r.configChangeFlags;
-                    } else {
-                        if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Make invisible? " + r
-                                + " finishing=" + r.finishing + " state=" + r.getState()
-                                + " stackShouldBeVisible=" + stackShouldBeVisible
-                                + " behindFullscreenActivity=" + behindFullscreenActivity
-                                + " mLaunchTaskBehind=" + r.mLaunchTaskBehind);
-                        r.makeInvisible();
-                    }
-                }
-                final int windowingMode = getWindowingMode();
-                if (windowingMode == WINDOWING_MODE_FREEFORM) {
-                    // The visibility of tasks and the activities they contain in freeform stack are
-                    // determined individually unlike other stacks where the visibility or fullscreen
-                    // status of an activity in a previous task affects other.
-                    behindFullscreenActivity = !stackShouldBeVisible;
-                } else if (isActivityTypeHome()) {
-                    if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Home task: at " + task
-                            + " stackShouldBeVisible=" + stackShouldBeVisible
-                            + " behindFullscreenActivity=" + behindFullscreenActivity);
-                    // No other task in the home stack should be visible behind the home activity.
-                    // Home activities is usually a translucent activity with the wallpaper behind
-                    // them. However, when they don't have the wallpaper behind them, we want to
-                    // show activities in the next application stack behind them vs. another
-                    // task in the home stack like recents.
-                    behindFullscreenActivity = true;
-                }
-            }
+            mEnsureActivitiesVisibleHelper.process(
+                    starting, configChanges, preserveWindows, notifyClients);
 
             if (mTranslucentActivityWaiting != null &&
                     mUndrawnActivitiesBelowTopTranslucent.isEmpty()) {
@@ -2214,7 +2113,7 @@
         return (flags & FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD) != 0;
     }
 
-    private void checkTranslucentActivityWaiting(ActivityRecord top) {
+    void checkTranslucentActivityWaiting(ActivityRecord top) {
         if (mTranslucentActivityWaiting != top) {
             mUndrawnActivitiesBelowTopTranslucent.clear();
             if (mTranslucentActivityWaiting != null) {
@@ -2226,31 +2125,6 @@
         }
     }
 
-    private boolean makeVisibleAndRestartIfNeeded(ActivityRecord starting, int configChanges,
-            boolean isTop, boolean andResume, ActivityRecord r) {
-        // We need to make sure the app is running if it's the top, or it is just made visible from
-        // invisible. If the app is already visible, it must have died while it was visible. In this
-        // case, we'll show the dead window but will not restart the app. Otherwise we could end up
-        // thrashing.
-        if (isTop || !r.mVisibleRequested) {
-            // This activity needs to be visible, but isn't even running...
-            // get it started and resume if no other stack in this stack is resumed.
-            if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Start and freeze screen for " + r);
-            if (r != starting) {
-                r.startFreezingScreenLocked(configChanges);
-            }
-            if (!r.mVisibleRequested || r.mLaunchTaskBehind) {
-                if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Starting and making visible: " + r);
-                r.setVisibility(true);
-            }
-            if (r != starting) {
-                mStackSupervisor.startSpecificActivityLocked(r, andResume, true /* checkConfig */);
-                return true;
-            }
-        }
-        return false;
-    }
-
     void convertActivityToTranslucent(ActivityRecord r) {
         mTranslucentActivityWaiting = r;
         mUndrawnActivitiesBelowTopTranslucent.clear();
@@ -2490,7 +2364,7 @@
                         && next.containsDismissKeyguardWindow();
 
                 if (canShowWhenLocked || mayDismissKeyguard) {
-                    ensureActivitiesVisibleLocked(null /* starting */, 0 /* configChanges */,
+                    ensureActivitiesVisible(null /* starting */, 0 /* configChanges */,
                             !PRESERVE_WINDOWS);
                     nothingToResume = shouldSleepActivities();
                 }
@@ -2819,7 +2693,7 @@
                     next.showStartingWindow(null /* prev */, false /* newTask */,
                             false /* taskSwitch */);
                 }
-                mStackSupervisor.startSpecificActivityLocked(next, true, false);
+                mStackSupervisor.startSpecificActivity(next, true, false);
                 return true;
             }
 
@@ -2846,7 +2720,7 @@
                 if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Restarting: " + next);
             }
             if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Restarting " + next);
-            mStackSupervisor.startSpecificActivityLocked(next, true, true);
+            mStackSupervisor.startSpecificActivity(next, true, true);
         }
 
         return true;
@@ -2980,7 +2854,7 @@
                 // If the caller has requested that the target task be
                 // reset, then do so.
                 if ((r.intent.getFlags() & Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
-                    resetTaskIfNeededLocked(r, r);
+                    resetTaskIfNeeded(r, r);
                     doShow = topRunningNonDelayedActivityLocked(null) == r;
                 }
             } else if (options != null && options.getAnimationType()
@@ -2991,7 +2865,7 @@
                 // Don't do a starting window for mLaunchTaskBehind. More importantly make sure we
                 // tell WindowManager that r is visible even though it is at the back of the stack.
                 r.setVisibility(true);
-                ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
+                ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
                 // Go ahead to execute app transition for this activity since the app transition
                 // will not be triggered through the resume channel.
                 getDisplay().mDisplayContent.executeAppTransition();
@@ -3052,297 +2926,6 @@
     }
 
     /**
-     * Helper method for {@link #resetTaskIfNeededLocked(ActivityRecord, ActivityRecord)}.
-     * Performs a reset of the given task, if needed for new activity start.
-     * @param task The task containing the Activity (taskTop) that might be reset.
-     * @param forceReset Flag indicating if clear task was requested
-     * @return An ActivityOptions that needs to be processed.
-     */
-    private ActivityOptions resetTargetTaskIfNeededLocked(Task task, boolean forceReset) {
-        ActivityOptions topOptions = null;
-
-        // Tracker of the end of currently handled reply chain (sublist) of activities. What happens
-        // to activities in the same chain will depend on what the end activity of the chain needs.
-        int replyChainEnd = -1;
-        boolean canMoveOptions = true;
-        int numTasksCreated = 0;
-
-        // We only do this for activities that are not the root of the task (since if we finish
-        // the root, we may no longer have the task!).
-        final int numActivities = task.getChildCount();
-        int lastActivityNdx = task.findRootIndex(true /* effectiveRoot */);
-        if (lastActivityNdx == -1) {
-            lastActivityNdx = 0;
-        }
-        for (int i = numActivities - 1; i > lastActivityNdx; --i) {
-            ActivityRecord target = task.getChildAt(i);
-            // TODO: Why is this needed? Looks like we're breaking the loop before we reach the root
-            if (target.isRootOfTask()) break;
-
-            final int flags = target.info.flags;
-            final boolean finishOnTaskLaunch =
-                    (flags & ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH) != 0;
-            final boolean allowTaskReparenting =
-                    (flags & ActivityInfo.FLAG_ALLOW_TASK_REPARENTING) != 0;
-            final boolean clearWhenTaskReset =
-                    (target.intent.getFlags() & Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0;
-
-            if (!finishOnTaskLaunch
-                    && !clearWhenTaskReset
-                    && target.resultTo != null) {
-                // If this activity is sending a reply to a previous
-                // activity, we can't do anything with it now until
-                // we reach the start of the reply chain.
-                // XXX note that we are assuming the result is always
-                // to the previous activity, which is almost always
-                // the case but we really shouldn't count on.
-                if (replyChainEnd < 0) {
-                    replyChainEnd = i;
-                }
-            } else if (!finishOnTaskLaunch
-                    && !clearWhenTaskReset
-                    && allowTaskReparenting
-                    && target.taskAffinity != null
-                    && !target.taskAffinity.equals(task.affinity)) {
-                // If this activity has an affinity for another
-                // task, then we need to move it out of here.  We will
-                // move it as far out of the way as possible, to the
-                // bottom of the activity stack.  This also keeps it
-                // correctly ordered with any activities we previously
-                // moved.
-                // TODO: We should probably look for other stacks also, since corresponding task
-                // with the same affinity is unlikely to be in the same stack.
-                final Task targetTask;
-                final ActivityRecord bottom =
-                        hasChild() && getChildAt(0).hasChild() ?
-                                getChildAt(0).getChildAt(0) : null;
-                if (bottom != null && target.taskAffinity.equals(bottom.getTask().affinity)) {
-                    // If the activity currently at the bottom has the
-                    // same task affinity as the one we are moving,
-                    // then merge it into the same task.
-                    targetTask = bottom.getTask();
-                    if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Start pushing activity " + target
-                            + " out to bottom task " + targetTask);
-                } else {
-                    targetTask = createTask(
-                            mStackSupervisor.getNextTaskIdForUserLocked(target.mUserId),
-                            target.info, null /* intent */, null /* voiceSession */,
-                            null /* voiceInteractor */, false /* toTop */);
-                    targetTask.affinityIntent = target.intent;
-                    numTasksCreated++;
-                    if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Start pushing activity " + target
-                            + " out to new task " + targetTask);
-                }
-
-                boolean noOptions = canMoveOptions;
-                final int start = replyChainEnd < 0 ? i : replyChainEnd;
-                for (int srcPos = start; srcPos >= i; --srcPos) {
-                    final ActivityRecord p = task.getChildAt(srcPos);
-                    if (p.finishing) {
-                        continue;
-                    }
-
-                    canMoveOptions = false;
-                    if (noOptions && topOptions == null) {
-                        topOptions = p.takeOptionsLocked(false /* fromClient */);
-                        if (topOptions != null) {
-                            noOptions = false;
-                        }
-                    }
-                    if (DEBUG_ADD_REMOVE) Slog.i(TAG_ADD_REMOVE,
-                            "Removing activity " + p + " from task=" + task + " adding to task="
-                            + targetTask + " Callers=" + Debug.getCallers(4));
-                    if (DEBUG_TASKS) Slog.v(TAG_TASKS,
-                            "Pushing next activity " + p + " out to target's task " + target);
-                    p.reparent(targetTask, 0 /* position - bottom */, "resetTargetTaskIfNeeded");
-                }
-
-                positionChildAtBottom(targetTask);
-                mStackSupervisor.mRecentTasks.add(targetTask);
-                replyChainEnd = -1;
-            } else if (forceReset || finishOnTaskLaunch || clearWhenTaskReset) {
-                // If the activity should just be removed -- either
-                // because it asks for it, or the task should be
-                // cleared -- then finish it and anything that is
-                // part of its reply chain.
-                int end;
-                if (clearWhenTaskReset) {
-                    // In this case, we want to finish this activity
-                    // and everything above it, so be sneaky and pretend
-                    // like these are all in the reply chain.
-                    end = task.getChildCount() - 1;
-                } else if (replyChainEnd < 0) {
-                    end = i;
-                } else {
-                    end = replyChainEnd;
-                }
-                boolean noOptions = canMoveOptions;
-                for (int srcPos = i; srcPos <= end; srcPos++) {
-                    ActivityRecord p = task.getChildAt(srcPos);
-                    if (p.finishing) {
-                        continue;
-                    }
-                    canMoveOptions = false;
-                    if (noOptions && topOptions == null) {
-                        topOptions = p.takeOptionsLocked(false /* fromClient */);
-                        if (topOptions != null) {
-                            noOptions = false;
-                        }
-                    }
-                    if (DEBUG_TASKS) Slog.w(TAG_TASKS,
-                            "resetTaskIntendedTask: calling finishActivity on " + p);
-                    if (p.finishIfPossible("reset-task", false /* oomAdj */)
-                            == FINISH_RESULT_REMOVED) {
-                        end--;
-                        srcPos--;
-                    }
-                }
-                replyChainEnd = -1;
-            } else {
-                // If we were in the middle of a chain, well the
-                // activity that started it all doesn't want anything
-                // special, so leave it all as-is.
-                replyChainEnd = -1;
-            }
-        }
-
-        // Create target stack for the newly created tasks if necessary
-        if (numTasksCreated > 0) {
-            ActivityDisplay display = getDisplay();
-            final boolean singleTaskInstanceDisplay = display.isSingleTaskInstance();
-            if (singleTaskInstanceDisplay) {
-                display = mRootActivityContainer.getDefaultDisplay();
-            }
-
-            if (singleTaskInstanceDisplay || display.alwaysCreateStack(getWindowingMode(),
-                    getActivityType())) {
-                for (int index = numTasksCreated - 1; index >= 0; index--) {
-                    final Task targetTask = getChildAt(index);
-                    final ActivityStack targetStack = display.getOrCreateStack(getWindowingMode(),
-                            getActivityType(), false /* onTop */);
-                    targetTask.reparent(targetStack, false /* toTop */,
-                            REPARENT_LEAVE_STACK_IN_PLACE, false /* animate */,
-                            true /* deferResume */, "resetTargetTask");
-                }
-            }
-        }
-
-        return topOptions;
-    }
-
-    /**
-     * Helper method for {@link #resetTaskIfNeededLocked(ActivityRecord, ActivityRecord)}.
-     * Processes all of the activities in a given Task looking for an affinity with the task
-     * of resetTaskIfNeededLocked.taskTop.
-     * @param affinityTask The task we are looking for an affinity to.
-     * @param task Task that resetTaskIfNeededLocked.taskTop belongs to.
-     * @param topTaskIsHigher True if #task has already been processed by resetTaskIfNeededLocked.
-     * @param forceReset Flag indicating if clear task was requested
-     */
-    // TODO: Consider merging with #resetTargetTaskIfNeededLocked() above
-    private int resetAffinityTaskIfNeededLocked(Task affinityTask, Task task,
-            boolean topTaskIsHigher, boolean forceReset, int taskInsertionPoint) {
-        // Tracker of the end of currently handled reply chain (sublist) of activities. What happens
-        // to activities in the same chain will depend on what the end activity of the chain needs.
-        int replyChainEnd = -1;
-        final String taskAffinity = task.affinity;
-
-        final int numActivities = task.getChildCount();
-
-        // Do not operate on or below the effective root Activity.
-        int lastActivityNdx = affinityTask.findRootIndex(true /* effectiveRoot */);
-        if (lastActivityNdx == -1) {
-            lastActivityNdx = 0;
-        }
-        for (int i = numActivities - 1; i > lastActivityNdx; --i) {
-            ActivityRecord target = task.getChildAt(i);
-            // TODO: Why is this needed? Looks like we're breaking the loop before we reach the root
-            if (target.isRootOfTask()) break;
-
-            final int flags = target.info.flags;
-            boolean finishOnTaskLaunch = (flags & ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH) != 0;
-            boolean allowTaskReparenting = (flags & ActivityInfo.FLAG_ALLOW_TASK_REPARENTING) != 0;
-
-            if (target.resultTo != null) {
-                // If this activity is sending a reply to a previous
-                // activity, we can't do anything with it now until
-                // we reach the start of the reply chain.
-                // XXX note that we are assuming the result is always
-                // to the previous activity, which is almost always
-                // the case but we really shouldn't count on.
-                if (replyChainEnd < 0) {
-                    replyChainEnd = i;
-                }
-            } else if (topTaskIsHigher
-                    && allowTaskReparenting
-                    && taskAffinity != null
-                    && taskAffinity.equals(target.taskAffinity)) {
-                // This activity has an affinity for our task. Either remove it if we are
-                // clearing or move it over to our task.  Note that
-                // we currently punt on the case where we are resetting a
-                // task that is not at the top but who has activities above
-                // with an affinity to it...  this is really not a normal
-                // case, and we will need to later pull that task to the front
-                // and usually at that point we will do the reset and pick
-                // up those remaining activities.  (This only happens if
-                // someone starts an activity in a new task from an activity
-                // in a task that is not currently on top.)
-                if (forceReset || finishOnTaskLaunch) {
-                    final int start = replyChainEnd >= 0 ? replyChainEnd : i;
-                    if (DEBUG_TASKS) Slog.v(TAG_TASKS,
-                            "Finishing task at index " + start + " to " + i);
-                    for (int srcPos = start; srcPos >= i; --srcPos) {
-                        final ActivityRecord p = task.getChildAt(srcPos);
-                        if (p.finishing) {
-                            continue;
-                        }
-                        p.finishIfPossible("move-affinity", false /* oomAdj */);
-                    }
-                } else {
-                    if (taskInsertionPoint < 0) {
-                        taskInsertionPoint = task.getChildCount();
-
-                    }
-
-                    final int start = replyChainEnd >= 0 ? replyChainEnd : i;
-                    if (DEBUG_TASKS) Slog.v(TAG_TASKS,
-                            "Reparenting from task=" + affinityTask + ":" + start + "-" + i
-                            + " to task=" + task + ":" + taskInsertionPoint);
-                    for (int srcPos = start; srcPos >= i; --srcPos) {
-                        final ActivityRecord p = task.getChildAt(srcPos);
-                        p.reparent(task, taskInsertionPoint, "resetAffinityTaskIfNeededLocked");
-
-                        if (DEBUG_ADD_REMOVE) Slog.i(TAG_ADD_REMOVE,
-                                "Removing and adding activity " + p + " to stack at " + task
-                                + " callers=" + Debug.getCallers(3));
-                        if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Pulling activity " + p
-                                + " from " + srcPos + " in to resetting task " + task);
-                    }
-                    positionChildAtTop(task);
-
-                    // Now we've moved it in to place...  but what if this is
-                    // a singleTop activity and we have put it on top of another
-                    // instance of the same activity?  Then we drop the instance
-                    // below so it remains singleTop.
-                    if (target.info.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP) {
-                        final ArrayList<ActivityRecord> taskActivities = task.mChildren;
-                        final int targetNdx = taskActivities.indexOf(target);
-                        if (targetNdx > 0) {
-                            final ActivityRecord p = taskActivities.get(targetNdx - 1);
-                            if (p.intent.getComponent().equals(target.intent.getComponent())) {
-                                p.finishIfPossible("replace", false /* oomAdj */);
-                            }
-                        }
-                    }
-                }
-
-                replyChainEnd = -1;
-            }
-        }
-        return taskInsertionPoint;
-    }
-
-    /**
      * Reset the task by reparenting the activities that have same affinity to the task or
      * reparenting the activities that have different affinityies out of the task, while these
      * activities allow task reparenting.
@@ -3352,37 +2935,16 @@
      * @return The non-finishing top activity of the task after reset or the original task top
      *         activity if all activities within the task are finishing.
      */
-    final ActivityRecord resetTaskIfNeededLocked(ActivityRecord taskTop,
-            ActivityRecord newActivity) {
+    ActivityRecord resetTaskIfNeeded(ActivityRecord taskTop, ActivityRecord newActivity) {
         final boolean forceReset =
                 (newActivity.info.flags & ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0;
         final Task task = taskTop.getTask();
 
-        // False until we evaluate the Task associated with taskTop. Switches to true
-        // for remaining tasks. Used for later tasks to reparent to task.
-        boolean taskFound = false;
-
         // If ActivityOptions are moved out and need to be aborted or moved to taskTop.
-        ActivityOptions topOptions = null;
+        final ActivityOptions topOptions = sResetTargetTaskHelper.process(this, task, forceReset);
 
-        // Preserve the location for reparenting in the new task.
-        int reparentInsertionPoint = -1;
-
-        for (int i = getChildCount() - 1; i >= 0; --i) {
-            final Task targetTask = getChildAt(i);
-
-            if (targetTask == task) {
-                topOptions = resetTargetTaskIfNeededLocked(task, forceReset);
-                taskFound = true;
-            } else {
-                reparentInsertionPoint = resetAffinityTaskIfNeededLocked(targetTask, task,
-                        taskFound, forceReset, reparentInsertionPoint);
-            }
-        }
-
-        int taskNdx = mChildren.indexOf(task);
-        if (taskNdx >= 0) {
-            ActivityRecord newTop = getChildAt(taskNdx).getTopNonFinishingActivity();
+        if (mChildren.contains(task)) {
+            final ActivityRecord newTop = task.getTopNonFinishingActivity();
             if (newTop != null) {
                 taskTop = newTop;
             }
@@ -3391,11 +2953,7 @@
         if (topOptions != null) {
             // If we got some ActivityOptions from an activity on top that
             // was removed from the task, propagate them to the new real top.
-            if (taskTop != null) {
-                taskTop.updateOptionsLocked(topOptions);
-            } else {
-                topOptions.abort();
-            }
+            taskTop.updateOptionsLocked(topOptions);
         }
 
         return taskTop;
@@ -4697,7 +4255,7 @@
 
         // The task might have already been running and its visibility needs to be synchronized with
         // the visibility of the stack / windows.
-        ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
+        ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
         mRootActivityContainer.resumeFocusedStacksTopActivities();
     }
 
@@ -5219,7 +4777,7 @@
         displayContent.layoutAndAssignWindowLayersIfNeeded();
     }
 
-    private void positionChildAtBottom(Task child) {
+    void positionChildAtBottom(Task child) {
         // If there are other focusable stacks on the display, the z-order of the display should not
         // be changed just because a task was placed at the bottom. E.g. if it is moving the topmost
         // task to bottom, the next focusable stack on the same display should be focused.
diff --git a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
index 6ea80d2..304f230 100644
--- a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
@@ -975,7 +975,7 @@
         }
     }
 
-    void startSpecificActivityLocked(ActivityRecord r, boolean andResume, boolean checkConfig) {
+    void startSpecificActivity(ActivityRecord r, boolean andResume, boolean checkConfig) {
         // Is this activity's application already running?
         final WindowProcessController wpc =
                 mService.getProcessController(r.processName, r.info.applicationInfo.uid);
@@ -1742,12 +1742,12 @@
              * to the fullscreen stack.  This is to guarantee that when we are removing a stack,
              * that the client receives onStop() before it is reparented.  We do this by detaching
              * the stack from the display so that it will be considered invisible when
-             * ensureActivitiesVisibleLocked() is called, and all of its activitys will be marked
+             * ensureActivitiesVisible() is called, and all of its activitys will be marked
              * invisible as well and added to the stopping list.  After which we process the
              * stopping list by handling the idle.
              */
             stack.mForceHidden = true;
-            stack.ensureActivitiesVisibleLocked(null, 0, PRESERVE_WINDOWS);
+            stack.ensureActivitiesVisible(null, 0, PRESERVE_WINDOWS);
             stack.mForceHidden = false;
             activityIdleInternalLocked(null, false /* fromTimeout */,
                     true /* processPausingActivites */, null /* configuration */);
@@ -2072,7 +2072,7 @@
 
         mRecentTasks.add(task);
         mService.getTaskChangeNotificationController().notifyTaskStackChanged();
-        stack.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
+        stack.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
 
         // When launching tasks behind, update the last active time of the top task after the new
         // task has been shown briefly
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index be7f887..8455c6d 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -1574,7 +1574,7 @@
                 // Also, we don't want to resume activities in a task that currently has an overlay
                 // as the starting activity just needs to be in the visible paused state until the
                 // over is removed.
-                mTargetStack.ensureActivitiesVisibleLocked(mStartActivity, 0, !PRESERVE_WINDOWS);
+                mTargetStack.ensureActivitiesVisible(mStartActivity, 0, !PRESERVE_WINDOWS);
                 // Go ahead and tell window manager to execute app transition for this activity
                 // since the app transition will not be triggered through the resume channel.
                 mTargetStack.getDisplay().mDisplayContent.executeAppTransition();
@@ -1812,7 +1812,7 @@
         final boolean resetTask =
                 reusedActivity != null && (mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0;
         if (resetTask) {
-            targetTaskTop = mTargetStack.resetTaskIfNeededLocked(targetTaskTop, mStartActivity);
+            targetTaskTop = mTargetStack.resetTaskIfNeeded(targetTaskTop, mStartActivity);
         }
 
         if ((mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
diff --git a/services/core/java/com/android/server/wm/AppTransitionController.java b/services/core/java/com/android/server/wm/AppTransitionController.java
index bef6af3..ff1b423 100644
--- a/services/core/java/com/android/server/wm/AppTransitionController.java
+++ b/services/core/java/com/android/server/wm/AppTransitionController.java
@@ -688,15 +688,16 @@
      * compare z-order.
      *
      * @param apps The list of apps to search.
-     * @param ignoreHidden If set to true, ignores apps that are {@link ActivityRecord#isHidden}.
+     * @param ignoreInvisible If set to true, ignores apps that are not
+     *                        {@link ActivityRecord#isVisible}.
      * @return The top {@link ActivityRecord}.
      */
-    private ActivityRecord getTopApp(ArraySet<ActivityRecord> apps, boolean ignoreHidden) {
+    private ActivityRecord getTopApp(ArraySet<ActivityRecord> apps, boolean ignoreInvisible) {
         int topPrefixOrderIndex = Integer.MIN_VALUE;
         ActivityRecord topApp = null;
         for (int i = apps.size() - 1; i >= 0; i--) {
             final ActivityRecord app = apps.valueAt(i);
-            if (ignoreHidden && app.isHidden()) {
+            if (ignoreInvisible && !app.isVisible()) {
                 continue;
             }
             final int prefixOrderIndex = app.getPrefixOrderIndex();
diff --git a/services/core/java/com/android/server/wm/BlackFrame.java b/services/core/java/com/android/server/wm/BlackFrame.java
index b4cecff..8ab1795 100644
--- a/services/core/java/com/android/server/wm/BlackFrame.java
+++ b/services/core/java/com/android/server/wm/BlackFrame.java
@@ -52,7 +52,6 @@
                     .setParent(surfaceControl)
                     .build();
             transaction.setWindowCrop(surface, w, h);
-            transaction.setLayerStack(surface, dc.getDisplayId());
             transaction.setAlpha(surface, 1);
             transaction.setLayer(surface, layer);
             transaction.setPosition(surface, left, top);
diff --git a/services/core/java/com/android/server/wm/CompatModePackages.java b/services/core/java/com/android/server/wm/CompatModePackages.java
index 104805f..320ca65 100644
--- a/services/core/java/com/android/server/wm/CompatModePackages.java
+++ b/services/core/java/com/android/server/wm/CompatModePackages.java
@@ -346,7 +346,7 @@
                         false /* preserveWindow */);
                 // And we need to make sure at this point that all other activities
                 // are made visible with the correct configuration.
-                stack.ensureActivitiesVisibleLocked(starting, 0, !PRESERVE_WINDOWS);
+                stack.ensureActivitiesVisible(starting, 0, !PRESERVE_WINDOWS);
             }
         }
     }
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 456f650..283b92c 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -644,11 +644,11 @@
                     + " config reported=" + w.isLastConfigReportedToClient());
             final ActivityRecord activity = w.mActivityRecord;
             if (gone) Slog.v(TAG, "  GONE: mViewVisibility=" + w.mViewVisibility
-                    + " mRelayoutCalled=" + w.mRelayoutCalled + " hidden=" + w.mToken.isHidden()
+                    + " mRelayoutCalled=" + w.mRelayoutCalled + " visible=" + w.mToken.isVisible()
                     + " visibleRequested=" + (activity != null && activity.mVisibleRequested)
                     + " parentHidden=" + w.isParentWindowHidden());
             else Slog.v(TAG, "  VIS: mViewVisibility=" + w.mViewVisibility
-                    + " mRelayoutCalled=" + w.mRelayoutCalled + " hidden=" + w.mToken.isHidden()
+                    + " mRelayoutCalled=" + w.mRelayoutCalled + " visible=" + w.mToken.isVisible()
                     + " visibleRequested=" + (activity != null && activity.mVisibleRequested)
                     + " parentHidden=" + w.isParentWindowHidden());
         }
@@ -3053,7 +3053,7 @@
                 wsa.destroySurface();
                 mWmService.mForceRemoves.add(w);
                 mTmpWindow = w;
-            } else if (w.mActivityRecord != null && w.mActivityRecord.isClientHidden()) {
+            } else if (w.mActivityRecord != null && !w.mActivityRecord.isClientVisible()) {
                 Slog.w(TAG_WM, "LEAKED SURFACE (app token hidden): "
                         + w + " surface=" + wsa.mSurfaceController
                         + " token=" + w.mActivityRecord);
@@ -4512,6 +4512,12 @@
             mName = name;
         }
 
+        @Override
+        boolean hasActivity() {
+            // I am a non-app-window-container :P
+            return false;
+        }
+
         void addChild(WindowToken token) {
             addChild(token, mWindowComparator);
         }
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index 8d5f90d..77e557b 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -3126,12 +3126,13 @@
                 : new AppearanceRegion[]{
                         new AppearanceRegion(fullscreenAppearance, fullscreenStackBounds)};
         final boolean isNavbarColorManagedByIme = result.second;
+        String cause = win.toString();
         mHandler.post(() -> {
             StatusBarManagerInternal statusBar = getStatusBarManagerInternal();
             if (statusBar != null) {
                 final int displayId = getDisplayId();
                 statusBar.setDisableFlags(displayId, visibility & StatusBarManager.DISABLE_MASK,
-                        win.toString());
+                        cause);
                 if (transientState.first.length > 0) {
                     statusBar.showTransient(displayId, transientState.first);
                 }
@@ -3143,8 +3144,10 @@
                 statusBar.topAppWindowChanged(displayId, isFullscreen, isImmersive);
 
                 // TODO(b/118118435): Remove this after removing system UI visibilities.
-                mDisplayContent.statusBarVisibilityChanged(
-                        visibility & ~(View.STATUS_BAR_UNHIDE | View.NAVIGATION_BAR_UNHIDE));
+                synchronized (mLock) {
+                    mDisplayContent.statusBarVisibilityChanged(
+                            visibility & ~(View.STATUS_BAR_UNHIDE | View.NAVIGATION_BAR_UNHIDE));
+                }
             }
         });
         return diff;
diff --git a/services/core/java/com/android/server/wm/DisplayWindowListenerController.java b/services/core/java/com/android/server/wm/DisplayWindowListenerController.java
index dbc452f..2da76ea 100644
--- a/services/core/java/com/android/server/wm/DisplayWindowListenerController.java
+++ b/services/core/java/com/android/server/wm/DisplayWindowListenerController.java
@@ -16,6 +16,7 @@
 
 package com.android.server.wm;
 
+import android.content.res.Configuration;
 import android.os.RemoteCallbackList;
 import android.os.RemoteException;
 import android.view.IDisplayWindowListener;
@@ -62,6 +63,28 @@
         mDisplayListeners.finishBroadcast();
     }
 
+    void dispatchDisplayChanged(ActivityDisplay display, Configuration newConfig) {
+        // Only report changed if this has actually been added to the hierarchy already.
+        boolean isInHierarchy = false;
+        for (int i = 0; i < display.getParent().getChildCount(); ++i) {
+            if (display.getParent().getChildAt(i) == display) {
+                isInHierarchy = true;
+            }
+        }
+        if (!isInHierarchy) {
+            return;
+        }
+        int count = mDisplayListeners.beginBroadcast();
+        for (int i = 0; i < count; ++i) {
+            try {
+                mDisplayListeners.getBroadcastItem(i).onDisplayConfigurationChanged(
+                        display.mDisplayId, newConfig);
+            } catch (RemoteException e) {
+            }
+        }
+        mDisplayListeners.finishBroadcast();
+    }
+
     void dispatchDisplayRemoved(ActivityDisplay display) {
         int count = mDisplayListeners.beginBroadcast();
         for (int i = 0; i < count; ++i) {
diff --git a/services/core/java/com/android/server/wm/EnsureActivitiesVisibleHelper.java b/services/core/java/com/android/server/wm/EnsureActivitiesVisibleHelper.java
new file mode 100644
index 0000000..3aae1b1
--- /dev/null
+++ b/services/core/java/com/android/server/wm/EnsureActivitiesVisibleHelper.java
@@ -0,0 +1,196 @@
+/*
+ * 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.wm;
+
+import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
+
+import static com.android.server.wm.ActivityStack.TAG_VISIBILITY;
+import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_VISIBILITY;
+
+import android.util.Slog;
+
+import com.android.internal.util.function.pooled.PooledConsumer;
+import com.android.internal.util.function.pooled.PooledLambda;
+
+/** Helper class to ensure activities are in the right visible state for a container. */
+class EnsureActivitiesVisibleHelper {
+    private final ActivityStack mContiner;
+    private ActivityRecord mTop;
+    private ActivityRecord mStarting;
+    private boolean mAboveTop;
+    private boolean mContainerShouldBeVisible;
+    private boolean mBehindFullscreenActivity;
+    private int mConfigChanges;
+    private boolean mPreserveWindows;
+    private boolean mNotifyClients;
+
+    EnsureActivitiesVisibleHelper(ActivityStack container) {
+        mContiner = container;
+    }
+
+    void reset(ActivityRecord starting, int configChanges, boolean preserveWindows,
+            boolean notifyClients) {
+        mStarting = starting;
+        mTop = mContiner.topRunningActivityLocked();
+        // If the top activity is not fullscreen, then we need to make sure any activities under it
+        // are now visible.
+        mAboveTop = mTop != null;
+        mContainerShouldBeVisible = mContiner.shouldBeVisible(mStarting);
+        mBehindFullscreenActivity = !mContainerShouldBeVisible;
+        mConfigChanges = configChanges;
+        mPreserveWindows = preserveWindows;
+        mNotifyClients = notifyClients;
+    }
+
+    /**
+     * Ensure visibility with an option to also update the configuration of visible activities.
+     * @see ActivityStack#ensureActivitiesVisible(ActivityRecord, int, boolean)
+     * @see RootActivityContainer#ensureActivitiesVisible(ActivityRecord, int, boolean)
+     */
+    void process(ActivityRecord starting, int configChanges, boolean preserveWindows,
+            boolean notifyClients) {
+        reset(starting, configChanges, preserveWindows, notifyClients);
+
+        if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "ensureActivitiesVisible behind " + mTop
+                + " configChanges=0x" + Integer.toHexString(configChanges));
+        if (mTop != null) {
+            mContiner.checkTranslucentActivityWaiting(mTop);
+        }
+
+        // We should not resume activities that being launched behind because these
+        // activities are actually behind other fullscreen activities, but still required
+        // to be visible (such as performing Recents animation).
+        final boolean resumeTopActivity = mTop != null && !mTop.mLaunchTaskBehind
+                && mContiner.isFocusable() && mContiner.isInStackLocked(starting) == null;
+
+        final PooledConsumer f = PooledLambda.obtainConsumer(
+                EnsureActivitiesVisibleHelper::setActivityVisibilityState, this,
+                PooledLambda.__(ActivityRecord.class), resumeTopActivity);
+        mContiner.forAllActivities(f);
+        f.recycle();
+    }
+
+    private void setActivityVisibilityState(ActivityRecord r, final boolean resumeTopActivity) {
+        final boolean isTop = r == mTop;
+        if (mAboveTop && !isTop) {
+            return;
+        }
+        mAboveTop = false;
+
+        final boolean reallyVisible = r.shouldBeVisible(
+                mBehindFullscreenActivity, false /* ignoringKeyguard */);
+
+        // Check whether activity should be visible without Keyguard influence
+        if (r.visibleIgnoringKeyguard) {
+            if (r.occludesParent()) {
+                // At this point, nothing else needs to be shown in this task.
+                if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Fullscreen: at " + r
+                        + " stackVisible=" + mContainerShouldBeVisible
+                        + " behindFullscreen=" + mBehindFullscreenActivity);
+                mBehindFullscreenActivity = true;
+            } else {
+                mBehindFullscreenActivity = false;
+            }
+        }
+
+        if (reallyVisible) {
+            if (r.finishing) {
+                return;
+            }
+            if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Make visible? " + r
+                    + " finishing=" + r.finishing + " state=" + r.getState());
+            // First: if this is not the current activity being started, make
+            // sure it matches the current configuration.
+            if (r != mStarting && mNotifyClients) {
+                r.ensureActivityConfiguration(0 /* globalChanges */, mPreserveWindows,
+                        true /* ignoreVisibility */);
+            }
+
+            if (!r.attachedToProcess()) {
+                makeVisibleAndRestartIfNeeded(mStarting, mConfigChanges, isTop,
+                        resumeTopActivity && isTop, r);
+            } else if (r.mVisibleRequested) {
+                // If this activity is already visible, then there is nothing to do here.
+                if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY,
+                        "Skipping: already visible at " + r);
+
+                if (r.mClientVisibilityDeferred && mNotifyClients) {
+                    r.makeClientVisible();
+                }
+
+                r.handleAlreadyVisible();
+                if (mNotifyClients) {
+                    r.makeActiveIfNeeded(mStarting);
+                }
+            } else {
+                r.makeVisibleIfNeeded(mStarting, mNotifyClients);
+            }
+            // Aggregate current change flags.
+            mConfigChanges |= r.configChangeFlags;
+        } else {
+            if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Make invisible? " + r
+                    + " finishing=" + r.finishing + " state=" + r.getState()
+                    + " stackShouldBeVisible=" + mContainerShouldBeVisible
+                    + " behindFullscreenActivity=" + mBehindFullscreenActivity
+                    + " mLaunchTaskBehind=" + r.mLaunchTaskBehind);
+            r.makeInvisible();
+        }
+
+        final int windowingMode = mContiner.getWindowingMode();
+        if (windowingMode == WINDOWING_MODE_FREEFORM) {
+            // The visibility of tasks and the activities they contain in freeform stack are
+            // determined individually unlike other stacks where the visibility or fullscreen
+            // status of an activity in a previous task affects other.
+            mBehindFullscreenActivity = !mContainerShouldBeVisible;
+        } else if (mContiner.isActivityTypeHome()) {
+            if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Home task: at " + mContiner
+                    + " stackShouldBeVisible=" + mContainerShouldBeVisible
+                    + " behindFullscreenActivity=" + mBehindFullscreenActivity);
+            // No other task in the home stack should be visible behind the home activity.
+            // Home activities is usually a translucent activity with the wallpaper behind
+            // them. However, when they don't have the wallpaper behind them, we want to
+            // show activities in the next application stack behind them vs. another
+            // task in the home stack like recents.
+            mBehindFullscreenActivity = true;
+        }
+    }
+
+    private void makeVisibleAndRestartIfNeeded(ActivityRecord starting, int configChanges,
+            boolean isTop, boolean andResume, ActivityRecord r) {
+        // We need to make sure the app is running if it's the top, or it is just made visible from
+        // invisible. If the app is already visible, it must have died while it was visible. In this
+        // case, we'll show the dead window but will not restart the app. Otherwise we could end up
+        // thrashing.
+        if (!isTop && r.mVisibleRequested) {
+            return;
+        }
+
+        // This activity needs to be visible, but isn't even running...
+        // get it started and resume if no other stack in this stack is resumed.
+        if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Start and freeze screen for " + r);
+        if (r != starting) {
+            r.startFreezingScreenLocked(configChanges);
+        }
+        if (!r.mVisibleRequested || r.mLaunchTaskBehind) {
+            if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Starting and making visible: " + r);
+            r.setVisibility(true);
+        }
+        if (r != starting) {
+            mContiner.mStackSupervisor.startSpecificActivity(r, andResume, true /* checkConfig */);
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/wm/HighRefreshRateBlacklist.java b/services/core/java/com/android/server/wm/HighRefreshRateBlacklist.java
index 29b6bc4..d9cf637 100644
--- a/services/core/java/com/android/server/wm/HighRefreshRateBlacklist.java
+++ b/services/core/java/com/android/server/wm/HighRefreshRateBlacklist.java
@@ -105,8 +105,10 @@
 
     private class OnPropertiesChangedListener implements DeviceConfig.OnPropertiesChangedListener {
         public void onPropertiesChanged(@NonNull DeviceConfig.Properties properties) {
-            updateBlacklist(
-                    properties.getString(KEY_HIGH_REFRESH_RATE_BLACKLIST, null /*default*/));
+            if (properties.getKeyset().contains(KEY_HIGH_REFRESH_RATE_BLACKLIST)) {
+                updateBlacklist(
+                        properties.getString(KEY_HIGH_REFRESH_RATE_BLACKLIST, null /*default*/));
+            }
         }
     }
 }
diff --git a/services/core/java/com/android/server/wm/RecentsAnimation.java b/services/core/java/com/android/server/wm/RecentsAnimation.java
index a17bd24..824a3c8 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimation.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimation.java
@@ -134,7 +134,7 @@
 
         if (!targetActivity.attachedToProcess()) {
             ProtoLog.d(WM_DEBUG_RECENTS_ANIMATIONS, "Real start recents");
-            mStackSupervisor.startSpecificActivityLocked(targetActivity, false /* andResume */,
+            mStackSupervisor.startSpecificActivity(targetActivity, false /* andResume */,
                     false /* checkConfig */);
             // Make sure the activity won't be involved in transition.
             if (targetActivity.getDisplayContent() != null) {
@@ -368,7 +368,7 @@
                         // transition (the target activity will be one of closing apps).
                         if (!controller.shouldDeferCancelWithScreenshot()
                                 && !targetStack.isFocusedStackOnDisplay()) {
-                            targetStack.ensureActivitiesVisibleLocked(null /* starting */,
+                            targetStack.ensureActivitiesVisible(null /* starting */,
                                     0 /* starting */, false /* preserveWindows */);
                         }
                         // Keep target stack in place, nothing changes, so ignore the transition
diff --git a/services/core/java/com/android/server/wm/ResetTargetTaskHelper.java b/services/core/java/com/android/server/wm/ResetTargetTaskHelper.java
new file mode 100644
index 0000000..413dfd5
--- /dev/null
+++ b/services/core/java/com/android/server/wm/ResetTargetTaskHelper.java
@@ -0,0 +1,295 @@
+/*
+ * 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.wm;
+
+import static com.android.server.wm.ActivityStack.TAG_ADD_REMOVE;
+import static com.android.server.wm.ActivityStack.TAG_TASKS;
+import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_ADD_REMOVE;
+import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_TASKS;
+import static com.android.server.wm.Task.REPARENT_LEAVE_STACK_IN_PLACE;
+
+import android.app.ActivityOptions;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.os.Debug;
+import android.util.Slog;
+
+import com.android.internal.util.function.pooled.PooledConsumer;
+import com.android.internal.util.function.pooled.PooledFunction;
+import com.android.internal.util.function.pooled.PooledLambda;
+
+import java.util.ArrayList;
+
+/** Helper class for processing the reset of a task. */
+class ResetTargetTaskHelper {
+    private Task mTask;
+    private ActivityStack mParent;
+    private Task mTargetTask;
+    private ActivityRecord mRoot;
+    private boolean mForceReset;
+    private boolean mCanMoveOptions;
+    private boolean mTargetTaskFound;
+    private int mActivityReparentPosition;
+    private ActivityOptions mTopOptions;
+    private ArrayList<ActivityRecord> mResultActivities = new ArrayList<>();
+    private ArrayList<ActivityRecord> mAllActivities = new ArrayList<>();
+    private ArrayList<Task> mCreatedTasks = new ArrayList<>();
+
+    private void reset(Task task) {
+        mTask = task;
+        mRoot = null;
+        mCanMoveOptions = true;
+        mTopOptions = null;
+        mResultActivities.clear();
+        mAllActivities.clear();
+        mCreatedTasks.clear();
+    }
+
+    ActivityOptions process(ActivityStack parent, Task targetTask, boolean forceReset) {
+        mParent = parent;
+        mForceReset = forceReset;
+        mTargetTask = targetTask;
+        mTargetTaskFound = false;
+        mActivityReparentPosition = -1;
+
+        final PooledConsumer c = PooledLambda.obtainConsumer(
+                ResetTargetTaskHelper::processTask, this, PooledLambda.__(Task.class));
+        parent.forAllTasks(c);
+        c.recycle();
+
+        reset(null);
+        mParent = null;
+        return mTopOptions;
+    }
+
+    private void processTask(Task task) {
+        reset(task);
+        mRoot = task.getRootActivity(true);
+        if (mRoot == null) return;
+
+        final boolean isTargetTask = task == mTargetTask;
+        if (isTargetTask) mTargetTaskFound = true;
+
+        final PooledFunction f = PooledLambda.obtainFunction(
+                ResetTargetTaskHelper::processActivity, this,
+                PooledLambda.__(ActivityRecord.class), isTargetTask);
+        task.forAllActivities(f);
+        f.recycle();
+
+        processCreatedTasks();
+    }
+
+    private boolean processActivity(ActivityRecord r, boolean isTargetTask) {
+        // End processing if we have reached the root.
+        if (r == mRoot) return true;
+
+        mAllActivities.add(r);
+        final int flags = r.info.flags;
+        final boolean finishOnTaskLaunch =
+                (flags & ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH) != 0;
+        final boolean allowTaskReparenting =
+                (flags & ActivityInfo.FLAG_ALLOW_TASK_REPARENTING) != 0;
+        final boolean clearWhenTaskReset =
+                (r.intent.getFlags() & Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0;
+
+        if (isTargetTask) {
+            if (!finishOnTaskLaunch && !clearWhenTaskReset) {
+                if (r.resultTo != null) {
+                    // If this activity is sending a reply to a previous activity, we can't do
+                    // anything with it now until we reach the start of the reply chain.
+                    // NOTE: that we are assuming the result is always to the previous activity,
+                    // which is almost always the case but we really shouldn't count on.
+                    mResultActivities.add(r);
+                    return false;
+                }
+                if (allowTaskReparenting && r.taskAffinity != null
+                        && !r.taskAffinity.equals(mTask.affinity)) {
+                    // If this activity has an affinity for another task, then we need to move
+                    // it out of here. We will move it as far out of the way as possible, to the
+                    // bottom of the activity stack. This also keeps it correctly ordered with
+                    // any activities we previously moved.
+                    // TODO: We should probably look for other stacks also, since corresponding
+                    //  task with the same affinity is unlikely to be in the same stack.
+                    final Task targetTask;
+                    final ActivityRecord bottom = mParent.getActivity(
+                            (ar) -> true, false /*traverseTopToBottom*/);
+
+                    if (bottom != null && r.taskAffinity.equals(bottom.getTask().affinity)) {
+                        // If the activity currently at the bottom has the same task affinity as
+                        // the one we are moving, then merge it into the same task.
+                        targetTask = bottom.getTask();
+                        if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Start pushing activity "
+                                + r + " out to bottom task " + targetTask);
+                    } else {
+                        targetTask = mParent.createTask(
+                                mParent.mStackSupervisor.getNextTaskIdForUserLocked(r.mUserId),
+                                r.info, null /* intent */, null /* voiceSession */,
+                                null /* voiceInteractor */, false /* toTop */);
+                        targetTask.affinityIntent = r.intent;
+                        mCreatedTasks.add(targetTask);
+                        if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Start pushing activity "
+                                + r + " out to new task " + targetTask);
+                    }
+
+                    mResultActivities.add(r);
+                    processResultActivities(r, targetTask, 0 /*bottom*/, true, true);
+                    mParent.positionChildAtBottom(targetTask);
+                    mParent.mStackSupervisor.mRecentTasks.add(targetTask);
+                    return false;
+                }
+            }
+            if (mForceReset || finishOnTaskLaunch || clearWhenTaskReset) {
+                // If the activity should just be removed either because it asks for it, or the
+                // task should be cleared, then finish it and anything that is part of its reply
+                // chain.
+                if (clearWhenTaskReset) {
+                    // In this case, we want to finish this activity and everything above it,
+                    // so be sneaky and pretend like these are all in the reply chain.
+                    finishActivities(mAllActivities, "clearWhenTaskReset");
+                } else {
+                    mResultActivities.add(r);
+                    finishActivities(mResultActivities, "reset-task");
+                }
+
+                mResultActivities.clear();
+                return false;
+            } else {
+                // If we were in the middle of a chain, well the activity that started it all
+                // doesn't want anything special, so leave it all as-is.
+                mResultActivities.clear();
+            }
+
+            return false;
+
+        } else {
+            mResultActivities.add(r);
+            if (r.resultTo != null) {
+                // If this activity is sending a reply to a previous activity, we can't do
+                // anything with it now until we reach the start of the reply chain.
+                // NOTE: that we are assuming the result is always to the previous activity,
+                // which is almost always the case but we really shouldn't count on.
+                return false;
+            } else if (mTargetTaskFound && allowTaskReparenting && mTargetTask.affinity != null
+                    && mTargetTask.affinity.equals(r.taskAffinity)) {
+                // This activity has an affinity for our task. Either remove it if we are
+                // clearing or move it over to our task. Note that we currently punt on the case
+                // where we are resetting a task that is not at the top but who has activities
+                // above with an affinity to it... this is really not a normal case, and we will
+                // need to later pull that task to the front and usually at that point we will
+                // do the reset and pick up those remaining activities. (This only happens if
+                // someone starts an activity in a new task from an activity in a task that is
+                // not currently on top.)
+                if (mForceReset || finishOnTaskLaunch) {
+                    finishActivities(mResultActivities, "move-affinity");
+                    return false;
+                }
+                if (mActivityReparentPosition == -1) {
+                    mActivityReparentPosition = mTargetTask.getChildCount();
+                }
+
+                processResultActivities(
+                        r, mTargetTask, mActivityReparentPosition, false, false);
+
+                mParent.positionChildAtTop(mTargetTask);
+
+                // Now we've moved it in to place...but what if this is a singleTop activity and
+                // we have put it on top of another instance of the same activity? Then we drop
+                // the instance below so it remains singleTop.
+                if (r.info.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP) {
+                    final ArrayList<ActivityRecord> taskActivities = mTargetTask.mChildren;
+                    final int targetNdx = taskActivities.indexOf(r);
+                    if (targetNdx > 0) {
+                        final ActivityRecord p = taskActivities.get(targetNdx - 1);
+                        if (p.intent.getComponent().equals(r.intent.getComponent())) {
+                            p.finishIfPossible("replace", false /* oomAdj */);
+                        }
+                    }
+                }
+            }
+            return false;
+        }
+    }
+
+    private void finishActivities(ArrayList<ActivityRecord> activities, String reason) {
+        boolean noOptions = mCanMoveOptions;
+
+        while (!activities.isEmpty()) {
+            final ActivityRecord p = activities.remove(0);
+            if (p.finishing) continue;
+
+            noOptions = takeOption(p, noOptions);
+
+            if (DEBUG_TASKS) Slog.w(TAG_TASKS,
+                    "resetTaskIntendedTask: calling finishActivity on " + p);
+            p.finishIfPossible(reason, false /* oomAdj */);
+        }
+    }
+
+    private void processResultActivities(ActivityRecord target, Task targetTask, int position,
+            boolean ignoreFinishing, boolean takeOptions) {
+        boolean noOptions = mCanMoveOptions;
+
+        while (!mResultActivities.isEmpty()) {
+            final ActivityRecord p = mResultActivities.remove(0);
+            if (ignoreFinishing&& p.finishing) continue;
+
+            if (takeOptions) {
+                noOptions = takeOption(p, noOptions);
+            }
+            if (DEBUG_ADD_REMOVE) Slog.i(TAG_ADD_REMOVE, "Removing activity " + p + " from task="
+                    + mTask + " adding to task=" + targetTask + " Callers=" + Debug.getCallers(4));
+            if (DEBUG_TASKS) Slog.v(TAG_TASKS,
+                    "Pushing next activity " + p + " out to target's task " + target);
+            p.reparent(targetTask, position, "resetTargetTaskIfNeeded");
+        }
+    }
+
+    private void processCreatedTasks() {
+        if (mCreatedTasks.isEmpty()) return;
+
+        ActivityDisplay display = mParent.getDisplay();
+        final boolean singleTaskInstanceDisplay = display.isSingleTaskInstance();
+        if (singleTaskInstanceDisplay) {
+            display = mParent.mRootActivityContainer.getDefaultDisplay();
+        }
+
+        final int windowingMode = mParent.getWindowingMode();
+        final int activityType = mParent.getActivityType();
+        if (!singleTaskInstanceDisplay && !display.alwaysCreateStack(windowingMode, activityType)) {
+            return;
+        }
+
+        while (!mCreatedTasks.isEmpty()) {
+            final Task targetTask = mCreatedTasks.remove(mCreatedTasks.size() - 1);
+            final ActivityStack targetStack = display.getOrCreateStack(
+                    windowingMode, activityType, false /* onTop */);
+            targetTask.reparent(targetStack, false /* toTop */, REPARENT_LEAVE_STACK_IN_PLACE,
+                    false /* animate */, true /* deferResume */, "resetTargetTask");
+        }
+    }
+
+    private boolean takeOption(ActivityRecord p, boolean noOptions) {
+        mCanMoveOptions = false;
+        if (noOptions && mTopOptions == null) {
+            mTopOptions = p.takeOptionsLocked(false /* fromClient */);
+            if (mTopOptions != null) {
+                noOptions = false;
+            }
+        }
+        return noOptions;
+    }
+}
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 6ddd943..28c5575 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -1067,12 +1067,30 @@
 
     /** Returns the first non-finishing activity from the bottom. */
     ActivityRecord getRootActivity() {
-        final int rootActivityIndex = findRootIndex(false /* effectiveRoot */);
-        if (rootActivityIndex == -1) {
-            // There are no non-finishing activities in the task.
-            return null;
+        // TODO: Figure out why we historical ignore relinquish identity for this case...
+        return getRootActivity(true /*ignoreRelinquishIdentity*/, false /*setToBottomIfNone*/);
+    }
+
+    ActivityRecord getRootActivity(boolean setToBottomIfNone) {
+        return getRootActivity(false /*ignoreRelinquishIdentity*/, false /*setToBottomIfNone*/);
+    }
+
+    ActivityRecord getRootActivity(boolean ignoreRelinquishIdentity, boolean setToBottomIfNone) {
+        ActivityRecord root;
+        if (ignoreRelinquishIdentity) {
+            root = getActivity((r) -> !r.finishing, false /*traverseTopToBottom*/);
+        } else {
+            root = getActivity((r) ->
+                            !r.finishing && (r.info.flags & FLAG_RELINQUISH_TASK_IDENTITY) == 0,
+                    false /*traverseTopToBottom*/);
         }
-        return getChildAt(rootActivityIndex);
+
+        if (root == null && setToBottomIfNone) {
+            // All activities in the task are either finishing or relinquish task identity.
+            // But we still want to update the intent, so let's use the bottom activity.
+            root = getActivity((r) -> true, false /*traverseTopToBottom*/);
+        }
+        return root;
     }
 
     ActivityRecord getTopNonFinishingActivity() {
@@ -2046,17 +2064,22 @@
             // could never go away in Honeycomb.
             final int compatScreenWidthDp = (int) (mTmpNonDecorBounds.width() / density);
             final int compatScreenHeightDp = (int) (mTmpNonDecorBounds.height() / density);
-            // We're only overriding LONG, SIZE and COMPAT parts of screenLayout, so we start
-            // override calculation with partial default.
             // Reducing the screen layout starting from its parent config.
-            final int sl = parentConfig.screenLayout
-                    & (Configuration.SCREENLAYOUT_LONG_MASK | Configuration.SCREENLAYOUT_SIZE_MASK);
-            final int longSize = Math.max(compatScreenHeightDp, compatScreenWidthDp);
-            final int shortSize = Math.min(compatScreenHeightDp, compatScreenWidthDp);
-            inOutConfig.screenLayout = Configuration.reduceScreenLayout(sl, longSize, shortSize);
+            inOutConfig.screenLayout = computeScreenLayoutOverride(parentConfig.screenLayout,
+                    compatScreenWidthDp, compatScreenHeightDp);
         }
     }
 
+    /** Computes LONG, SIZE and COMPAT parts of {@link Configuration#screenLayout}. */
+    static int computeScreenLayoutOverride(int sourceScreenLayout, int screenWidthDp,
+            int screenHeightDp) {
+        sourceScreenLayout = sourceScreenLayout
+                & (Configuration.SCREENLAYOUT_LONG_MASK | Configuration.SCREENLAYOUT_SIZE_MASK);
+        final int longSize = Math.max(screenWidthDp, screenHeightDp);
+        final int shortSize = Math.min(screenWidthDp, screenHeightDp);
+        return Configuration.reduceScreenLayout(sourceScreenLayout, longSize, shortSize);
+    }
+
     @Override
     void resolveOverrideConfiguration(Configuration newParentConfig) {
         mTmpBounds.set(getResolvedOverrideConfiguration().windowConfiguration.getBounds());
@@ -2508,7 +2531,7 @@
         for (int i = mChildren.size() - 1; i >= 0; i--) {
             final ActivityRecord token = mChildren.get(i);
             // skip hidden (or about to hide) apps
-            if (token.mIsExiting || token.isClientHidden() || !token.mVisibleRequested) {
+            if (token.mIsExiting || !token.isClientVisible() || !token.mVisibleRequested) {
                 continue;
             }
             final WindowState win = token.findMainWindow();
@@ -2726,10 +2749,9 @@
 
     ActivityRecord getTopVisibleActivity() {
         for (int i = mChildren.size() - 1; i >= 0; i--) {
-            final ActivityRecord token = mChildren.get(i);
-            // skip hidden (or about to hide) apps
-            if (!token.mIsExiting && !token.isClientHidden() && token.mVisibleRequested) {
-                return token;
+            final ActivityRecord activity = mChildren.get(i);
+            if (!activity.mIsExiting && activity.isClientVisible() && activity.mVisibleRequested) {
+                return activity;
             }
         }
         return null;
diff --git a/services/core/java/com/android/server/wm/WallpaperController.java b/services/core/java/com/android/server/wm/WallpaperController.java
index ef79403..6ff4b2e 100644
--- a/services/core/java/com/android/server/wm/WallpaperController.java
+++ b/services/core/java/com/android/server/wm/WallpaperController.java
@@ -120,7 +120,7 @@
         }
 
         mFindResults.resetTopWallpaper = true;
-        if (w.mActivityRecord != null && w.mActivityRecord.isHidden()
+        if (w.mActivityRecord != null && !w.mActivityRecord.isVisible()
                 && !w.mActivityRecord.isAnimating(TRANSITION)) {
 
             // If this window's app token is hidden and not animating, it is of no interest to us.
@@ -278,9 +278,11 @@
         for (int i = mWallpaperTokens.size() - 1; i >= 0; i--) {
             final WallpaperWindowToken token = mWallpaperTokens.get(i);
             token.hideWallpaperToken(wasDeferred, "hideWallpapers");
-            if (DEBUG_WALLPAPER_LIGHT && !token.isHidden()) Slog.d(TAG, "Hiding wallpaper " + token
-                    + " from " + winGoingAway + " target=" + mWallpaperTarget + " prev="
-                    + mPrevWallpaperTarget + "\n" + Debug.getCallers(5, "  "));
+            if (DEBUG_WALLPAPER_LIGHT && token.isVisible()) {
+                Slog.d(TAG, "Hiding wallpaper " + token
+                        + " from " + winGoingAway + " target=" + mWallpaperTarget + " prev="
+                        + mPrevWallpaperTarget + "\n" + Debug.getCallers(5, "  "));
+            }
         }
     }
 
diff --git a/services/core/java/com/android/server/wm/WallpaperWindowToken.java b/services/core/java/com/android/server/wm/WallpaperWindowToken.java
index 528cece..d23bf97 100644
--- a/services/core/java/com/android/server/wm/WallpaperWindowToken.java
+++ b/services/core/java/com/android/server/wm/WallpaperWindowToken.java
@@ -56,7 +56,6 @@
             final WindowState wallpaper = mChildren.get(j);
             wallpaper.hideWallpaperWindow(wasDeferred, reason);
         }
-        setHidden(true);
     }
 
     void sendWindowWallpaperCommand(
@@ -88,9 +87,7 @@
         final int dw = displayInfo.logicalWidth;
         final int dh = displayInfo.logicalHeight;
 
-        if (isHidden() == visible) {
-            setHidden(!visible);
-
+        if (isVisible() != visible) {
             // Need to do a layout to ensure the wallpaper now has the correct size.
             mDisplayContent.setLayoutNeeded();
         }
@@ -118,10 +115,9 @@
 
     void updateWallpaperWindows(boolean visible) {
 
-        if (isHidden() == visible) {
+        if (isVisible() != visible) {
             if (DEBUG_WALLPAPER_LIGHT) Slog.d(TAG,
-                    "Wallpaper token " + token + " hidden=" + !visible);
-            setHidden(!visible);
+                    "Wallpaper token " + token + " visible=" + visible);
             // Need to do a layout to ensure the wallpaper now has the correct size.
             mDisplayContent.setLayoutNeeded();
         }
diff --git a/services/core/java/com/android/server/wm/Watermark.java b/services/core/java/com/android/server/wm/Watermark.java
index 725aaa48..4e1b217 100644
--- a/services/core/java/com/android/server/wm/Watermark.java
+++ b/services/core/java/com/android/server/wm/Watermark.java
@@ -121,8 +121,7 @@
                     .setBufferSize(1, 1)
                     .setFormat(PixelFormat.TRANSLUCENT)
                     .build();
-            t.setLayerStack(ctrl, mDisplay.getLayerStack())
-                    .setLayer(ctrl, WindowManagerService.TYPE_LAYER_MULTIPLIER * 100)
+            t.setLayer(ctrl, WindowManagerService.TYPE_LAYER_MULTIPLIER * 100)
                     .setPosition(ctrl, 0, 0)
                     .show(ctrl);
             mSurface.copyFrom(ctrl);
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index 3e78d5e..453514b2 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -79,6 +79,7 @@
 import java.util.Comparator;
 import java.util.LinkedList;
 import java.util.function.Consumer;
+import java.util.function.Function;
 import java.util.function.Predicate;
 
 /**
@@ -775,10 +776,10 @@
 
     /**
      * @return {@code true} if in this subtree of the hierarchy we have an
-     *         {@ode ActivityRecord#isAnimating(TRANSITION)}, {@code false} otherwise.
+     *         {@code ActivityRecord#isAnimating(TRANSITION)}, {@code false} otherwise.
      */
     boolean isAppTransitioning() {
-        return forAllActivities(app -> app.isAnimating(TRANSITION));
+        return getActivity(app -> app.isAnimating(TRANSITION)) != null;
     }
 
     /**
@@ -1094,7 +1095,7 @@
         wrapper.release();
     }
 
-    boolean forAllActivities(ToBooleanFunction<ActivityRecord> callback) {
+    boolean forAllActivities(Function<ActivityRecord, Boolean> callback) {
         for (int i = mChildren.size() - 1; i >= 0; --i) {
             if (mChildren.get(i).forAllActivities(callback)) {
                 return true;
@@ -1103,6 +1104,72 @@
         return false;
     }
 
+    void forAllActivities(Consumer<ActivityRecord> callback) {
+        forAllActivities(callback, true /*traverseTopToBottom*/);
+    }
+
+    void forAllActivities(Consumer<ActivityRecord> callback, boolean traverseTopToBottom) {
+        if (traverseTopToBottom) {
+            for (int i = mChildren.size() - 1; i >= 0; --i) {
+                mChildren.get(i).forAllActivities(callback, traverseTopToBottom);
+            }
+        } else {
+            final int count = mChildren.size();
+            for (int i = 0; i < count; i++) {
+                mChildren.get(i).forAllActivities(callback, traverseTopToBottom);
+            }
+        }
+    }
+
+    /** @return {@code true} if this node or any of its children contains an activity. */
+    boolean hasActivity() {
+        for (int i = mChildren.size() - 1; i >= 0; --i) {
+            if (mChildren.get(i).hasActivity()) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    ActivityRecord getActivity(Predicate<ActivityRecord> callback) {
+        return getActivity(callback, true /*traverseTopToBottom*/);
+    }
+
+    ActivityRecord getActivity(Predicate<ActivityRecord> callback, boolean traverseTopToBottom) {
+        if (traverseTopToBottom) {
+            for (int i = mChildren.size() - 1; i >= 0; --i) {
+                final ActivityRecord r = mChildren.get(i).getActivity(callback, traverseTopToBottom);
+                if (r != null) {
+                    return r;
+                }
+            }
+        } else {
+            final int count = mChildren.size();
+            for (int i = 0; i < count; i++) {
+                final ActivityRecord r = mChildren.get(i).getActivity(callback, traverseTopToBottom);
+                if (r != null) {
+                    return r;
+                }
+            }
+        }
+
+        return null;
+    }
+
+    ActivityRecord getTopActivity(boolean includeFinishing, boolean includeOverlays) {
+        // Break down into 4 calls to avoid object creation due to capturing input params.
+        if (includeFinishing) {
+            if (includeOverlays) {
+                return getActivity((r) -> true);
+            }
+            return getActivity((r) -> !r.mTaskOverlay);
+        } else if (includeOverlays) {
+            return getActivity((r) -> !r.finishing);
+        }
+
+        return getActivity((r) -> !r.finishing && !r.mTaskOverlay);
+    }
+
     void forAllWallpaperWindows(Consumer<WallpaperWindowToken> callback) {
         for (int i = mChildren.size() - 1; i >= 0; --i) {
             mChildren.get(i).forAllWallpaperWindows(callback);
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index a42f2e1..a2467e6 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -1668,7 +1668,7 @@
             if (mInTouchMode) {
                 res |= WindowManagerGlobal.ADD_FLAG_IN_TOUCH_MODE;
             }
-            if (win.mActivityRecord == null || !win.mActivityRecord.isClientHidden()) {
+            if (win.mActivityRecord == null || win.mActivityRecord.isClientVisible()) {
                 res |= WindowManagerGlobal.ADD_FLAG_APP_VISIBLE;
             }
 
@@ -2201,7 +2201,7 @@
             // associated appToken is not hidden.
             final boolean shouldRelayout = viewVisibility == View.VISIBLE &&
                     (win.mActivityRecord == null || win.mAttrs.type == TYPE_APPLICATION_STARTING
-                            || !win.mActivityRecord.isClientHidden());
+                            || win.mActivityRecord.isClientVisible());
 
             // If we are not currently running the exit animation, we need to see about starting
             // one.
diff --git a/services/core/java/com/android/server/wm/WindowManagerShellCommand.java b/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
index 2218366..5da3eb6 100644
--- a/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
+++ b/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
@@ -20,7 +20,6 @@
 
 import android.graphics.Point;
 import android.graphics.Rect;
-import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
 import android.os.ShellCommand;
 import android.os.UserHandle;
@@ -352,9 +351,7 @@
     }
 
     private int runDumpVisibleWindowViews(PrintWriter pw) {
-        ParcelFileDescriptor outFile = openFileForSystem(getNextArgRequired(), "w");
-        try (ZipOutputStream out = new ZipOutputStream(
-                new ParcelFileDescriptor.AutoCloseOutputStream(outFile))) {
+        try (ZipOutputStream out = new ZipOutputStream(getRawOutputStream())) {
             ArrayList<Pair<String, ByteTransferPipe>> requestList = new ArrayList<>();
             synchronized (mInternal.mGlobalLock) {
                 // Request dump from all windows parallelly before writing to disk.
@@ -368,7 +365,6 @@
                             requestList.add(Pair.create(w.getName(), pipe));
                         } catch (IOException | RemoteException e) {
                             // Skip this window
-                            pw.println("Error for window " + w.getName() + " : " + e.getMessage());
                             if (pipe != null) {
                                 pipe.kill();
                             }
@@ -382,8 +378,6 @@
                     data = entry.second.get();
                 } catch (IOException e) {
                     // Ignore this window
-                    pw.println(
-                            "Error for window " + entry.first + " : " + e.getMessage());
                     continue;
                 }
                 out.putNextEntry(new ZipEntry(entry.first));
@@ -414,7 +408,7 @@
         pw.println("    Dismiss the keyguard, prompting user for auth if necessary.");
         pw.println("  set-user-rotation [free|lock] [-d DISPLAY_ID] [rotation]");
         pw.println("    Set user rotation mode and user rotation.");
-        pw.println("  dump-visible-window-views out-file");
+        pw.println("  dump-visible-window-views");
         pw.println("    Dumps the encoded view hierarchies of visible windows");
         pw.println("  set-fix-to-user-rotation [-d DISPLAY_ID] [enabled|disabled]");
         pw.println("    Enable or disable rotating display for app requested orientation.");
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 593b84f..0441669 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -1569,7 +1569,7 @@
      * not the pending requested hidden state.
      */
     boolean isVisibleNow() {
-        return (!mToken.isHidden() || mAttrs.type == TYPE_APPLICATION_STARTING)
+        return (mToken.isVisible() || mAttrs.type == TYPE_APPLICATION_STARTING)
                 && isVisible();
     }
 
@@ -1642,7 +1642,7 @@
             return false;
         }
         final boolean parentAndClientVisible = !isParentWindowHidden()
-                && mViewVisibility == View.VISIBLE && !mToken.isHidden();
+                && mViewVisibility == View.VISIBLE && mToken.isVisible();
         return mHasSurface && isVisibleByPolicy() && !mDestroying
                 && (parentAndClientVisible || isAnimating(TRANSITION | PARENTS));
     }
@@ -1661,7 +1661,7 @@
         } else {
             final Task task = getTask();
             final boolean canFromTask = task != null && task.canAffectSystemUiFlags();
-            return canFromTask && !mActivityRecord.isHidden();
+            return canFromTask && mActivityRecord.isVisible();
         }
     }
 
@@ -1690,7 +1690,7 @@
         final ActivityRecord atoken = mActivityRecord;
         return mViewVisibility == View.GONE
                 || !mRelayoutCalled
-                || (atoken == null && mToken.isHidden())
+                || (atoken == null && !mToken.isVisible())
                 || (atoken != null && !atoken.mVisibleRequested)
                 || isParentWindowGoneForLayout()
                 || (mAnimatingExit && !isAnimatingLw())
@@ -2595,7 +2595,7 @@
      * interacts with it.
      */
     private boolean shouldKeepVisibleDeadAppWindow() {
-        if (!isWinVisibleLw() || mActivityRecord == null || mActivityRecord.isClientHidden()) {
+        if (!isWinVisibleLw() || mActivityRecord == null || !mActivityRecord.isClientVisible()) {
             // Not a visible app window or the app isn't dead.
             return false;
         }
@@ -2907,13 +2907,13 @@
     void sendAppVisibilityToClients() {
         super.sendAppVisibilityToClients();
 
-        final boolean clientHidden = mActivityRecord.isClientHidden();
-        if (mAttrs.type == TYPE_APPLICATION_STARTING && clientHidden) {
+        final boolean clientVisible = mActivityRecord.isClientVisible();
+        if (mAttrs.type == TYPE_APPLICATION_STARTING && !clientVisible) {
             // Don't hide the starting window.
             return;
         }
 
-        if (clientHidden) {
+        if (!clientVisible) {
             // Once we are notifying the client that it's visibility has changed, we need to prevent
             // it from destroying child surfaces until the animation has finished. We do this by
             // detaching any surface control the client added from the client.
@@ -2927,8 +2927,8 @@
 
         try {
             if (DEBUG_VISIBILITY) Slog.v(TAG,
-                    "Setting visibility of " + this + ": " + (!clientHidden));
-            mClient.dispatchAppVisibility(!clientHidden);
+                    "Setting visibility of " + this + ": " + clientVisible);
+            mClient.dispatchAppVisibility(clientVisible);
         } catch (RemoteException e) {
         }
     }
@@ -4170,7 +4170,7 @@
                     + " parentHidden=" + isParentWindowHidden()
                     + " tok.visibleRequested="
                     + (mActivityRecord != null && mActivityRecord.mVisibleRequested)
-                    + " tok.hidden=" + (mActivityRecord != null && mActivityRecord.isHidden())
+                    + " tok.visible=" + (mActivityRecord != null && mActivityRecord.isVisible())
                     + " animating=" + isAnimating(TRANSITION | PARENTS)
                     + " tok animating="
                     + (mActivityRecord != null && mActivityRecord.isAnimating(TRANSITION))
diff --git a/services/core/java/com/android/server/wm/WindowToken.java b/services/core/java/com/android/server/wm/WindowToken.java
index 057f493..287d7cd 100644
--- a/services/core/java/com/android/server/wm/WindowToken.java
+++ b/services/core/java/com/android/server/wm/WindowToken.java
@@ -29,7 +29,6 @@
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
 import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL;
 import static com.android.server.wm.WindowTokenProto.HASH_CODE;
-import static com.android.server.wm.WindowTokenProto.HIDDEN;
 import static com.android.server.wm.WindowTokenProto.PAUSED;
 import static com.android.server.wm.WindowTokenProto.WAITING_TO_SHOW;
 import static com.android.server.wm.WindowTokenProto.WINDOWS;
@@ -72,9 +71,6 @@
     // Is key dispatching paused for this token?
     boolean paused = false;
 
-    // Should this token's windows be hidden?
-    private boolean mHidden;
-
     // Temporary for finding which tokens no longer have visible windows.
     boolean hasVisible;
 
@@ -124,16 +120,6 @@
         }
     }
 
-    void setHidden(boolean hidden) {
-        if (hidden != mHidden) {
-            mHidden = hidden;
-        }
-    }
-
-    boolean isHidden() {
-        return mHidden;
-    }
-
     void removeAllWindowsIfPossible() {
         for (int i = mChildren.size() - 1; i >= 0; --i) {
             final WindowState win = mChildren.get(i);
@@ -152,7 +138,7 @@
         // This token is exiting, so allow it to be removed when it no longer contains any windows.
         mPersistOnEmpty = false;
 
-        if (mHidden) {
+        if (!isVisible()) {
             return;
         }
 
@@ -165,7 +151,10 @@
             changed |= win.onSetAppExiting();
         }
 
-        setHidden(true);
+        final ActivityRecord app = asActivityRecord();
+        if (app != null) {
+            app.setVisible(false);
+        }
 
         if (changed) {
             mWmService.mWindowPlacerLocked.performSurfacePlacement();
@@ -282,7 +271,6 @@
             final WindowState w = mChildren.get(i);
             w.writeToProto(proto, WINDOWS, logLevel);
         }
-        proto.write(HIDDEN, mHidden);
         proto.write(WAITING_TO_SHOW, waitingToShow);
         proto.write(PAUSED, paused);
         proto.end(token);
@@ -292,7 +280,6 @@
         super.dump(pw, prefix, dumpAll);
         pw.print(prefix); pw.print("windows="); pw.println(mChildren);
         pw.print(prefix); pw.print("windowType="); pw.print(windowType);
-                pw.print(" hidden="); pw.print(mHidden);
                 pw.print(" hasVisible="); pw.println(hasVisible);
         if (waitingToShow) {
             pw.print(prefix); pw.print("waitingToShow="); pw.print(waitingToShow);
diff --git a/services/core/jni/com_android_server_VibratorService.cpp b/services/core/jni/com_android_server_VibratorService.cpp
index 746610d..612a1e7 100644
--- a/services/core/jni/com_android_server_VibratorService.cpp
+++ b/services/core/jni/com_android_server_VibratorService.cpp
@@ -291,7 +291,7 @@
 
 static void vibratorSetAmplitude(JNIEnv*, jclass, jint amplitude) {
     if (auto hal = getHal<aidl::IVibrator>()) {
-        auto status = hal->call(&aidl::IVibrator::IVibrator::setAmplitude, amplitude);
+        auto status = hal->call(&aidl::IVibrator::IVibrator::setAmplitude, static_cast<float>(amplitude) / UINT8_MAX);
         if (!status.isOk()) {
             ALOGE("Failed to set vibrator amplitude: %s", status.toString8().string());
         }
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..7ef9f44 100644
--- a/services/net/Android.bp
+++ b/services/net/Android.bp
@@ -1,38 +1,34 @@
+filegroup {
+    name: "services.net-sources",
+    srcs: ["java/**/*.java"],
+    path: "java",
+    visibility: ["//frameworks/base/services"],
+}
+
 java_library_static {
     name: "services.net",
     srcs: [
+        ":net-module-utils-srcs",
         ":tethering-servicesnet-srcs",
-        "java/**/*.java",
+        ":services.net-sources",
     ],
     static_libs: [
         "dnsresolver_aidl_interface-V2-java",
         "netd_aidl_interface-unstable-java",
+        "netlink-client",
         "networkstack-client",
         "tethering-client",
     ],
 }
 
 filegroup {
-    name: "services-networkstack-shared-srcs",
-    srcs: [
-        "java/android/net/ip/InterfaceController.java", // TODO: move to NetworkStack with tethering
-        "java/android/net/util/InterfaceParams.java", // TODO: move to NetworkStack with IpServer
-        "java/android/net/shared/*.java",
-        "java/android/net/netlink/*.java",
-    ],
-}
-
-filegroup {
     name: "services-tethering-shared-srcs",
     srcs: [
         ":framework-annotations",
         "java/android/net/ConnectivityModuleConnector.java",
         "java/android/net/NetworkStackClient.java",
-        "java/android/net/ip/InterfaceController.java",
-        "java/android/net/netlink/*.java",
-        "java/android/net/util/InterfaceParams.java",
         "java/android/net/util/NetdService.java",
         "java/android/net/util/NetworkConstants.java",
-        "java/android/net/util/SharedLog.java"
     ],
+    visibility: ["//frameworks/base/packages/Tethering"],
 }
diff --git a/services/net/java/android/net/ip/InterfaceController.java b/services/net/java/android/net/ip/InterfaceController.java
deleted file mode 100644
index 970bc9c..0000000
--- a/services/net/java/android/net/ip/InterfaceController.java
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.ip;
-
-import android.net.INetd;
-import android.net.InterfaceConfigurationParcel;
-import android.net.LinkAddress;
-import android.net.util.SharedLog;
-import android.os.RemoteException;
-import android.os.ServiceSpecificException;
-import android.system.OsConstants;
-
-import java.net.Inet4Address;
-import java.net.InetAddress;
-
-
-/**
- * Encapsulates the multiple IP configuration operations performed on an interface.
- *
- * TODO: refactor/eliminate the redundant ways to set and clear addresses.
- *
- * @hide
- */
-public class InterfaceController {
-    private final static boolean DBG = false;
-
-    private final String mIfName;
-    private final INetd mNetd;
-    private final SharedLog mLog;
-
-    public InterfaceController(String ifname, INetd netd, SharedLog log) {
-        mIfName = ifname;
-        mNetd = netd;
-        mLog = log;
-    }
-
-    private boolean setInterfaceAddress(LinkAddress addr) {
-        final InterfaceConfigurationParcel ifConfig = new InterfaceConfigurationParcel();
-        ifConfig.ifName = mIfName;
-        ifConfig.ipv4Addr = addr.getAddress().getHostAddress();
-        ifConfig.prefixLength = addr.getPrefixLength();
-        ifConfig.hwAddr = "";
-        ifConfig.flags = new String[0];
-        try {
-            mNetd.interfaceSetCfg(ifConfig);
-        } catch (RemoteException | ServiceSpecificException e) {
-            logError("Setting IPv4 address to %s/%d failed: %s",
-                    ifConfig.ipv4Addr, ifConfig.prefixLength, e);
-            return false;
-        }
-        return true;
-    }
-
-    /**
-     * Set the IPv4 address of the interface.
-     */
-    public boolean setIPv4Address(LinkAddress address) {
-        if (!(address.getAddress() instanceof Inet4Address)) {
-            return false;
-        }
-        return setInterfaceAddress(address);
-    }
-
-    /**
-     * Clear the IPv4Address of the interface.
-     */
-    public boolean clearIPv4Address() {
-        return setInterfaceAddress(new LinkAddress("0.0.0.0/0"));
-    }
-
-    private boolean setEnableIPv6(boolean enabled) {
-        try {
-            mNetd.interfaceSetEnableIPv6(mIfName, enabled);
-        } catch (RemoteException | ServiceSpecificException e) {
-            logError("%s IPv6 failed: %s", (enabled ? "enabling" : "disabling"), e);
-            return false;
-        }
-        return true;
-    }
-
-    /**
-     * Enable IPv6 on the interface.
-     */
-    public boolean enableIPv6() {
-        return setEnableIPv6(true);
-    }
-
-    /**
-     * Disable IPv6 on the interface.
-     */
-    public boolean disableIPv6() {
-        return setEnableIPv6(false);
-    }
-
-    /**
-     * Enable or disable IPv6 privacy extensions on the interface.
-     * @param enabled Whether the extensions should be enabled.
-     */
-    public boolean setIPv6PrivacyExtensions(boolean enabled) {
-        try {
-            mNetd.interfaceSetIPv6PrivacyExtensions(mIfName, enabled);
-        } catch (RemoteException | ServiceSpecificException e) {
-            logError("error %s IPv6 privacy extensions: %s",
-                    (enabled ? "enabling" : "disabling"), e);
-            return false;
-        }
-        return true;
-    }
-
-    /**
-     * Set IPv6 address generation mode on the interface.
-     *
-     * <p>IPv6 should be disabled before changing the mode.
-     */
-    public boolean setIPv6AddrGenModeIfSupported(int mode) {
-        try {
-            mNetd.setIPv6AddrGenMode(mIfName, mode);
-        } catch (RemoteException e) {
-            logError("Unable to set IPv6 addrgen mode: %s", e);
-            return false;
-        } catch (ServiceSpecificException e) {
-            if (e.errorCode != OsConstants.EOPNOTSUPP) {
-                logError("Unable to set IPv6 addrgen mode: %s", e);
-                return false;
-            }
-        }
-        return true;
-    }
-
-    /**
-     * Add an address to the interface.
-     */
-    public boolean addAddress(LinkAddress addr) {
-        return addAddress(addr.getAddress(), addr.getPrefixLength());
-    }
-
-    /**
-     * Add an address to the interface.
-     */
-    public boolean addAddress(InetAddress ip, int prefixLen) {
-        try {
-            mNetd.interfaceAddAddress(mIfName, ip.getHostAddress(), prefixLen);
-        } catch (ServiceSpecificException | RemoteException e) {
-            logError("failed to add %s/%d: %s", ip, prefixLen, e);
-            return false;
-        }
-        return true;
-    }
-
-    /**
-     * Remove an address from the interface.
-     */
-    public boolean removeAddress(InetAddress ip, int prefixLen) {
-        try {
-            mNetd.interfaceDelAddress(mIfName, ip.getHostAddress(), prefixLen);
-        } catch (ServiceSpecificException | RemoteException e) {
-            logError("failed to remove %s/%d: %s", ip, prefixLen, e);
-            return false;
-        }
-        return true;
-    }
-
-    /**
-     * Remove all addresses from the interface.
-     */
-    public boolean clearAllAddresses() {
-        try {
-            mNetd.interfaceClearAddrs(mIfName);
-        } catch (Exception e) {
-            logError("Failed to clear addresses: %s", e);
-            return false;
-        }
-        return true;
-    }
-
-    private void logError(String fmt, Object... args) {
-        mLog.e(String.format(fmt, args));
-    }
-}
diff --git a/services/net/java/android/net/netlink/ConntrackMessage.java b/services/net/java/android/net/netlink/ConntrackMessage.java
deleted file mode 100644
index 6978739..0000000
--- a/services/net/java/android/net/netlink/ConntrackMessage.java
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.netlink;
-
-import static android.net.netlink.StructNlMsgHdr.NLM_F_ACK;
-import static android.net.netlink.StructNlMsgHdr.NLM_F_REPLACE;
-import static android.net.netlink.StructNlMsgHdr.NLM_F_REQUEST;
-
-import static java.nio.ByteOrder.BIG_ENDIAN;
-
-import android.system.OsConstants;
-
-import java.net.Inet4Address;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-
-
-/**
- * A NetlinkMessage subclass for netlink conntrack messages.
- *
- * see also: &lt;linux_src&gt;/include/uapi/linux/netfilter/nfnetlink_conntrack.h
- *
- * @hide
- */
-public class ConntrackMessage extends NetlinkMessage {
-    public static final int STRUCT_SIZE = StructNlMsgHdr.STRUCT_SIZE + StructNfGenMsg.STRUCT_SIZE;
-
-    public static final short NFNL_SUBSYS_CTNETLINK = 1;
-    public static final short IPCTNL_MSG_CT_NEW = 0;
-
-    // enum ctattr_type
-    public static final short CTA_TUPLE_ORIG  = 1;
-    public static final short CTA_TUPLE_REPLY = 2;
-    public static final short CTA_TIMEOUT     = 7;
-
-    // enum ctattr_tuple
-    public static final short CTA_TUPLE_IP    = 1;
-    public static final short CTA_TUPLE_PROTO = 2;
-
-    // enum ctattr_ip
-    public static final short CTA_IP_V4_SRC = 1;
-    public static final short CTA_IP_V4_DST = 2;
-
-    // enum ctattr_l4proto
-    public static final short CTA_PROTO_NUM      = 1;
-    public static final short CTA_PROTO_SRC_PORT = 2;
-    public static final short CTA_PROTO_DST_PORT = 3;
-
-    public static byte[] newIPv4TimeoutUpdateRequest(
-            int proto, Inet4Address src, int sport, Inet4Address dst, int dport, int timeoutSec) {
-        // *** STYLE WARNING ***
-        //
-        // Code below this point uses extra block indentation to highlight the
-        // packing of nested tuple netlink attribute types.
-        final StructNlAttr ctaTupleOrig = new StructNlAttr(CTA_TUPLE_ORIG,
-                new StructNlAttr(CTA_TUPLE_IP,
-                        new StructNlAttr(CTA_IP_V4_SRC, src),
-                        new StructNlAttr(CTA_IP_V4_DST, dst)),
-                new StructNlAttr(CTA_TUPLE_PROTO,
-                        new StructNlAttr(CTA_PROTO_NUM, (byte) proto),
-                        new StructNlAttr(CTA_PROTO_SRC_PORT, (short) sport, BIG_ENDIAN),
-                        new StructNlAttr(CTA_PROTO_DST_PORT, (short) dport, BIG_ENDIAN)));
-
-        final StructNlAttr ctaTimeout = new StructNlAttr(CTA_TIMEOUT, timeoutSec, BIG_ENDIAN);
-
-        final int payloadLength = ctaTupleOrig.getAlignedLength() + ctaTimeout.getAlignedLength();
-        final byte[] bytes = new byte[STRUCT_SIZE + payloadLength];
-        final ByteBuffer byteBuffer = ByteBuffer.wrap(bytes);
-        byteBuffer.order(ByteOrder.nativeOrder());
-
-        final ConntrackMessage ctmsg = new ConntrackMessage();
-        ctmsg.mHeader.nlmsg_len = bytes.length;
-        ctmsg.mHeader.nlmsg_type = (NFNL_SUBSYS_CTNETLINK << 8) | IPCTNL_MSG_CT_NEW;
-        ctmsg.mHeader.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_REPLACE;
-        ctmsg.mHeader.nlmsg_seq = 1;
-        ctmsg.pack(byteBuffer);
-
-        ctaTupleOrig.pack(byteBuffer);
-        ctaTimeout.pack(byteBuffer);
-
-        return bytes;
-    }
-
-    protected StructNfGenMsg mNfGenMsg;
-
-    private ConntrackMessage() {
-        super(new StructNlMsgHdr());
-        mNfGenMsg = new StructNfGenMsg((byte) OsConstants.AF_INET);
-    }
-
-    public void pack(ByteBuffer byteBuffer) {
-        mHeader.pack(byteBuffer);
-        mNfGenMsg.pack(byteBuffer);
-    }
-}
diff --git a/services/net/java/android/net/netlink/InetDiagMessage.java b/services/net/java/android/net/netlink/InetDiagMessage.java
deleted file mode 100644
index ca07630..0000000
--- a/services/net/java/android/net/netlink/InetDiagMessage.java
+++ /dev/null
@@ -1,221 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.netlink;
-
-import static android.net.netlink.NetlinkConstants.SOCK_DIAG_BY_FAMILY;
-import static android.net.netlink.NetlinkSocket.DEFAULT_RECV_BUFSIZE;
-import static android.net.netlink.StructNlMsgHdr.NLM_F_DUMP;
-import static android.net.netlink.StructNlMsgHdr.NLM_F_REQUEST;
-import static android.os.Process.INVALID_UID;
-import static android.system.OsConstants.AF_INET;
-import static android.system.OsConstants.AF_INET6;
-import static android.system.OsConstants.IPPROTO_UDP;
-import static android.system.OsConstants.NETLINK_INET_DIAG;
-
-import android.annotation.Nullable;
-import android.net.util.SocketUtils;
-import android.system.ErrnoException;
-import android.util.Log;
-
-import java.io.FileDescriptor;
-import java.io.IOException;
-import java.io.InterruptedIOException;
-import java.net.Inet4Address;
-import java.net.Inet6Address;
-import java.net.InetSocketAddress;
-import java.net.SocketException;
-import java.net.UnknownHostException;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-
-/**
- * A NetlinkMessage subclass for netlink inet_diag messages.
- *
- * see also: &lt;linux_src&gt;/include/uapi/linux/inet_diag.h
- *
- * @hide
- */
-public class InetDiagMessage extends NetlinkMessage {
-    public static final String TAG = "InetDiagMessage";
-    private static final int TIMEOUT_MS = 500;
-
-    public static byte[] InetDiagReqV2(int protocol, InetSocketAddress local,
-            InetSocketAddress remote, int family, short flags) {
-        return InetDiagReqV2(protocol, local, remote, family, flags, 0 /* pad */,
-                0 /* idiagExt */, StructInetDiagReqV2.INET_DIAG_REQ_V2_ALL_STATES);
-    }
-
-    /**
-     * Construct an inet_diag_req_v2 message. This method will throw {@code NullPointerException}
-     * if local and remote are not both null or both non-null.
-     *
-     * @param protocol the request protocol type. This should be set to one of IPPROTO_TCP,
-     *                 IPPROTO_UDP, or IPPROTO_UDPLITE.
-     * @param local local socket address of the target socket. This will be packed into a
-     *              {@Code StructInetDiagSockId}. Request to diagnose for all sockets if both of
-     *              local or remote address is null.
-     * @param remote remote socket address of the target socket. This will be packed into a
-     *              {@Code StructInetDiagSockId}. Request to diagnose for all sockets if both of
-     *              local or remote address is null.
-     * @param family the ip family of the request message. This should be set to either AF_INET or
-     *               AF_INET6 for IPv4 or IPv6 sockets respectively.
-     * @param flags message flags. See &lt;linux_src&gt;/include/uapi/linux/netlink.h.
-     * @param pad for raw socket protocol specification.
-     * @param idiagExt a set of flags defining what kind of extended information to report.
-     * @param state a bit mask that defines a filter of socket states.
-     *
-     * @return bytes array representation of the message
-     **/
-    public static byte[] InetDiagReqV2(int protocol, @Nullable InetSocketAddress local,
-            @Nullable InetSocketAddress remote, int family, short flags, int pad, int idiagExt,
-            int state) throws NullPointerException {
-        final byte[] bytes = new byte[StructNlMsgHdr.STRUCT_SIZE + StructInetDiagReqV2.STRUCT_SIZE];
-        final ByteBuffer byteBuffer = ByteBuffer.wrap(bytes);
-        byteBuffer.order(ByteOrder.nativeOrder());
-
-        final StructNlMsgHdr nlMsgHdr = new StructNlMsgHdr();
-        nlMsgHdr.nlmsg_len = bytes.length;
-        nlMsgHdr.nlmsg_type = SOCK_DIAG_BY_FAMILY;
-        nlMsgHdr.nlmsg_flags = flags;
-        nlMsgHdr.pack(byteBuffer);
-        final StructInetDiagReqV2 inetDiagReqV2 =
-                new StructInetDiagReqV2(protocol, local, remote, family, pad, idiagExt, state);
-
-        inetDiagReqV2.pack(byteBuffer);
-        return bytes;
-    }
-
-    public StructInetDiagMsg mStructInetDiagMsg;
-
-    private InetDiagMessage(StructNlMsgHdr header) {
-        super(header);
-        mStructInetDiagMsg = new StructInetDiagMsg();
-    }
-
-    public static InetDiagMessage parse(StructNlMsgHdr header, ByteBuffer byteBuffer) {
-        final InetDiagMessage msg = new InetDiagMessage(header);
-        msg.mStructInetDiagMsg = StructInetDiagMsg.parse(byteBuffer);
-        return msg;
-    }
-
-    private static int lookupUidByFamily(int protocol, InetSocketAddress local,
-                                         InetSocketAddress remote, int family, short flags,
-                                         FileDescriptor fd)
-            throws ErrnoException, InterruptedIOException {
-        byte[] msg = InetDiagReqV2(protocol, local, remote, family, flags);
-        NetlinkSocket.sendMessage(fd, msg, 0, msg.length, TIMEOUT_MS);
-        ByteBuffer response = NetlinkSocket.recvMessage(fd, DEFAULT_RECV_BUFSIZE, TIMEOUT_MS);
-
-        final NetlinkMessage nlMsg = NetlinkMessage.parse(response);
-        final StructNlMsgHdr hdr = nlMsg.getHeader();
-        if (hdr.nlmsg_type == NetlinkConstants.NLMSG_DONE) {
-            return INVALID_UID;
-        }
-        if (nlMsg instanceof InetDiagMessage) {
-            return ((InetDiagMessage) nlMsg).mStructInetDiagMsg.idiag_uid;
-        }
-        return INVALID_UID;
-    }
-
-    private static final int FAMILY[] = {AF_INET6, AF_INET};
-
-    private static int lookupUid(int protocol, InetSocketAddress local,
-                                 InetSocketAddress remote, FileDescriptor fd)
-            throws ErrnoException, InterruptedIOException {
-        int uid;
-
-        for (int family : FAMILY) {
-            /**
-             * For exact match lookup, swap local and remote for UDP lookups due to kernel
-             * bug which will not be fixed. See aosp/755889 and
-             * https://www.mail-archive.com/netdev@vger.kernel.org/msg248638.html
-             */
-            if (protocol == IPPROTO_UDP) {
-                uid = lookupUidByFamily(protocol, remote, local, family, NLM_F_REQUEST, fd);
-            } else {
-                uid = lookupUidByFamily(protocol, local, remote, family, NLM_F_REQUEST, fd);
-            }
-            if (uid != INVALID_UID) {
-                return uid;
-            }
-        }
-
-        /**
-         * For UDP it's possible for a socket to send packets to arbitrary destinations, even if the
-         * socket is not connected (and even if the socket is connected to a different destination).
-         * If we want this API to work for such packets, then on miss we need to do a second lookup
-         * with only the local address and port filled in.
-         * Always use flags == NLM_F_REQUEST | NLM_F_DUMP for wildcard.
-         */
-        if (protocol == IPPROTO_UDP) {
-            try {
-                InetSocketAddress wildcard = new InetSocketAddress(
-                        Inet6Address.getByName("::"), 0);
-                uid = lookupUidByFamily(protocol, local, wildcard, AF_INET6,
-                        (short) (NLM_F_REQUEST | NLM_F_DUMP), fd);
-                if (uid != INVALID_UID) {
-                    return uid;
-                }
-                wildcard = new InetSocketAddress(Inet4Address.getByName("0.0.0.0"), 0);
-                uid = lookupUidByFamily(protocol, local, wildcard, AF_INET,
-                        (short) (NLM_F_REQUEST | NLM_F_DUMP), fd);
-                if (uid != INVALID_UID) {
-                    return uid;
-                }
-            } catch (UnknownHostException e) {
-                Log.e(TAG, e.toString());
-            }
-        }
-        return INVALID_UID;
-    }
-
-    /**
-     * Use an inet_diag socket to look up the UID associated with the input local and remote
-     * address/port and protocol of a connection.
-     */
-    public static int getConnectionOwnerUid(int protocol, InetSocketAddress local,
-                                            InetSocketAddress remote) {
-        int uid = INVALID_UID;
-        FileDescriptor fd = null;
-        try {
-            fd = NetlinkSocket.forProto(NETLINK_INET_DIAG);
-            NetlinkSocket.connectToKernel(fd);
-            uid = lookupUid(protocol, local, remote, fd);
-        } catch (ErrnoException | SocketException | IllegalArgumentException
-                | InterruptedIOException e) {
-            Log.e(TAG, e.toString());
-        } finally {
-            if (fd != null) {
-                try {
-                    SocketUtils.closeSocket(fd);
-                } catch (IOException e) {
-                    Log.e(TAG, e.toString());
-                }
-            }
-        }
-        return uid;
-    }
-
-    @Override
-    public String toString() {
-        return "InetDiagMessage{ "
-                + "nlmsghdr{" + (mHeader == null ? "" : mHeader.toString()) + "}, "
-                + "inet_diag_msg{"
-                + (mStructInetDiagMsg == null ? "" : mStructInetDiagMsg.toString()) + "} "
-                + "}";
-    }
-}
diff --git a/services/net/java/android/net/netlink/NetlinkConstants.java b/services/net/java/android/net/netlink/NetlinkConstants.java
deleted file mode 100644
index fc1551c..0000000
--- a/services/net/java/android/net/netlink/NetlinkConstants.java
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.netlink;
-
-import android.system.OsConstants;
-import com.android.internal.util.HexDump;
-
-import java.nio.ByteBuffer;
-
-
-/**
- * Various constants and static helper methods for netlink communications.
- *
- * Values taken from:
- *
- *     &lt;linux_src&gt;/include/uapi/linux/netlink.h
- *     &lt;linux_src&gt;/include/uapi/linux/rtnetlink.h
- *
- * @hide
- */
-public class NetlinkConstants {
-    private NetlinkConstants() {}
-
-    public static final int NLA_ALIGNTO = 4;
-
-    public static final int alignedLengthOf(short length) {
-        final int intLength = (int) length & 0xffff;
-        return alignedLengthOf(intLength);
-    }
-
-    public static final int alignedLengthOf(int length) {
-        if (length <= 0) { return 0; }
-        return (((length + NLA_ALIGNTO - 1) / NLA_ALIGNTO) * NLA_ALIGNTO);
-    }
-
-    public static String stringForAddressFamily(int family) {
-        if (family == OsConstants.AF_INET) { return "AF_INET"; }
-        if (family == OsConstants.AF_INET6) { return "AF_INET6"; }
-        if (family == OsConstants.AF_NETLINK) { return "AF_NETLINK"; }
-        return String.valueOf(family);
-    }
-
-    public static String stringForProtocol(int protocol) {
-        if (protocol == OsConstants.IPPROTO_TCP) { return "IPPROTO_TCP"; }
-        if (protocol == OsConstants.IPPROTO_UDP) { return "IPPROTO_UDP"; }
-        return String.valueOf(protocol);
-    }
-
-    public static String hexify(byte[] bytes) {
-        if (bytes == null) { return "(null)"; }
-        return HexDump.toHexString(bytes);
-    }
-
-    public static String hexify(ByteBuffer buffer) {
-        if (buffer == null) { return "(null)"; }
-        return HexDump.toHexString(
-                buffer.array(), buffer.position(), buffer.remaining());
-    }
-
-    // Known values for struct nlmsghdr nlm_type.
-    public static final short NLMSG_NOOP         = 1;   // Nothing
-    public static final short NLMSG_ERROR        = 2;   // Error
-    public static final short NLMSG_DONE         = 3;   // End of a dump
-    public static final short NLMSG_OVERRUN      = 4;   // Data lost
-    public static final short NLMSG_MAX_RESERVED = 15;  // Max reserved value
-
-    public static final short RTM_NEWLINK        = 16;
-    public static final short RTM_DELLINK        = 17;
-    public static final short RTM_GETLINK        = 18;
-    public static final short RTM_SETLINK        = 19;
-    public static final short RTM_NEWADDR        = 20;
-    public static final short RTM_DELADDR        = 21;
-    public static final short RTM_GETADDR        = 22;
-    public static final short RTM_NEWROUTE       = 24;
-    public static final short RTM_DELROUTE       = 25;
-    public static final short RTM_GETROUTE       = 26;
-    public static final short RTM_NEWNEIGH       = 28;
-    public static final short RTM_DELNEIGH       = 29;
-    public static final short RTM_GETNEIGH       = 30;
-    public static final short RTM_NEWRULE        = 32;
-    public static final short RTM_DELRULE        = 33;
-    public static final short RTM_GETRULE        = 34;
-    public static final short RTM_NEWNDUSEROPT   = 68;
-
-    /* see &lt;linux_src&gt;/include/uapi/linux/sock_diag.h */
-    public static final short SOCK_DIAG_BY_FAMILY = 20;
-
-    public static String stringForNlMsgType(short nlm_type) {
-        switch (nlm_type) {
-            case NLMSG_NOOP: return "NLMSG_NOOP";
-            case NLMSG_ERROR: return "NLMSG_ERROR";
-            case NLMSG_DONE: return "NLMSG_DONE";
-            case NLMSG_OVERRUN: return "NLMSG_OVERRUN";
-            case RTM_NEWLINK: return "RTM_NEWLINK";
-            case RTM_DELLINK: return "RTM_DELLINK";
-            case RTM_GETLINK: return "RTM_GETLINK";
-            case RTM_SETLINK: return "RTM_SETLINK";
-            case RTM_NEWADDR: return "RTM_NEWADDR";
-            case RTM_DELADDR: return "RTM_DELADDR";
-            case RTM_GETADDR: return "RTM_GETADDR";
-            case RTM_NEWROUTE: return "RTM_NEWROUTE";
-            case RTM_DELROUTE: return "RTM_DELROUTE";
-            case RTM_GETROUTE: return "RTM_GETROUTE";
-            case RTM_NEWNEIGH: return "RTM_NEWNEIGH";
-            case RTM_DELNEIGH: return "RTM_DELNEIGH";
-            case RTM_GETNEIGH: return "RTM_GETNEIGH";
-            case RTM_NEWRULE: return "RTM_NEWRULE";
-            case RTM_DELRULE: return "RTM_DELRULE";
-            case RTM_GETRULE: return "RTM_GETRULE";
-            case RTM_NEWNDUSEROPT: return "RTM_NEWNDUSEROPT";
-            default:
-                return "unknown RTM type: " + String.valueOf(nlm_type);
-        }
-    }
-}
diff --git a/services/net/java/android/net/netlink/NetlinkErrorMessage.java b/services/net/java/android/net/netlink/NetlinkErrorMessage.java
deleted file mode 100644
index e275574..0000000
--- a/services/net/java/android/net/netlink/NetlinkErrorMessage.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.netlink;
-
-import android.net.netlink.StructNlMsgHdr;
-import android.net.netlink.NetlinkMessage;
-
-import java.nio.ByteBuffer;
-
-
-/**
- * A NetlinkMessage subclass for netlink error messages.
- *
- * @hide
- */
-public class NetlinkErrorMessage extends NetlinkMessage {
-
-    public static NetlinkErrorMessage parse(StructNlMsgHdr header, ByteBuffer byteBuffer) {
-        final NetlinkErrorMessage errorMsg = new NetlinkErrorMessage(header);
-
-        errorMsg.mNlMsgErr = StructNlMsgErr.parse(byteBuffer);
-        if (errorMsg.mNlMsgErr == null) {
-            return null;
-        }
-
-        return errorMsg;
-    }
-
-    private StructNlMsgErr mNlMsgErr;
-
-    NetlinkErrorMessage(StructNlMsgHdr header) {
-        super(header);
-        mNlMsgErr = null;
-    }
-
-    public StructNlMsgErr getNlMsgError() {
-        return mNlMsgErr;
-    }
-
-    @Override
-    public String toString() {
-        return "NetlinkErrorMessage{ "
-                + "nlmsghdr{" + (mHeader == null ? "" : mHeader.toString()) + "}, "
-                + "nlmsgerr{" + (mNlMsgErr == null ? "" : mNlMsgErr.toString()) + "} "
-                + "}";
-    }
-}
diff --git a/services/net/java/android/net/netlink/NetlinkMessage.java b/services/net/java/android/net/netlink/NetlinkMessage.java
deleted file mode 100644
index a325db8..0000000
--- a/services/net/java/android/net/netlink/NetlinkMessage.java
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.netlink;
-
-import android.net.netlink.NetlinkConstants;
-import android.net.netlink.NetlinkErrorMessage;
-import android.net.netlink.RtNetlinkNeighborMessage;
-import android.net.netlink.StructNlAttr;
-import android.net.netlink.StructNlMsgHdr;
-import android.util.Log;
-
-import java.nio.ByteBuffer;
-
-
-/**
- * NetlinkMessage base class for other, more specific netlink message types.
- *
- * Classes that extend NetlinkMessage should:
- *     - implement a public static parse(StructNlMsgHdr, ByteBuffer) method
- *     - returning either null (parse errors) or a new object of the subclass
- *       type (cast-able to NetlinkMessage)
- *
- * NetlinkMessage.parse() should be updated to know which nlmsg_type values
- * correspond with which message subclasses.
- *
- * @hide
- */
-public class NetlinkMessage {
-    private final static String TAG = "NetlinkMessage";
-
-    public static NetlinkMessage parse(ByteBuffer byteBuffer) {
-        final int startPosition = (byteBuffer != null) ? byteBuffer.position() : -1;
-        final StructNlMsgHdr nlmsghdr = StructNlMsgHdr.parse(byteBuffer);
-        if (nlmsghdr == null) {
-            return null;
-        }
-
-        int payloadLength = NetlinkConstants.alignedLengthOf(nlmsghdr.nlmsg_len);
-        payloadLength -= StructNlMsgHdr.STRUCT_SIZE;
-        if (payloadLength < 0 || payloadLength > byteBuffer.remaining()) {
-            // Malformed message or runt buffer.  Pretend the buffer was consumed.
-            byteBuffer.position(byteBuffer.limit());
-            return null;
-        }
-
-        switch (nlmsghdr.nlmsg_type) {
-            //case NetlinkConstants.NLMSG_NOOP:
-            case NetlinkConstants.NLMSG_ERROR:
-                return (NetlinkMessage) NetlinkErrorMessage.parse(nlmsghdr, byteBuffer);
-            case NetlinkConstants.NLMSG_DONE:
-                byteBuffer.position(byteBuffer.position() + payloadLength);
-                return new NetlinkMessage(nlmsghdr);
-            //case NetlinkConstants.NLMSG_OVERRUN:
-            case NetlinkConstants.RTM_NEWNEIGH:
-            case NetlinkConstants.RTM_DELNEIGH:
-            case NetlinkConstants.RTM_GETNEIGH:
-                return (NetlinkMessage) RtNetlinkNeighborMessage.parse(nlmsghdr, byteBuffer);
-            case NetlinkConstants.SOCK_DIAG_BY_FAMILY:
-                return (NetlinkMessage) InetDiagMessage.parse(nlmsghdr, byteBuffer);
-            default:
-                if (nlmsghdr.nlmsg_type <= NetlinkConstants.NLMSG_MAX_RESERVED) {
-                    // Netlink control message.  Just parse the header for now,
-                    // pretending the whole message was consumed.
-                    byteBuffer.position(byteBuffer.position() + payloadLength);
-                    return new NetlinkMessage(nlmsghdr);
-                }
-                return null;
-        }
-    }
-
-    protected StructNlMsgHdr mHeader;
-
-    public NetlinkMessage(StructNlMsgHdr nlmsghdr) {
-        mHeader = nlmsghdr;
-    }
-
-    public StructNlMsgHdr getHeader() {
-        return mHeader;
-    }
-
-    @Override
-    public String toString() {
-        return "NetlinkMessage{" + (mHeader == null ? "" : mHeader.toString()) + "}";
-    }
-}
diff --git a/services/net/java/android/net/netlink/NetlinkSocket.java b/services/net/java/android/net/netlink/NetlinkSocket.java
deleted file mode 100644
index 7311fc5..0000000
--- a/services/net/java/android/net/netlink/NetlinkSocket.java
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.netlink;
-
-import static android.net.util.SocketUtils.makeNetlinkSocketAddress;
-import static android.system.OsConstants.AF_NETLINK;
-import static android.system.OsConstants.EIO;
-import static android.system.OsConstants.EPROTO;
-import static android.system.OsConstants.ETIMEDOUT;
-import static android.system.OsConstants.SOCK_DGRAM;
-import static android.system.OsConstants.SOL_SOCKET;
-import static android.system.OsConstants.SO_RCVBUF;
-import static android.system.OsConstants.SO_RCVTIMEO;
-import static android.system.OsConstants.SO_SNDTIMEO;
-
-import android.net.util.SocketUtils;
-import android.system.ErrnoException;
-import android.system.Os;
-import android.system.StructTimeval;
-import android.util.Log;
-
-import java.io.FileDescriptor;
-import java.io.IOException;
-import java.io.InterruptedIOException;
-import java.net.SocketException;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-
-
-/**
- * NetlinkSocket
- *
- * A small static class to assist with AF_NETLINK socket operations.
- *
- * @hide
- */
-public class NetlinkSocket {
-    private static final String TAG = "NetlinkSocket";
-
-    public static final int DEFAULT_RECV_BUFSIZE = 8 * 1024;
-    public static final int SOCKET_RECV_BUFSIZE = 64 * 1024;
-
-    public static void sendOneShotKernelMessage(int nlProto, byte[] msg) throws ErrnoException {
-        final String errPrefix = "Error in NetlinkSocket.sendOneShotKernelMessage";
-        final long IO_TIMEOUT = 300L;
-
-        final FileDescriptor fd = forProto(nlProto);
-
-        try {
-            connectToKernel(fd);
-            sendMessage(fd, msg, 0, msg.length, IO_TIMEOUT);
-            final ByteBuffer bytes = recvMessage(fd, DEFAULT_RECV_BUFSIZE, IO_TIMEOUT);
-            // recvMessage() guaranteed to not return null if it did not throw.
-            final NetlinkMessage response = NetlinkMessage.parse(bytes);
-            if (response != null && response instanceof NetlinkErrorMessage &&
-                    (((NetlinkErrorMessage) response).getNlMsgError() != null)) {
-                final int errno = ((NetlinkErrorMessage) response).getNlMsgError().error;
-                if (errno != 0) {
-                    // TODO: consider ignoring EINVAL (-22), which appears to be
-                    // normal when probing a neighbor for which the kernel does
-                    // not already have / no longer has a link layer address.
-                    Log.e(TAG, errPrefix + ", errmsg=" + response.toString());
-                    // Note: convert kernel errnos (negative) into userspace errnos (positive).
-                    throw new ErrnoException(response.toString(), Math.abs(errno));
-                }
-            } else {
-                final String errmsg;
-                if (response == null) {
-                    bytes.position(0);
-                    errmsg = "raw bytes: " + NetlinkConstants.hexify(bytes);
-                } else {
-                    errmsg = response.toString();
-                }
-                Log.e(TAG, errPrefix + ", errmsg=" + errmsg);
-                throw new ErrnoException(errmsg, EPROTO);
-            }
-        } catch (InterruptedIOException e) {
-            Log.e(TAG, errPrefix, e);
-            throw new ErrnoException(errPrefix, ETIMEDOUT, e);
-        } catch (SocketException e) {
-            Log.e(TAG, errPrefix, e);
-            throw new ErrnoException(errPrefix, EIO, e);
-        } finally {
-            try {
-                SocketUtils.closeSocket(fd);
-            } catch (IOException e) {
-                // Nothing we can do here
-            }
-        }
-    }
-
-    public static FileDescriptor forProto(int nlProto) throws ErrnoException {
-        final FileDescriptor fd = Os.socket(AF_NETLINK, SOCK_DGRAM, nlProto);
-        Os.setsockoptInt(fd, SOL_SOCKET, SO_RCVBUF, SOCKET_RECV_BUFSIZE);
-        return fd;
-    }
-
-    public static void connectToKernel(FileDescriptor fd) throws ErrnoException, SocketException {
-        Os.connect(fd, makeNetlinkSocketAddress(0, 0));
-    }
-
-    private static void checkTimeout(long timeoutMs) {
-        if (timeoutMs < 0) {
-            throw new IllegalArgumentException("Negative timeouts not permitted");
-        }
-    }
-
-    /**
-     * Wait up to |timeoutMs| (or until underlying socket error) for a
-     * netlink message of at most |bufsize| size.
-     *
-     * Multi-threaded calls with different timeouts will cause unexpected results.
-     */
-    public static ByteBuffer recvMessage(FileDescriptor fd, int bufsize, long timeoutMs)
-            throws ErrnoException, IllegalArgumentException, InterruptedIOException {
-        checkTimeout(timeoutMs);
-
-        Os.setsockoptTimeval(fd, SOL_SOCKET, SO_RCVTIMEO, StructTimeval.fromMillis(timeoutMs));
-
-        ByteBuffer byteBuffer = ByteBuffer.allocate(bufsize);
-        int length = Os.read(fd, byteBuffer);
-        if (length == bufsize) {
-            Log.w(TAG, "maximum read");
-        }
-        byteBuffer.position(0);
-        byteBuffer.limit(length);
-        byteBuffer.order(ByteOrder.nativeOrder());
-        return byteBuffer;
-    }
-
-    /**
-     * Send a message to a peer to which this socket has previously connected,
-     * waiting at most |timeoutMs| milliseconds for the send to complete.
-     *
-     * Multi-threaded calls with different timeouts will cause unexpected results.
-     */
-    public static int sendMessage(
-            FileDescriptor fd, byte[] bytes, int offset, int count, long timeoutMs)
-            throws ErrnoException, IllegalArgumentException, InterruptedIOException {
-        checkTimeout(timeoutMs);
-        Os.setsockoptTimeval(fd, SOL_SOCKET, SO_SNDTIMEO, StructTimeval.fromMillis(timeoutMs));
-        return Os.write(fd, bytes, offset, count);
-    }
-}
diff --git a/services/net/java/android/net/netlink/RtNetlinkNeighborMessage.java b/services/net/java/android/net/netlink/RtNetlinkNeighborMessage.java
deleted file mode 100644
index e784fbb..0000000
--- a/services/net/java/android/net/netlink/RtNetlinkNeighborMessage.java
+++ /dev/null
@@ -1,251 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.netlink;
-
-import static android.net.netlink.StructNlMsgHdr.NLM_F_ACK;
-import static android.net.netlink.StructNlMsgHdr.NLM_F_DUMP;
-import static android.net.netlink.StructNlMsgHdr.NLM_F_REPLACE;
-import static android.net.netlink.StructNlMsgHdr.NLM_F_REQUEST;
-
-import android.net.netlink.StructNdaCacheInfo;
-import android.net.netlink.StructNdMsg;
-import android.net.netlink.StructNlAttr;
-import android.net.netlink.StructNlMsgHdr;
-import android.net.netlink.NetlinkMessage;
-import android.system.OsConstants;
-import android.util.Log;
-
-import java.net.InetAddress;
-import java.net.Inet6Address;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-
-
-/**
- * A NetlinkMessage subclass for rtnetlink neighbor messages.
- *
- * see also: &lt;linux_src&gt;/include/uapi/linux/neighbour.h
- *
- * @hide
- */
-public class RtNetlinkNeighborMessage extends NetlinkMessage {
-    public static final short NDA_UNSPEC    = 0;
-    public static final short NDA_DST       = 1;
-    public static final short NDA_LLADDR    = 2;
-    public static final short NDA_CACHEINFO = 3;
-    public static final short NDA_PROBES    = 4;
-    public static final short NDA_VLAN      = 5;
-    public static final short NDA_PORT      = 6;
-    public static final short NDA_VNI       = 7;
-    public static final short NDA_IFINDEX   = 8;
-    public static final short NDA_MASTER    = 9;
-
-    private static StructNlAttr findNextAttrOfType(short attrType, ByteBuffer byteBuffer) {
-        while (byteBuffer != null && byteBuffer.remaining() > 0) {
-            final StructNlAttr nlAttr = StructNlAttr.peek(byteBuffer);
-            if (nlAttr == null) {
-                break;
-            }
-            if (nlAttr.nla_type == attrType) {
-                return StructNlAttr.parse(byteBuffer);
-            }
-            if (byteBuffer.remaining() < nlAttr.getAlignedLength()) {
-                break;
-            }
-            byteBuffer.position(byteBuffer.position() + nlAttr.getAlignedLength());
-        }
-        return null;
-    }
-
-    public static RtNetlinkNeighborMessage parse(StructNlMsgHdr header, ByteBuffer byteBuffer) {
-        final RtNetlinkNeighborMessage neighMsg = new RtNetlinkNeighborMessage(header);
-
-        neighMsg.mNdmsg = StructNdMsg.parse(byteBuffer);
-        if (neighMsg.mNdmsg == null) {
-            return null;
-        }
-
-        // Some of these are message-type dependent, and not always present.
-        final int baseOffset = byteBuffer.position();
-        StructNlAttr nlAttr = findNextAttrOfType(NDA_DST, byteBuffer);
-        if (nlAttr != null) {
-            neighMsg.mDestination = nlAttr.getValueAsInetAddress();
-        }
-
-        byteBuffer.position(baseOffset);
-        nlAttr = findNextAttrOfType(NDA_LLADDR, byteBuffer);
-        if (nlAttr != null) {
-            neighMsg.mLinkLayerAddr = nlAttr.nla_value;
-        }
-
-        byteBuffer.position(baseOffset);
-        nlAttr = findNextAttrOfType(NDA_PROBES, byteBuffer);
-        if (nlAttr != null) {
-            neighMsg.mNumProbes = nlAttr.getValueAsInt(0);
-        }
-
-        byteBuffer.position(baseOffset);
-        nlAttr = findNextAttrOfType(NDA_CACHEINFO, byteBuffer);
-        if (nlAttr != null) {
-            neighMsg.mCacheInfo = StructNdaCacheInfo.parse(nlAttr.getValueAsByteBuffer());
-        }
-
-        final int kMinConsumed = StructNlMsgHdr.STRUCT_SIZE + StructNdMsg.STRUCT_SIZE;
-        final int kAdditionalSpace = NetlinkConstants.alignedLengthOf(
-                neighMsg.mHeader.nlmsg_len - kMinConsumed);
-        if (byteBuffer.remaining() < kAdditionalSpace) {
-            byteBuffer.position(byteBuffer.limit());
-        } else {
-            byteBuffer.position(baseOffset + kAdditionalSpace);
-        }
-
-        return neighMsg;
-    }
-
-    /**
-     * A convenience method to create an RTM_GETNEIGH request message.
-     */
-    public static byte[] newGetNeighborsRequest(int seqNo) {
-        final int length = StructNlMsgHdr.STRUCT_SIZE + StructNdMsg.STRUCT_SIZE;
-        final byte[] bytes = new byte[length];
-        final ByteBuffer byteBuffer = ByteBuffer.wrap(bytes);
-        byteBuffer.order(ByteOrder.nativeOrder());
-
-        final StructNlMsgHdr nlmsghdr = new StructNlMsgHdr();
-        nlmsghdr.nlmsg_len = length;
-        nlmsghdr.nlmsg_type = NetlinkConstants.RTM_GETNEIGH;
-        nlmsghdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
-        nlmsghdr.nlmsg_seq = seqNo;
-        nlmsghdr.pack(byteBuffer);
-
-        final StructNdMsg ndmsg = new StructNdMsg();
-        ndmsg.pack(byteBuffer);
-
-        return bytes;
-    }
-
-    /**
-     * A convenience method to create an RTM_NEWNEIGH message, to modify
-     * the kernel's state information for a specific neighbor.
-     */
-    public static byte[] newNewNeighborMessage(
-            int seqNo, InetAddress ip, short nudState, int ifIndex, byte[] llAddr) {
-        final StructNlMsgHdr nlmsghdr = new StructNlMsgHdr();
-        nlmsghdr.nlmsg_type = NetlinkConstants.RTM_NEWNEIGH;
-        nlmsghdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_REPLACE;
-        nlmsghdr.nlmsg_seq = seqNo;
-
-        final RtNetlinkNeighborMessage msg = new RtNetlinkNeighborMessage(nlmsghdr);
-        msg.mNdmsg = new StructNdMsg();
-        msg.mNdmsg.ndm_family =
-                (byte) ((ip instanceof Inet6Address) ? OsConstants.AF_INET6 : OsConstants.AF_INET);
-        msg.mNdmsg.ndm_ifindex = ifIndex;
-        msg.mNdmsg.ndm_state = nudState;
-        msg.mDestination = ip;
-        msg.mLinkLayerAddr = llAddr;  // might be null
-
-        final byte[] bytes = new byte[msg.getRequiredSpace()];
-        nlmsghdr.nlmsg_len = bytes.length;
-        final ByteBuffer byteBuffer = ByteBuffer.wrap(bytes);
-        byteBuffer.order(ByteOrder.nativeOrder());
-        msg.pack(byteBuffer);
-        return bytes;
-    }
-
-    private StructNdMsg mNdmsg;
-    private InetAddress mDestination;
-    private byte[] mLinkLayerAddr;
-    private int mNumProbes;
-    private StructNdaCacheInfo mCacheInfo;
-
-    private RtNetlinkNeighborMessage(StructNlMsgHdr header) {
-        super(header);
-        mNdmsg = null;
-        mDestination = null;
-        mLinkLayerAddr = null;
-        mNumProbes = 0;
-        mCacheInfo = null;
-    }
-
-    public StructNdMsg getNdHeader() {
-        return mNdmsg;
-    }
-
-    public InetAddress getDestination() {
-        return mDestination;
-    }
-
-    public byte[] getLinkLayerAddress() {
-        return mLinkLayerAddr;
-    }
-
-    public int getProbes() {
-        return mNumProbes;
-    }
-
-    public StructNdaCacheInfo getCacheInfo() {
-        return mCacheInfo;
-    }
-
-    public int getRequiredSpace() {
-        int spaceRequired = StructNlMsgHdr.STRUCT_SIZE + StructNdMsg.STRUCT_SIZE;
-        if (mDestination != null) {
-            spaceRequired += NetlinkConstants.alignedLengthOf(
-                    StructNlAttr.NLA_HEADERLEN + mDestination.getAddress().length);
-        }
-        if (mLinkLayerAddr != null) {
-            spaceRequired += NetlinkConstants.alignedLengthOf(
-                    StructNlAttr.NLA_HEADERLEN + mLinkLayerAddr.length);
-        }
-        // Currently we don't write messages with NDA_PROBES nor NDA_CACHEINFO
-        // attributes appended.  Fix later, if necessary.
-        return spaceRequired;
-    }
-
-    private static void packNlAttr(short nlType, byte[] nlValue, ByteBuffer byteBuffer) {
-        final StructNlAttr nlAttr = new StructNlAttr();
-        nlAttr.nla_type = nlType;
-        nlAttr.nla_value = nlValue;
-        nlAttr.nla_len = (short) (StructNlAttr.NLA_HEADERLEN + nlAttr.nla_value.length);
-        nlAttr.pack(byteBuffer);
-    }
-
-    public void pack(ByteBuffer byteBuffer) {
-        getHeader().pack(byteBuffer) ;
-        mNdmsg.pack(byteBuffer);
-
-        if (mDestination != null) {
-            packNlAttr(NDA_DST, mDestination.getAddress(), byteBuffer);
-        }
-        if (mLinkLayerAddr != null) {
-            packNlAttr(NDA_LLADDR, mLinkLayerAddr, byteBuffer);
-        }
-    }
-
-    @Override
-    public String toString() {
-        final String ipLiteral = (mDestination == null) ? "" : mDestination.getHostAddress();
-        return "RtNetlinkNeighborMessage{ "
-                + "nlmsghdr{" + (mHeader == null ? "" : mHeader.toString()) + "}, "
-                + "ndmsg{" + (mNdmsg == null ? "" : mNdmsg.toString()) + "}, "
-                + "destination{" + ipLiteral + "} "
-                + "linklayeraddr{" + NetlinkConstants.hexify(mLinkLayerAddr) + "} "
-                + "probes{" + mNumProbes + "} "
-                + "cacheinfo{" + (mCacheInfo == null ? "" : mCacheInfo.toString()) + "} "
-                + "}";
-    }
-}
diff --git a/services/net/java/android/net/netlink/StructInetDiagMsg.java b/services/net/java/android/net/netlink/StructInetDiagMsg.java
deleted file mode 100644
index da824ad..0000000
--- a/services/net/java/android/net/netlink/StructInetDiagMsg.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.netlink;
-
-import static java.nio.ByteOrder.BIG_ENDIAN;
-import static android.system.OsConstants.AF_INET;
-import static android.system.OsConstants.AF_INET6;
-
-import java.net.Inet4Address;
-import java.net.InetSocketAddress;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import android.util.Log;
-
-/**
- * struct inet_diag_msg
- *
- * see &lt;linux_src&gt;/include/uapi/linux/inet_diag.h
- *
- * struct inet_diag_msg {
- *      __u8    idiag_family;
- *      __u8    idiag_state;
- *      __u8    idiag_timer;
- *      __u8    idiag_retrans;
- *      struct  inet_diag_sockid id;
- *      __u32   idiag_expires;
- *      __u32   idiag_rqueue;
- *      __u32   idiag_wqueue;
- *      __u32   idiag_uid;
- *      __u32   idiag_inode;
- * };
- *
- * @hide
- */
-public class StructInetDiagMsg {
-    public static final int STRUCT_SIZE = 4 + StructInetDiagSockId.STRUCT_SIZE + 20;
-    private static final int IDIAG_UID_OFFSET = StructNlMsgHdr.STRUCT_SIZE + 4 +
-            StructInetDiagSockId.STRUCT_SIZE + 12;
-    public int idiag_uid;
-
-    public static StructInetDiagMsg parse(ByteBuffer byteBuffer) {
-        StructInetDiagMsg struct = new StructInetDiagMsg();
-        struct.idiag_uid = byteBuffer.getInt(IDIAG_UID_OFFSET);
-        return struct;
-    }
-
-    @Override
-    public String toString() {
-        return "StructInetDiagMsg{ "
-                + "idiag_uid{" + idiag_uid + "}, "
-                + "}";
-    }
-}
diff --git a/services/net/java/android/net/netlink/StructInetDiagReqV2.java b/services/net/java/android/net/netlink/StructInetDiagReqV2.java
deleted file mode 100644
index 2268113..0000000
--- a/services/net/java/android/net/netlink/StructInetDiagReqV2.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.netlink;
-
-import android.annotation.Nullable;
-
-import java.net.InetSocketAddress;
-import java.nio.ByteBuffer;
-
-/**
- * struct inet_diag_req_v2
- *
- * see &lt;linux_src&gt;/include/uapi/linux/inet_diag.h
- *
- *      struct inet_diag_req_v2 {
- *          __u8    sdiag_family;
- *          __u8    sdiag_protocol;
- *          __u8    idiag_ext;
- *          __u8    pad;
- *          __u32   idiag_states;
- *          struct  inet_diag_sockid id;
- *      };
- *
- * @hide
- */
-public class StructInetDiagReqV2 {
-    public static final int STRUCT_SIZE = 8 + StructInetDiagSockId.STRUCT_SIZE;
-
-    private final byte mSdiagFamily;
-    private final byte mSdiagProtocol;
-    private final byte mIdiagExt;
-    private final byte mPad;
-    private final StructInetDiagSockId mId;
-    private final int mState;
-    public static final int INET_DIAG_REQ_V2_ALL_STATES = (int) 0xffffffff;
-
-    public StructInetDiagReqV2(int protocol, InetSocketAddress local, InetSocketAddress remote,
-            int family) {
-        this(protocol, local, remote, family, 0 /* pad */, 0 /* extension */,
-                INET_DIAG_REQ_V2_ALL_STATES);
-    }
-
-    public StructInetDiagReqV2(int protocol, @Nullable InetSocketAddress local,
-            @Nullable InetSocketAddress remote, int family, int pad, int extension, int state)
-            throws NullPointerException {
-        mSdiagFamily = (byte) family;
-        mSdiagProtocol = (byte) protocol;
-        // Request for all sockets if no specific socket is requested. Specify the local and remote
-        // socket address information for target request socket.
-        if ((local == null) != (remote == null)) {
-            throw new NullPointerException("Local and remote must be both null or both non-null");
-        }
-        mId = ((local != null && remote != null) ? new StructInetDiagSockId(local, remote) : null);
-        mPad = (byte) pad;
-        mIdiagExt = (byte) extension;
-        mState = state;
-    }
-
-    public void pack(ByteBuffer byteBuffer) {
-        // The ByteOrder must have already been set by the caller.
-        byteBuffer.put((byte) mSdiagFamily);
-        byteBuffer.put((byte) mSdiagProtocol);
-        byteBuffer.put((byte) mIdiagExt);
-        byteBuffer.put((byte) mPad);
-        byteBuffer.putInt(mState);
-        if (mId != null) mId.pack(byteBuffer);
-    }
-
-    @Override
-    public String toString() {
-        final String familyStr = NetlinkConstants.stringForAddressFamily(mSdiagFamily);
-        final String protocolStr = NetlinkConstants.stringForAddressFamily(mSdiagProtocol);
-
-        return "StructInetDiagReqV2{ "
-                + "sdiag_family{" + familyStr + "}, "
-                + "sdiag_protocol{" + protocolStr + "}, "
-                + "idiag_ext{" + mIdiagExt + ")}, "
-                + "pad{" + mPad + "}, "
-                + "idiag_states{" + Integer.toHexString(mState) + "}, "
-                + ((mId != null) ? mId.toString() : "inet_diag_sockid=null")
-                + "}";
-    }
-}
diff --git a/services/net/java/android/net/netlink/StructInetDiagSockId.java b/services/net/java/android/net/netlink/StructInetDiagSockId.java
deleted file mode 100644
index 2e9fa25..0000000
--- a/services/net/java/android/net/netlink/StructInetDiagSockId.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.netlink;
-
-import static java.nio.ByteOrder.BIG_ENDIAN;
-
-import java.net.Inet4Address;
-import java.net.InetSocketAddress;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-
-/**
- * struct inet_diag_req_v2
- *
- * see &lt;linux_src&gt;/include/uapi/linux/inet_diag.h
- *
- * struct inet_diag_sockid {
- *        __be16    idiag_sport;
- *        __be16    idiag_dport;
- *        __be32    idiag_src[4];
- *        __be32    idiag_dst[4];
- *        __u32     idiag_if;
- *        __u32     idiag_cookie[2];
- * #define INET_DIAG_NOCOOKIE (~0U)
- * };
- *
- * @hide
- */
-public class StructInetDiagSockId {
-    public static final int STRUCT_SIZE = 48;
-
-    private final InetSocketAddress mLocSocketAddress;
-    private final InetSocketAddress mRemSocketAddress;
-    private final byte[] INET_DIAG_NOCOOKIE = new byte[]{
-            (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
-            (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff};
-    private final byte[] IPV4_PADDING = new byte[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
-
-    public StructInetDiagSockId(InetSocketAddress loc, InetSocketAddress rem) {
-        mLocSocketAddress = loc;
-        mRemSocketAddress = rem;
-    }
-
-    public void pack(ByteBuffer byteBuffer) {
-        byteBuffer.order(BIG_ENDIAN);
-        byteBuffer.putShort((short) mLocSocketAddress.getPort());
-        byteBuffer.putShort((short) mRemSocketAddress.getPort());
-        byteBuffer.put(mLocSocketAddress.getAddress().getAddress());
-        if (mLocSocketAddress.getAddress() instanceof Inet4Address) {
-            byteBuffer.put(IPV4_PADDING);
-        }
-        byteBuffer.put(mRemSocketAddress.getAddress().getAddress());
-        if (mRemSocketAddress.getAddress() instanceof Inet4Address) {
-            byteBuffer.put(IPV4_PADDING);
-        }
-        byteBuffer.order(ByteOrder.nativeOrder());
-        byteBuffer.putInt(0);
-        byteBuffer.put(INET_DIAG_NOCOOKIE);
-    }
-
-    @Override
-    public String toString() {
-        return "StructInetDiagSockId{ "
-                + "idiag_sport{" + mLocSocketAddress.getPort() + "}, "
-                + "idiag_dport{" + mRemSocketAddress.getPort() + "}, "
-                + "idiag_src{" + mLocSocketAddress.getAddress().getHostAddress() + "}, "
-                + "idiag_dst{" + mRemSocketAddress.getAddress().getHostAddress() + "}, "
-                + "idiag_if{" + 0 + "} "
-                + "idiag_cookie{INET_DIAG_NOCOOKIE}"
-                + "}";
-    }
-}
diff --git a/services/net/java/android/net/netlink/StructNdMsg.java b/services/net/java/android/net/netlink/StructNdMsg.java
deleted file mode 100644
index e34ec39..0000000
--- a/services/net/java/android/net/netlink/StructNdMsg.java
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.netlink;
-
-import android.net.netlink.NetlinkConstants;
-import android.system.OsConstants;
-import java.nio.ByteBuffer;
-
-
-/**
- * struct ndmsg
- *
- * see: &lt;linux_src&gt;/include/uapi/linux/neighbour.h
- *
- * @hide
- */
-public class StructNdMsg {
-    // Already aligned.
-    public static final int STRUCT_SIZE = 12;
-
-    // Neighbor Cache Entry States
-    public static final short NUD_NONE        = 0x00;
-    public static final short NUD_INCOMPLETE  = 0x01;
-    public static final short NUD_REACHABLE   = 0x02;
-    public static final short NUD_STALE       = 0x04;
-    public static final short NUD_DELAY       = 0x08;
-    public static final short NUD_PROBE       = 0x10;
-    public static final short NUD_FAILED      = 0x20;
-    public static final short NUD_NOARP       = 0x40;
-    public static final short NUD_PERMANENT   = 0x80;
-
-    public static String stringForNudState(short nudState) {
-        switch (nudState) {
-            case NUD_NONE: return "NUD_NONE";
-            case NUD_INCOMPLETE: return "NUD_INCOMPLETE";
-            case NUD_REACHABLE: return "NUD_REACHABLE";
-            case NUD_STALE: return "NUD_STALE";
-            case NUD_DELAY: return "NUD_DELAY";
-            case NUD_PROBE: return "NUD_PROBE";
-            case NUD_FAILED: return "NUD_FAILED";
-            case NUD_NOARP: return "NUD_NOARP";
-            case NUD_PERMANENT: return "NUD_PERMANENT";
-            default:
-                return "unknown NUD state: " + String.valueOf(nudState);
-        }
-    }
-
-    public static boolean isNudStateConnected(short nudState) {
-        return ((nudState & (NUD_PERMANENT|NUD_NOARP|NUD_REACHABLE)) != 0);
-    }
-
-    public static boolean isNudStateValid(short nudState) {
-        return (isNudStateConnected(nudState) ||
-                ((nudState & (NUD_PROBE|NUD_STALE|NUD_DELAY)) != 0));
-    }
-
-    // Neighbor Cache Entry Flags
-    public static byte NTF_USE       = (byte) 0x01;
-    public static byte NTF_SELF      = (byte) 0x02;
-    public static byte NTF_MASTER    = (byte) 0x04;
-    public static byte NTF_PROXY     = (byte) 0x08;
-    public static byte NTF_ROUTER    = (byte) 0x80;
-
-    public static String stringForNudFlags(byte flags) {
-        final StringBuilder sb = new StringBuilder();
-        if ((flags & NTF_USE) != 0) {
-            sb.append("NTF_USE");
-        }
-        if ((flags & NTF_SELF) != 0) {
-            if (sb.length() > 0) { sb.append("|"); }
-            sb.append("NTF_SELF");
-        }
-        if ((flags & NTF_MASTER) != 0) {
-            if (sb.length() > 0) { sb.append("|"); }
-            sb.append("NTF_MASTER");
-        }
-        if ((flags & NTF_PROXY) != 0) {
-            if (sb.length() > 0) { sb.append("|");
-        }
-            sb.append("NTF_PROXY"); }
-        if ((flags & NTF_ROUTER) != 0) {
-            if (sb.length() > 0) { sb.append("|"); }
-            sb.append("NTF_ROUTER");
-        }
-        return sb.toString();
-    }
-
-    private static boolean hasAvailableSpace(ByteBuffer byteBuffer) {
-        return byteBuffer != null && byteBuffer.remaining() >= STRUCT_SIZE;
-    }
-
-    public static StructNdMsg parse(ByteBuffer byteBuffer) {
-        if (!hasAvailableSpace(byteBuffer)) { return null; }
-
-        // The ByteOrder must have already been set by the caller.  In most
-        // cases ByteOrder.nativeOrder() is correct, with the possible
-        // exception of usage within unittests.
-        final StructNdMsg struct = new StructNdMsg();
-        struct.ndm_family = byteBuffer.get();
-        final byte pad1 = byteBuffer.get();
-        final short pad2 = byteBuffer.getShort();
-        struct.ndm_ifindex = byteBuffer.getInt();
-        struct.ndm_state = byteBuffer.getShort();
-        struct.ndm_flags = byteBuffer.get();
-        struct.ndm_type = byteBuffer.get();
-        return struct;
-    }
-
-    public byte ndm_family;
-    public int ndm_ifindex;
-    public short ndm_state;
-    public byte ndm_flags;
-    public byte ndm_type;
-
-    public StructNdMsg() {
-        ndm_family = (byte) OsConstants.AF_UNSPEC;
-    }
-
-    public void pack(ByteBuffer byteBuffer) {
-        // The ByteOrder must have already been set by the caller.  In most
-        // cases ByteOrder.nativeOrder() is correct, with the exception
-        // of usage within unittests.
-        byteBuffer.put(ndm_family);
-        byteBuffer.put((byte) 0);         // pad1
-        byteBuffer.putShort((short) 0);   // pad2
-        byteBuffer.putInt(ndm_ifindex);
-        byteBuffer.putShort(ndm_state);
-        byteBuffer.put(ndm_flags);
-        byteBuffer.put(ndm_type);
-    }
-
-    public boolean nudConnected() {
-        return isNudStateConnected(ndm_state);
-    }
-
-    public boolean nudValid() {
-        return isNudStateValid(ndm_state);
-    }
-
-    @Override
-    public String toString() {
-        final String stateStr = "" + ndm_state + " (" + stringForNudState(ndm_state) + ")";
-        final String flagsStr = "" + ndm_flags + " (" + stringForNudFlags(ndm_flags) + ")";
-        return "StructNdMsg{ "
-                + "family{" + NetlinkConstants.stringForAddressFamily((int) ndm_family) + "}, "
-                + "ifindex{" + ndm_ifindex + "}, "
-                + "state{" + stateStr + "}, "
-                + "flags{" + flagsStr + "}, "
-                + "type{" + ndm_type + "} "
-                + "}";
-    }
-}
diff --git a/services/net/java/android/net/netlink/StructNdaCacheInfo.java b/services/net/java/android/net/netlink/StructNdaCacheInfo.java
deleted file mode 100644
index 16cf563..0000000
--- a/services/net/java/android/net/netlink/StructNdaCacheInfo.java
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.netlink;
-
-import android.system.Os;
-import android.system.OsConstants;
-
-import java.nio.ByteBuffer;
-
-
-/**
- * struct nda_cacheinfo
- *
- * see: &lt;linux_src&gt;/include/uapi/linux/neighbour.h
- *
- * @hide
- */
-public class StructNdaCacheInfo {
-    // Already aligned.
-    public static final int STRUCT_SIZE = 16;
-
-    private static boolean hasAvailableSpace(ByteBuffer byteBuffer) {
-        return byteBuffer != null && byteBuffer.remaining() >= STRUCT_SIZE;
-    }
-
-    public static StructNdaCacheInfo parse(ByteBuffer byteBuffer) {
-        if (!hasAvailableSpace(byteBuffer)) { return null; }
-
-        // The ByteOrder must have already been set by the caller.  In most
-        // cases ByteOrder.nativeOrder() is correct, with the possible
-        // exception of usage within unittests.
-        final StructNdaCacheInfo struct = new StructNdaCacheInfo();
-        struct.ndm_used = byteBuffer.getInt();
-        struct.ndm_confirmed = byteBuffer.getInt();
-        struct.ndm_updated = byteBuffer.getInt();
-        struct.ndm_refcnt = byteBuffer.getInt();
-        return struct;
-    }
-
-    // TODO: investigate whether this can change during device runtime and
-    // decide what (if anything) should be done about that.
-    private static final long CLOCK_TICKS_PER_SECOND = Os.sysconf(OsConstants._SC_CLK_TCK);
-
-    private static long ticksToMilliSeconds(int intClockTicks) {
-        final long longClockTicks = (long) intClockTicks & 0xffffffff;
-        return (longClockTicks * 1000) / CLOCK_TICKS_PER_SECOND;
-    }
-
-    /**
-     * Explanatory notes, for reference.
-     *
-     * Before being returned to user space, the neighbor entry times are
-     * converted to clock_t's like so:
-     *
-     *     ndm_used      = jiffies_to_clock_t(now - neigh->used);
-     *     ndm_confirmed = jiffies_to_clock_t(now - neigh->confirmed);
-     *     ndm_updated   = jiffies_to_clock_t(now - neigh->updated);
-     *
-     * meaning that these values are expressed as "clock ticks ago".  To
-     * convert these clock ticks to seconds divide by sysconf(_SC_CLK_TCK).
-     * When _SC_CLK_TCK is 100, for example, the ndm_* times are expressed
-     * in centiseconds.
-     *
-     * These values are unsigned, but fortunately being expressed as "some
-     * clock ticks ago", these values are typically very small (and 
-     * 2^31 centiseconds = 248 days).
-     *
-     * By observation, it appears that:
-     *     ndm_used: the last time ARP/ND took place for this neighbor
-     *     ndm_confirmed: the last time ARP/ND succeeded for this neighbor OR
-     *                    higher layer confirmation (TCP or MSG_CONFIRM)
-     *                    was received
-     *     ndm_updated: the time when the current NUD state was entered
-     */
-    public int ndm_used;
-    public int ndm_confirmed;
-    public int ndm_updated;
-    public int ndm_refcnt;
-
-    public StructNdaCacheInfo() {}
-
-    public long lastUsed() {
-        return ticksToMilliSeconds(ndm_used);
-    }
-
-    public long lastConfirmed() {
-        return ticksToMilliSeconds(ndm_confirmed);
-    }
-
-    public long lastUpdated() {
-        return ticksToMilliSeconds(ndm_updated);
-    }
-
-    @Override
-    public String toString() {
-        return "NdaCacheInfo{ "
-                + "ndm_used{" + lastUsed() + "}, "
-                + "ndm_confirmed{" + lastConfirmed() + "}, "
-                + "ndm_updated{" + lastUpdated() + "}, "
-                + "ndm_refcnt{" + ndm_refcnt + "} "
-                + "}";
-    }
-}
diff --git a/services/net/java/android/net/netlink/StructNfGenMsg.java b/services/net/java/android/net/netlink/StructNfGenMsg.java
deleted file mode 100644
index 8155977..0000000
--- a/services/net/java/android/net/netlink/StructNfGenMsg.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.netlink;
-
-import java.nio.ByteBuffer;
-
-
-/**
- * struct nfgenmsg
- *
- * see &lt;linux_src&gt;/include/uapi/linux/netfilter/nfnetlink.h
- *
- * @hide
- */
-public class StructNfGenMsg {
-    public static final int STRUCT_SIZE = 2 + Short.BYTES;
-
-    public static final int NFNETLINK_V0 = 0;
-
-    final public byte nfgen_family;
-    final public byte version;
-    final public short res_id;  // N.B.: this is big endian in the kernel
-
-    public StructNfGenMsg(byte family) {
-        nfgen_family = family;
-        version = (byte) NFNETLINK_V0;
-        res_id = (short) 0;
-    }
-
-    public void pack(ByteBuffer byteBuffer) {
-        byteBuffer.put(nfgen_family);
-        byteBuffer.put(version);
-        byteBuffer.putShort(res_id);
-    }
-}
diff --git a/services/net/java/android/net/netlink/StructNlAttr.java b/services/net/java/android/net/netlink/StructNlAttr.java
deleted file mode 100644
index 28a4e88..0000000
--- a/services/net/java/android/net/netlink/StructNlAttr.java
+++ /dev/null
@@ -1,210 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.netlink;
-
-import android.net.netlink.NetlinkConstants;
-
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-import java.nio.ByteOrder;
-import java.nio.ByteBuffer;
-
-
-/**
- * struct nlattr
- *
- * see: &lt;linux_src&gt;/include/uapi/linux/netlink.h
- *
- * @hide
- */
-public class StructNlAttr {
-    // Already aligned.
-    public static final int NLA_HEADERLEN  = 4;
-    public static final int NLA_F_NESTED   = (1 << 15);
-
-    public static short makeNestedType(short type) {
-        return (short) (type | NLA_F_NESTED);
-    }
-
-    // Return a (length, type) object only, without consuming any bytes in
-    // |byteBuffer| and without copying or interpreting any value bytes.
-    // This is used for scanning over a packed set of struct nlattr's,
-    // looking for instances of a particular type.
-    public static StructNlAttr peek(ByteBuffer byteBuffer) {
-        if (byteBuffer == null || byteBuffer.remaining() < NLA_HEADERLEN) {
-            return null;
-        }
-        final int baseOffset = byteBuffer.position();
-
-        // Assume the byte order of the buffer is the expected byte order of the value.
-        final StructNlAttr struct = new StructNlAttr(byteBuffer.order());
-        // The byte order of nla_len and nla_type is always native.
-        final ByteOrder originalOrder = byteBuffer.order();
-        byteBuffer.order(ByteOrder.nativeOrder());
-        try {
-            struct.nla_len = byteBuffer.getShort();
-            struct.nla_type = byteBuffer.getShort();
-        } finally {
-            byteBuffer.order(originalOrder);
-        }
-
-        byteBuffer.position(baseOffset);
-        if (struct.nla_len < NLA_HEADERLEN) {
-            // Malformed.
-            return null;
-        }
-        return struct;
-    }
-
-    public static StructNlAttr parse(ByteBuffer byteBuffer) {
-        final StructNlAttr struct = peek(byteBuffer);
-        if (struct == null || byteBuffer.remaining() < struct.getAlignedLength()) {
-            return null;
-        }
-
-        final int baseOffset = byteBuffer.position();
-        byteBuffer.position(baseOffset + NLA_HEADERLEN);
-
-        int valueLen = ((int) struct.nla_len) & 0xffff;
-        valueLen -= NLA_HEADERLEN;
-        if (valueLen > 0) {
-            struct.nla_value = new byte[valueLen];
-            byteBuffer.get(struct.nla_value, 0, valueLen);
-            byteBuffer.position(baseOffset + struct.getAlignedLength());
-        }
-        return struct;
-    }
-
-    public short nla_len = (short) NLA_HEADERLEN;
-    public short nla_type;
-    public byte[] nla_value;
-
-    // The byte order used to read/write the value member. Netlink length and
-    // type members are always read/written in native order.
-    private ByteOrder mByteOrder = ByteOrder.nativeOrder();
-
-    public StructNlAttr() {}
-
-    public StructNlAttr(ByteOrder byteOrder) {
-        mByteOrder = byteOrder;
-    }
-
-    public StructNlAttr(short type, byte value) {
-        nla_type = type;
-        setValue(new byte[1]);
-        nla_value[0] = value;
-    }
-
-    public StructNlAttr(short type, short value) {
-        this(type, value, ByteOrder.nativeOrder());
-    }
-
-    public StructNlAttr(short type, short value, ByteOrder order) {
-        this(order);
-        nla_type = type;
-        setValue(new byte[Short.BYTES]);
-        getValueAsByteBuffer().putShort(value);
-    }
-
-    public StructNlAttr(short type, int value) {
-        this(type, value, ByteOrder.nativeOrder());
-    }
-
-    public StructNlAttr(short type, int value, ByteOrder order) {
-        this(order);
-        nla_type = type;
-        setValue(new byte[Integer.BYTES]);
-        getValueAsByteBuffer().putInt(value);
-    }
-
-    public StructNlAttr(short type, InetAddress ip) {
-        nla_type = type;
-        setValue(ip.getAddress());
-    }
-
-    public StructNlAttr(short type, StructNlAttr... nested) {
-        this();
-        nla_type = makeNestedType(type);
-
-        int payloadLength = 0;
-        for (StructNlAttr nla : nested) payloadLength += nla.getAlignedLength();
-        setValue(new byte[payloadLength]);
-
-        final ByteBuffer buf = getValueAsByteBuffer();
-        for (StructNlAttr nla : nested) {
-            nla.pack(buf);
-        }
-    }
-
-    public int getAlignedLength() {
-        return NetlinkConstants.alignedLengthOf(nla_len);
-    }
-
-    public ByteBuffer getValueAsByteBuffer() {
-        if (nla_value == null) { return null; }
-        final ByteBuffer byteBuffer = ByteBuffer.wrap(nla_value);
-        byteBuffer.order(mByteOrder);
-        return byteBuffer;
-    }
-
-    public int getValueAsInt(int defaultValue) {
-        final ByteBuffer byteBuffer = getValueAsByteBuffer();
-        if (byteBuffer == null || byteBuffer.remaining() != Integer.BYTES) {
-            return defaultValue;
-        }
-        return getValueAsByteBuffer().getInt();
-    }
-
-    public InetAddress getValueAsInetAddress() {
-        if (nla_value == null) { return null; }
-
-        try {
-            return InetAddress.getByAddress(nla_value);
-        } catch (UnknownHostException ignored) {
-            return null;
-        }
-    }
-
-    public void pack(ByteBuffer byteBuffer) {
-        final ByteOrder originalOrder = byteBuffer.order();
-        final int originalPosition = byteBuffer.position();
-
-        byteBuffer.order(ByteOrder.nativeOrder());
-        try {
-            byteBuffer.putShort(nla_len);
-            byteBuffer.putShort(nla_type);
-            if (nla_value != null) byteBuffer.put(nla_value);
-        } finally {
-            byteBuffer.order(originalOrder);
-        }
-        byteBuffer.position(originalPosition + getAlignedLength());
-    }
-
-    private void setValue(byte[] value) {
-        nla_value = value;
-        nla_len = (short) (NLA_HEADERLEN + ((nla_value != null) ? nla_value.length : 0));
-    }
-
-    @Override
-    public String toString() {
-        return "StructNlAttr{ "
-                + "nla_len{" + nla_len + "}, "
-                + "nla_type{" + nla_type + "}, "
-                + "nla_value{" + NetlinkConstants.hexify(nla_value) + "}, "
-                + "}";
-    }
-}
diff --git a/services/net/java/android/net/netlink/StructNlMsgErr.java b/services/net/java/android/net/netlink/StructNlMsgErr.java
deleted file mode 100644
index 6fcc6e69d..0000000
--- a/services/net/java/android/net/netlink/StructNlMsgErr.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.netlink;
-
-import android.net.netlink.NetlinkConstants;
-import android.net.netlink.StructNlMsgHdr;
-
-import java.nio.ByteBuffer;
-
-
-/**
- * struct nlmsgerr
- *
- * see &lt;linux_src&gt;/include/uapi/linux/netlink.h
- *
- * @hide
- */
-public class StructNlMsgErr {
-    public static final int STRUCT_SIZE = Integer.BYTES + StructNlMsgHdr.STRUCT_SIZE;
-
-    public static boolean hasAvailableSpace(ByteBuffer byteBuffer) {
-        return byteBuffer != null && byteBuffer.remaining() >= STRUCT_SIZE;
-    }
-
-    public static StructNlMsgErr parse(ByteBuffer byteBuffer) {
-        if (!hasAvailableSpace(byteBuffer)) { return null; }
-
-        // The ByteOrder must have already been set by the caller.  In most
-        // cases ByteOrder.nativeOrder() is correct, with the exception
-        // of usage within unittests.
-        final StructNlMsgErr struct = new StructNlMsgErr();
-        struct.error = byteBuffer.getInt();
-        struct.msg = StructNlMsgHdr.parse(byteBuffer);
-        return struct;
-    }
-
-    public int error;
-    public StructNlMsgHdr msg;
-
-    public void pack(ByteBuffer byteBuffer) {
-        // The ByteOrder must have already been set by the caller.  In most
-        // cases ByteOrder.nativeOrder() is correct, with the possible
-        // exception of usage within unittests.
-        byteBuffer.putInt(error);
-        if (msg != null) {
-            msg.pack(byteBuffer);
-        }
-    }
-
-    @Override
-    public String toString() {
-        return "StructNlMsgErr{ "
-                + "error{" + error + "}, "
-                + "msg{" + (msg == null ? "" : msg.toString()) + "} "
-                + "}";
-    }
-}
diff --git a/services/net/java/android/net/netlink/StructNlMsgHdr.java b/services/net/java/android/net/netlink/StructNlMsgHdr.java
deleted file mode 100644
index 98ab5e7..0000000
--- a/services/net/java/android/net/netlink/StructNlMsgHdr.java
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.netlink;
-
-import android.net.netlink.NetlinkConstants;
-import java.nio.ByteBuffer;
-
-
-/**
- * struct nlmsghdr
- *
- * see &lt;linux_src&gt;/include/uapi/linux/netlink.h
- *
- * @hide
- */
-public class StructNlMsgHdr {
-    // Already aligned.
-    public static final int STRUCT_SIZE = 16;
-
-    public static final short NLM_F_REQUEST = 0x0001;
-    public static final short NLM_F_MULTI   = 0x0002;
-    public static final short NLM_F_ACK     = 0x0004;
-    public static final short NLM_F_ECHO    = 0x0008;
-    // Flags for a GET request.
-    public static final short NLM_F_ROOT    = 0x0100;
-    public static final short NLM_F_MATCH   = 0x0200;
-    public static final short NLM_F_DUMP    = NLM_F_ROOT|NLM_F_MATCH;
-    // Flags for a NEW request.
-    public static final short NLM_F_REPLACE   = 0x100;
-    public static final short NLM_F_EXCL      = 0x200;
-    public static final short NLM_F_CREATE    = 0x400;
-    public static final short NLM_F_APPEND    = 0x800;
-
-
-    public static String stringForNlMsgFlags(short flags) {
-        final StringBuilder sb = new StringBuilder();
-        if ((flags & NLM_F_REQUEST) != 0) {
-            sb.append("NLM_F_REQUEST");
-        }
-        if ((flags & NLM_F_MULTI) != 0) {
-            if (sb.length() > 0) { sb.append("|"); }
-            sb.append("NLM_F_MULTI");
-        }
-        if ((flags & NLM_F_ACK) != 0) {
-            if (sb.length() > 0) { sb.append("|"); }
-            sb.append("NLM_F_ACK");
-        }
-        if ((flags & NLM_F_ECHO) != 0) {
-            if (sb.length() > 0) { sb.append("|"); }
-            sb.append("NLM_F_ECHO");
-        }
-        if ((flags & NLM_F_ROOT) != 0) {
-            if (sb.length() > 0) { sb.append("|"); }
-            sb.append("NLM_F_ROOT");
-        }
-        if ((flags & NLM_F_MATCH) != 0) {
-            if (sb.length() > 0) { sb.append("|"); }
-            sb.append("NLM_F_MATCH");
-        }
-        return sb.toString();
-    }
-
-    public static boolean hasAvailableSpace(ByteBuffer byteBuffer) {
-        return byteBuffer != null && byteBuffer.remaining() >= STRUCT_SIZE;
-    }
-
-    public static StructNlMsgHdr parse(ByteBuffer byteBuffer) {
-        if (!hasAvailableSpace(byteBuffer)) { return null; }
-
-        // The ByteOrder must have already been set by the caller.  In most
-        // cases ByteOrder.nativeOrder() is correct, with the exception
-        // of usage within unittests.
-        final StructNlMsgHdr struct = new StructNlMsgHdr();
-        struct.nlmsg_len = byteBuffer.getInt();
-        struct.nlmsg_type = byteBuffer.getShort();
-        struct.nlmsg_flags = byteBuffer.getShort();
-        struct.nlmsg_seq = byteBuffer.getInt();
-        struct.nlmsg_pid = byteBuffer.getInt();
-
-        if (struct.nlmsg_len < STRUCT_SIZE) {
-            // Malformed.
-            return null;
-        }
-        return struct;
-    }
-
-    public int nlmsg_len;
-    public short nlmsg_type;
-    public short nlmsg_flags;
-    public int nlmsg_seq;
-    public int nlmsg_pid;
-
-    public StructNlMsgHdr() {
-        nlmsg_len = 0;
-        nlmsg_type = 0;
-        nlmsg_flags = 0;
-        nlmsg_seq = 0;
-        nlmsg_pid = 0;
-    }
-
-    public void pack(ByteBuffer byteBuffer) {
-        // The ByteOrder must have already been set by the caller.  In most
-        // cases ByteOrder.nativeOrder() is correct, with the possible
-        // exception of usage within unittests.
-        byteBuffer.putInt(nlmsg_len);
-        byteBuffer.putShort(nlmsg_type);
-        byteBuffer.putShort(nlmsg_flags);
-        byteBuffer.putInt(nlmsg_seq);
-        byteBuffer.putInt(nlmsg_pid);
-    }
-
-    @Override
-    public String toString() {
-        final String typeStr = "" + nlmsg_type
-                + "(" + NetlinkConstants.stringForNlMsgType(nlmsg_type) + ")";
-        final String flagsStr = "" + nlmsg_flags
-                + "(" + stringForNlMsgFlags(nlmsg_flags) + ")";
-        return "StructNlMsgHdr{ "
-                + "nlmsg_len{" + nlmsg_len + "}, "
-                + "nlmsg_type{" + typeStr + "}, "
-                + "nlmsg_flags{" + flagsStr + ")}, "
-                + "nlmsg_seq{" + nlmsg_seq + "}, "
-                + "nlmsg_pid{" + nlmsg_pid + "} "
-                + "}";
-    }
-}
diff --git a/services/net/java/android/net/shared/InitialConfiguration.java b/services/net/java/android/net/shared/InitialConfiguration.java
deleted file mode 100644
index 007c8ca9..0000000
--- a/services/net/java/android/net/shared/InitialConfiguration.java
+++ /dev/null
@@ -1,240 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.shared;
-
-import static android.net.shared.ParcelableUtil.fromParcelableArray;
-import static android.net.shared.ParcelableUtil.toParcelableArray;
-import static android.text.TextUtils.join;
-
-import android.net.InetAddresses;
-import android.net.InitialConfigurationParcelable;
-import android.net.IpPrefix;
-import android.net.LinkAddress;
-import android.net.RouteInfo;
-
-import java.net.Inet4Address;
-import java.net.InetAddress;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-import java.util.function.Predicate;
-
-/** @hide */
-public class InitialConfiguration {
-    public final Set<LinkAddress> ipAddresses = new HashSet<>();
-    public final Set<IpPrefix> directlyConnectedRoutes = new HashSet<>();
-    public final Set<InetAddress> dnsServers = new HashSet<>();
-
-    private static final int RFC6177_MIN_PREFIX_LENGTH = 48;
-    private static final int RFC7421_PREFIX_LENGTH = 64;
-
-    public static final InetAddress INET6_ANY = InetAddresses.parseNumericAddress("::");
-
-    /**
-     * Create a InitialConfiguration that is a copy of the specified configuration.
-     */
-    public static InitialConfiguration copy(InitialConfiguration config) {
-        if (config == null) {
-            return null;
-        }
-        InitialConfiguration configCopy = new InitialConfiguration();
-        configCopy.ipAddresses.addAll(config.ipAddresses);
-        configCopy.directlyConnectedRoutes.addAll(config.directlyConnectedRoutes);
-        configCopy.dnsServers.addAll(config.dnsServers);
-        return configCopy;
-    }
-
-    @Override
-    public String toString() {
-        return String.format(
-                "InitialConfiguration(IPs: {%s}, prefixes: {%s}, DNS: {%s})",
-                join(", ", ipAddresses), join(", ", directlyConnectedRoutes),
-                join(", ", dnsServers));
-    }
-
-    /**
-     * Tests whether the contents of this IpConfiguration represent a valid configuration.
-     */
-    public boolean isValid() {
-        if (ipAddresses.isEmpty()) {
-            return false;
-        }
-
-        // For every IP address, there must be at least one prefix containing that address.
-        for (LinkAddress addr : ipAddresses) {
-            if (!any(directlyConnectedRoutes, (p) -> p.contains(addr.getAddress()))) {
-                return false;
-            }
-        }
-        // For every dns server, there must be at least one prefix containing that address.
-        for (InetAddress addr : dnsServers) {
-            if (!any(directlyConnectedRoutes, (p) -> p.contains(addr))) {
-                return false;
-            }
-        }
-        // All IPv6 LinkAddresses have an RFC7421-suitable prefix length
-        // (read: compliant with RFC4291#section2.5.4).
-        if (any(ipAddresses, not(InitialConfiguration::isPrefixLengthCompliant))) {
-            return false;
-        }
-        // If directlyConnectedRoutes contains an IPv6 default route
-        // then ipAddresses MUST contain at least one non-ULA GUA.
-        if (any(directlyConnectedRoutes, InitialConfiguration::isIPv6DefaultRoute)
-                && all(ipAddresses, not(InitialConfiguration::isIPv6GUA))) {
-            return false;
-        }
-        // The prefix length of routes in directlyConnectedRoutes be within reasonable
-        // bounds for IPv6: /48-/64 just as we’d accept in RIOs.
-        if (any(directlyConnectedRoutes, not(InitialConfiguration::isPrefixLengthCompliant))) {
-            return false;
-        }
-        // There no more than one IPv4 address
-        if (ipAddresses.stream().filter(InitialConfiguration::isIPv4).count() > 1) {
-            return false;
-        }
-
-        return true;
-    }
-
-    /**
-     * @return true if the given list of addressess and routes satisfies provisioning for this
-     * InitialConfiguration. LinkAddresses and RouteInfo objects are not compared with equality
-     * because addresses and routes seen by Netlink will contain additional fields like flags,
-     * interfaces, and so on. If this InitialConfiguration has no IP address specified, the
-     * provisioning check always fails.
-     *
-     * If the given list of routes is null, only addresses are taken into considerations.
-     */
-    public boolean isProvisionedBy(List<LinkAddress> addresses, List<RouteInfo> routes) {
-        if (ipAddresses.isEmpty()) {
-            return false;
-        }
-
-        for (LinkAddress addr : ipAddresses) {
-            if (!any(addresses, (addrSeen) -> addr.isSameAddressAs(addrSeen))) {
-                return false;
-            }
-        }
-
-        if (routes != null) {
-            for (IpPrefix prefix : directlyConnectedRoutes) {
-                if (!any(routes, (routeSeen) -> isDirectlyConnectedRoute(routeSeen, prefix))) {
-                    return false;
-                }
-            }
-        }
-
-        return true;
-    }
-
-    /**
-     * Convert this configuration to a {@link InitialConfigurationParcelable}.
-     */
-    public InitialConfigurationParcelable toStableParcelable() {
-        final InitialConfigurationParcelable p = new InitialConfigurationParcelable();
-        p.ipAddresses = ipAddresses.toArray(new LinkAddress[0]);
-        p.directlyConnectedRoutes = directlyConnectedRoutes.toArray(new IpPrefix[0]);
-        p.dnsServers = toParcelableArray(
-                dnsServers, IpConfigurationParcelableUtil::parcelAddress, String.class);
-        return p;
-    }
-
-    /**
-     * Create an instance of {@link InitialConfiguration} based on the contents of the specified
-     * {@link InitialConfigurationParcelable}.
-     */
-    public static InitialConfiguration fromStableParcelable(InitialConfigurationParcelable p) {
-        if (p == null) return null;
-        final InitialConfiguration config = new InitialConfiguration();
-        config.ipAddresses.addAll(Arrays.asList(p.ipAddresses));
-        config.directlyConnectedRoutes.addAll(Arrays.asList(p.directlyConnectedRoutes));
-        config.dnsServers.addAll(
-                fromParcelableArray(p.dnsServers, IpConfigurationParcelableUtil::unparcelAddress));
-        return config;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (!(obj instanceof InitialConfiguration)) return false;
-        final InitialConfiguration other = (InitialConfiguration) obj;
-        return ipAddresses.equals(other.ipAddresses)
-                && directlyConnectedRoutes.equals(other.directlyConnectedRoutes)
-                && dnsServers.equals(other.dnsServers);
-    }
-
-    private static boolean isDirectlyConnectedRoute(RouteInfo route, IpPrefix prefix) {
-        return !route.hasGateway() && prefix.equals(route.getDestination());
-    }
-
-    private static boolean isPrefixLengthCompliant(LinkAddress addr) {
-        return isIPv4(addr) || isCompliantIPv6PrefixLength(addr.getPrefixLength());
-    }
-
-    private static boolean isPrefixLengthCompliant(IpPrefix prefix) {
-        return isIPv4(prefix) || isCompliantIPv6PrefixLength(prefix.getPrefixLength());
-    }
-
-    private static boolean isCompliantIPv6PrefixLength(int prefixLength) {
-        return (RFC6177_MIN_PREFIX_LENGTH <= prefixLength)
-                && (prefixLength <= RFC7421_PREFIX_LENGTH);
-    }
-
-    private static boolean isIPv4(IpPrefix prefix) {
-        return prefix.getAddress() instanceof Inet4Address;
-    }
-
-    private static boolean isIPv4(LinkAddress addr) {
-        return addr.getAddress() instanceof Inet4Address;
-    }
-
-    private static boolean isIPv6DefaultRoute(IpPrefix prefix) {
-        return prefix.getAddress().equals(INET6_ANY);
-    }
-
-    private static boolean isIPv6GUA(LinkAddress addr) {
-        return addr.isIpv6() && addr.isGlobalPreferred();
-    }
-
-    // TODO: extract out into CollectionUtils.
-
-    /**
-     * Indicate whether any element of the specified iterable verifies the specified predicate.
-     */
-    public static <T> boolean any(Iterable<T> coll, Predicate<T> fn) {
-        for (T t : coll) {
-            if (fn.test(t)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    /**
-     * Indicate whether all elements of the specified iterable verifies the specified predicate.
-     */
-    public static <T> boolean all(Iterable<T> coll, Predicate<T> fn) {
-        return !any(coll, not(fn));
-    }
-
-    /**
-     * Create a predicate that returns the opposite value of the specified predicate.
-     */
-    public static <T> Predicate<T> not(Predicate<T> fn) {
-        return (t) -> !fn.test(t);
-    }
-}
diff --git a/services/net/java/android/net/shared/IpConfigurationParcelableUtil.java b/services/net/java/android/net/shared/IpConfigurationParcelableUtil.java
deleted file mode 100644
index 172dc24..0000000
--- a/services/net/java/android/net/shared/IpConfigurationParcelableUtil.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.shared;
-
-import android.annotation.Nullable;
-import android.net.DhcpResults;
-import android.net.DhcpResultsParcelable;
-import android.net.InetAddresses;
-
-import java.net.Inet4Address;
-import java.net.InetAddress;
-
-/**
- * Collection of utility methods to convert to and from stable AIDL parcelables for IpClient
- * configuration classes.
- * @hide
- */
-public final class IpConfigurationParcelableUtil {
-    /**
-     * Convert DhcpResults to a DhcpResultsParcelable.
-     */
-    public static DhcpResultsParcelable toStableParcelable(@Nullable DhcpResults results) {
-        if (results == null) return null;
-        final DhcpResultsParcelable p = new DhcpResultsParcelable();
-        p.baseConfiguration = results.toStaticIpConfiguration();
-        p.leaseDuration = results.leaseDuration;
-        p.mtu = results.mtu;
-        p.serverAddress = parcelAddress(results.serverAddress);
-        p.vendorInfo = results.vendorInfo;
-        p.serverHostName = results.serverHostName;
-        return p;
-    }
-
-    /**
-     * Convert a DhcpResultsParcelable to DhcpResults.
-     */
-    public static DhcpResults fromStableParcelable(@Nullable DhcpResultsParcelable p) {
-        if (p == null) return null;
-        final DhcpResults results = new DhcpResults(p.baseConfiguration);
-        results.leaseDuration = p.leaseDuration;
-        results.mtu = p.mtu;
-        results.serverAddress = (Inet4Address) unparcelAddress(p.serverAddress);
-        results.vendorInfo = p.vendorInfo;
-        results.serverHostName = p.serverHostName;
-        return results;
-    }
-
-    /**
-     * Convert InetAddress to String.
-     * TODO: have an InetAddressParcelable
-     */
-    public static String parcelAddress(@Nullable InetAddress addr) {
-        if (addr == null) return null;
-        return addr.getHostAddress();
-    }
-
-    /**
-     * Convert String to InetAddress.
-     * TODO: have an InetAddressParcelable
-     */
-    public static InetAddress unparcelAddress(@Nullable String addr) {
-        if (addr == null) return null;
-        return InetAddresses.parseNumericAddress(addr);
-    }
-}
diff --git a/services/net/java/android/net/shared/LinkPropertiesParcelableUtil.java b/services/net/java/android/net/shared/LinkPropertiesParcelableUtil.java
deleted file mode 100644
index 1729da6..0000000
--- a/services/net/java/android/net/shared/LinkPropertiesParcelableUtil.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.shared;
-
-import android.annotation.Nullable;
-import android.net.LinkProperties;
-import android.net.ProxyInfo;
-
-/**
- * Collection of utility methods to convert to and from stable AIDL parcelables for LinkProperties
- * and its attributes.
- * @hide
- */
-public final class LinkPropertiesParcelableUtil {
-    // Temporary methods to facilitate migrating clients away from LinkPropertiesParcelable
-    // TODO: remove the following methods after migrating clients.
-
-    /**
-     * @deprecated conversion to stable parcelable is no longer necessary.
-     */
-    @Deprecated
-    public static LinkProperties toStableParcelable(@Nullable LinkProperties lp) {
-        return lp;
-    }
-
-    /**
-     * @deprecated conversion to stable parcelable is no longer necessary.
-     */
-    @Deprecated
-    public static ProxyInfo toStableParcelable(@Nullable ProxyInfo info) {
-        return info;
-    }
-}
diff --git a/services/net/java/android/net/shared/NetworkMonitorUtils.java b/services/net/java/android/net/shared/NetworkMonitorUtils.java
deleted file mode 100644
index 46e9c73..0000000
--- a/services/net/java/android/net/shared/NetworkMonitorUtils.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.shared;
-
-import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
-import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
-import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN;
-import static android.net.NetworkCapabilities.NET_CAPABILITY_TRUSTED;
-
-import android.net.NetworkCapabilities;
-
-/** @hide */
-public class NetworkMonitorUtils {
-
-    // Network conditions broadcast constants
-    public static final String ACTION_NETWORK_CONDITIONS_MEASURED =
-            "android.net.conn.NETWORK_CONDITIONS_MEASURED";
-    public static final String EXTRA_CONNECTIVITY_TYPE = "extra_connectivity_type";
-    public static final String EXTRA_NETWORK_TYPE = "extra_network_type";
-    public static final String EXTRA_RESPONSE_RECEIVED = "extra_response_received";
-    public static final String EXTRA_IS_CAPTIVE_PORTAL = "extra_is_captive_portal";
-    public static final String EXTRA_CELL_ID = "extra_cellid";
-    public static final String EXTRA_SSID = "extra_ssid";
-    public static final String EXTRA_BSSID = "extra_bssid";
-    /** real time since boot */
-    public static final String EXTRA_REQUEST_TIMESTAMP_MS = "extra_request_timestamp_ms";
-    public static final String EXTRA_RESPONSE_TIMESTAMP_MS = "extra_response_timestamp_ms";
-    public static final String PERMISSION_ACCESS_NETWORK_CONDITIONS =
-            "android.permission.ACCESS_NETWORK_CONDITIONS";
-
-    /**
-     * Return whether validation is required for private DNS in strict mode.
-     * @param nc Network capabilities of the network to test.
-     */
-    public static boolean isPrivateDnsValidationRequired(NetworkCapabilities nc) {
-        // TODO: Consider requiring validation for DUN networks.
-        return nc != null
-                && nc.hasCapability(NET_CAPABILITY_INTERNET)
-                && nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)
-                && nc.hasCapability(NET_CAPABILITY_TRUSTED);
-    }
-
-    /**
-     * Return whether validation is required for a network.
-     * @param nc Network capabilities of the network to test.
-     */
-    public static boolean isValidationRequired(NetworkCapabilities nc) {
-        // TODO: Consider requiring validation for DUN networks.
-        return isPrivateDnsValidationRequired(nc) && nc.hasCapability(NET_CAPABILITY_NOT_VPN);
-    }
-}
diff --git a/services/net/java/android/net/shared/ParcelableUtil.java b/services/net/java/android/net/shared/ParcelableUtil.java
deleted file mode 100644
index 3f40300..0000000
--- a/services/net/java/android/net/shared/ParcelableUtil.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.shared;
-
-import android.annotation.NonNull;
-
-import java.lang.reflect.Array;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.function.Function;
-
-/**
- * Utility methods to help convert to/from stable parcelables.
- * @hide
- */
-public final class ParcelableUtil {
-    // Below methods could be implemented easily with streams, but streams are frowned upon in
-    // frameworks code.
-
-    /**
-     * Convert a list of BaseType items to an array of ParcelableType items using the specified
-     * converter function.
-     */
-    public static <ParcelableType, BaseType> ParcelableType[] toParcelableArray(
-            @NonNull Collection<BaseType> base,
-            @NonNull Function<BaseType, ParcelableType> conv,
-            @NonNull Class<ParcelableType> parcelClass) {
-        final ParcelableType[] out = (ParcelableType[]) Array.newInstance(parcelClass, base.size());
-        int i = 0;
-        for (BaseType b : base) {
-            out[i] = conv.apply(b);
-            i++;
-        }
-        return out;
-    }
-
-    /**
-     * Convert an array of ParcelableType items to a list of BaseType items using the specified
-     * converter function.
-     */
-    public static <ParcelableType, BaseType> ArrayList<BaseType> fromParcelableArray(
-            @NonNull ParcelableType[] parceled, @NonNull Function<ParcelableType, BaseType> conv) {
-        final ArrayList<BaseType> out = new ArrayList<>(parceled.length);
-        for (ParcelableType t : parceled) {
-            out.add(conv.apply(t));
-        }
-        return out;
-    }
-}
diff --git a/services/net/java/android/net/shared/PrivateDnsConfig.java b/services/net/java/android/net/shared/PrivateDnsConfig.java
deleted file mode 100644
index c7dc530..0000000
--- a/services/net/java/android/net/shared/PrivateDnsConfig.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.shared;
-
-import static android.net.shared.ParcelableUtil.fromParcelableArray;
-import static android.net.shared.ParcelableUtil.toParcelableArray;
-
-import android.net.PrivateDnsConfigParcel;
-import android.text.TextUtils;
-
-import java.net.InetAddress;
-import java.util.Arrays;
-
-/** @hide */
-public class PrivateDnsConfig {
-    public final boolean useTls;
-    public final String hostname;
-    public final InetAddress[] ips;
-
-    public PrivateDnsConfig() {
-        this(false);
-    }
-
-    public PrivateDnsConfig(boolean useTls) {
-        this.useTls = useTls;
-        this.hostname = "";
-        this.ips = new InetAddress[0];
-    }
-
-    public PrivateDnsConfig(String hostname, InetAddress[] ips) {
-        this.useTls = !TextUtils.isEmpty(hostname);
-        this.hostname = useTls ? hostname : "";
-        this.ips = (ips != null) ? ips : new InetAddress[0];
-    }
-
-    public PrivateDnsConfig(PrivateDnsConfig cfg) {
-        useTls = cfg.useTls;
-        hostname = cfg.hostname;
-        ips = cfg.ips;
-    }
-
-    /**
-     * Indicates whether this is a strict mode private DNS configuration.
-     */
-    public boolean inStrictMode() {
-        return useTls && !TextUtils.isEmpty(hostname);
-    }
-
-    @Override
-    public String toString() {
-        return PrivateDnsConfig.class.getSimpleName()
-                + "{" + useTls + ":" + hostname + "/" + Arrays.toString(ips) + "}";
-    }
-
-    /**
-     * Create a stable AIDL-compatible parcel from the current instance.
-     */
-    public PrivateDnsConfigParcel toParcel() {
-        final PrivateDnsConfigParcel parcel = new PrivateDnsConfigParcel();
-        parcel.hostname = hostname;
-        parcel.ips = toParcelableArray(
-                Arrays.asList(ips), IpConfigurationParcelableUtil::parcelAddress, String.class);
-
-        return parcel;
-    }
-
-    /**
-     * Build a configuration from a stable AIDL-compatible parcel.
-     */
-    public static PrivateDnsConfig fromParcel(PrivateDnsConfigParcel parcel) {
-        InetAddress[] ips = new InetAddress[parcel.ips.length];
-        ips = fromParcelableArray(parcel.ips, IpConfigurationParcelableUtil::unparcelAddress)
-                .toArray(ips);
-        return new PrivateDnsConfig(parcel.hostname, ips);
-    }
-}
diff --git a/services/net/java/android/net/shared/ProvisioningConfiguration.java b/services/net/java/android/net/shared/ProvisioningConfiguration.java
deleted file mode 100644
index 6f9c294..0000000
--- a/services/net/java/android/net/shared/ProvisioningConfiguration.java
+++ /dev/null
@@ -1,312 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.shared;
-
-import android.annotation.Nullable;
-import android.net.INetd;
-import android.net.Network;
-import android.net.ProvisioningConfigurationParcelable;
-import android.net.StaticIpConfiguration;
-import android.net.apf.ApfCapabilities;
-import android.net.ip.IIpClient;
-
-import java.util.Objects;
-import java.util.StringJoiner;
-
-/**
- * This class encapsulates parameters to be passed to
- * IpClient#startProvisioning(). A defensive copy is made by IpClient
- * and the values specified herein are in force until IpClient#stop()
- * is called.
- *
- * Example use:
- *
- *     final ProvisioningConfiguration config =
- *             new ProvisioningConfiguration.Builder()
- *                     .withPreDhcpAction()
- *                     .withProvisioningTimeoutMs(36 * 1000)
- *                     .build();
- *     mIpClient.startProvisioning(config.toStableParcelable());
- *     ...
- *     mIpClient.stop();
- *
- * The specified provisioning configuration will only be active until
- * IIpClient#stop() is called. Future calls to IIpClient#startProvisioning()
- * must specify the configuration again.
- * @hide
- */
-public class ProvisioningConfiguration {
-    // TODO: Delete this default timeout once those callers that care are
-    // fixed to pass in their preferred timeout.
-    //
-    // We pick 36 seconds so we can send DHCP requests at
-    //
-    //     t=0, t=2, t=6, t=14, t=30
-    //
-    // allowing for 10% jitter.
-    private static final int DEFAULT_TIMEOUT_MS = 36 * 1000;
-
-    /**
-     * Builder to create a {@link ProvisioningConfiguration}.
-     */
-    public static class Builder {
-        protected ProvisioningConfiguration mConfig = new ProvisioningConfiguration();
-
-        /**
-         * Specify that the configuration should not enable IPv4. It is enabled by default.
-         */
-        public Builder withoutIPv4() {
-            mConfig.mEnableIPv4 = false;
-            return this;
-        }
-
-        /**
-         * Specify that the configuration should not enable IPv6. It is enabled by default.
-         */
-        public Builder withoutIPv6() {
-            mConfig.mEnableIPv6 = false;
-            return this;
-        }
-
-        /**
-         * Specify that the configuration should not use a MultinetworkPolicyTracker. It is used
-         * by default.
-         */
-        public Builder withoutMultinetworkPolicyTracker() {
-            mConfig.mUsingMultinetworkPolicyTracker = false;
-            return this;
-        }
-
-        /**
-         * Specify that the configuration should not use a IpReachabilityMonitor. It is used by
-         * default.
-         */
-        public Builder withoutIpReachabilityMonitor() {
-            mConfig.mUsingIpReachabilityMonitor = false;
-            return this;
-        }
-
-        /**
-         * Identical to {@link #withPreDhcpAction(int)}, using a default timeout.
-         * @see #withPreDhcpAction(int)
-         */
-        public Builder withPreDhcpAction() {
-            mConfig.mRequestedPreDhcpActionMs = DEFAULT_TIMEOUT_MS;
-            return this;
-        }
-
-        /**
-         * Specify that {@link IpClientCallbacks#onPreDhcpAction()} should be called. Clients must
-         * call {@link IIpClient#completedPreDhcpAction()} when the callback called. This behavior
-         * is disabled by default.
-         * @param dhcpActionTimeoutMs Timeout for clients to call completedPreDhcpAction().
-         */
-        public Builder withPreDhcpAction(int dhcpActionTimeoutMs) {
-            mConfig.mRequestedPreDhcpActionMs = dhcpActionTimeoutMs;
-            return this;
-        }
-
-        /**
-         * Specify the initial provisioning configuration.
-         */
-        public Builder withInitialConfiguration(InitialConfiguration initialConfig) {
-            mConfig.mInitialConfig = initialConfig;
-            return this;
-        }
-
-        /**
-         * Specify a static configuration for provisioning.
-         */
-        public Builder withStaticConfiguration(StaticIpConfiguration staticConfig) {
-            mConfig.mStaticIpConfig = staticConfig;
-            return this;
-        }
-
-        /**
-         * Specify ApfCapabilities.
-         */
-        public Builder withApfCapabilities(ApfCapabilities apfCapabilities) {
-            mConfig.mApfCapabilities = apfCapabilities;
-            return this;
-        }
-
-        /**
-         * Specify the timeout to use for provisioning.
-         */
-        public Builder withProvisioningTimeoutMs(int timeoutMs) {
-            mConfig.mProvisioningTimeoutMs = timeoutMs;
-            return this;
-        }
-
-        /**
-         * Specify that IPv6 address generation should use a random MAC address.
-         */
-        public Builder withRandomMacAddress() {
-            mConfig.mIPv6AddrGenMode = INetd.IPV6_ADDR_GEN_MODE_EUI64;
-            return this;
-        }
-
-        /**
-         * Specify that IPv6 address generation should use a stable MAC address.
-         */
-        public Builder withStableMacAddress() {
-            mConfig.mIPv6AddrGenMode = INetd.IPV6_ADDR_GEN_MODE_STABLE_PRIVACY;
-            return this;
-        }
-
-        /**
-         * Specify the network to use for provisioning.
-         */
-        public Builder withNetwork(Network network) {
-            mConfig.mNetwork = network;
-            return this;
-        }
-
-        /**
-         * Specify the display name that the IpClient should use.
-         */
-        public Builder withDisplayName(String displayName) {
-            mConfig.mDisplayName = displayName;
-            return this;
-        }
-
-        /**
-         * Build the configuration using previously specified parameters.
-         */
-        public ProvisioningConfiguration build() {
-            return new ProvisioningConfiguration(mConfig);
-        }
-    }
-
-    public boolean mEnableIPv4 = true;
-    public boolean mEnableIPv6 = true;
-    public boolean mUsingMultinetworkPolicyTracker = true;
-    public boolean mUsingIpReachabilityMonitor = true;
-    public int mRequestedPreDhcpActionMs;
-    public InitialConfiguration mInitialConfig;
-    public StaticIpConfiguration mStaticIpConfig;
-    public ApfCapabilities mApfCapabilities;
-    public int mProvisioningTimeoutMs = DEFAULT_TIMEOUT_MS;
-    public int mIPv6AddrGenMode = INetd.IPV6_ADDR_GEN_MODE_STABLE_PRIVACY;
-    public Network mNetwork = null;
-    public String mDisplayName = null;
-
-    public ProvisioningConfiguration() {} // used by Builder
-
-    public ProvisioningConfiguration(ProvisioningConfiguration other) {
-        mEnableIPv4 = other.mEnableIPv4;
-        mEnableIPv6 = other.mEnableIPv6;
-        mUsingMultinetworkPolicyTracker = other.mUsingMultinetworkPolicyTracker;
-        mUsingIpReachabilityMonitor = other.mUsingIpReachabilityMonitor;
-        mRequestedPreDhcpActionMs = other.mRequestedPreDhcpActionMs;
-        mInitialConfig = InitialConfiguration.copy(other.mInitialConfig);
-        mStaticIpConfig = other.mStaticIpConfig == null
-                ? null
-                : new StaticIpConfiguration(other.mStaticIpConfig);
-        mApfCapabilities = other.mApfCapabilities;
-        mProvisioningTimeoutMs = other.mProvisioningTimeoutMs;
-        mIPv6AddrGenMode = other.mIPv6AddrGenMode;
-        mNetwork = other.mNetwork;
-        mDisplayName = other.mDisplayName;
-    }
-
-    /**
-     * Create a ProvisioningConfigurationParcelable from this ProvisioningConfiguration.
-     */
-    public ProvisioningConfigurationParcelable toStableParcelable() {
-        final ProvisioningConfigurationParcelable p = new ProvisioningConfigurationParcelable();
-        p.enableIPv4 = mEnableIPv4;
-        p.enableIPv6 = mEnableIPv6;
-        p.usingMultinetworkPolicyTracker = mUsingMultinetworkPolicyTracker;
-        p.usingIpReachabilityMonitor = mUsingIpReachabilityMonitor;
-        p.requestedPreDhcpActionMs = mRequestedPreDhcpActionMs;
-        p.initialConfig = mInitialConfig == null ? null : mInitialConfig.toStableParcelable();
-        p.staticIpConfig = mStaticIpConfig == null
-                ? null
-                : new StaticIpConfiguration(mStaticIpConfig);
-        p.apfCapabilities = mApfCapabilities; // ApfCapabilities is immutable
-        p.provisioningTimeoutMs = mProvisioningTimeoutMs;
-        p.ipv6AddrGenMode = mIPv6AddrGenMode;
-        p.network = mNetwork;
-        p.displayName = mDisplayName;
-        return p;
-    }
-
-    /**
-     * Create a ProvisioningConfiguration from a ProvisioningConfigurationParcelable.
-     */
-    public static ProvisioningConfiguration fromStableParcelable(
-            @Nullable ProvisioningConfigurationParcelable p) {
-        if (p == null) return null;
-        final ProvisioningConfiguration config = new ProvisioningConfiguration();
-        config.mEnableIPv4 = p.enableIPv4;
-        config.mEnableIPv6 = p.enableIPv6;
-        config.mUsingMultinetworkPolicyTracker = p.usingMultinetworkPolicyTracker;
-        config.mUsingIpReachabilityMonitor = p.usingIpReachabilityMonitor;
-        config.mRequestedPreDhcpActionMs = p.requestedPreDhcpActionMs;
-        config.mInitialConfig = InitialConfiguration.fromStableParcelable(p.initialConfig);
-        config.mStaticIpConfig = p.staticIpConfig == null
-                ? null
-                : new StaticIpConfiguration(p.staticIpConfig);
-        config.mApfCapabilities = p.apfCapabilities; // ApfCapabilities is immutable
-        config.mProvisioningTimeoutMs = p.provisioningTimeoutMs;
-        config.mIPv6AddrGenMode = p.ipv6AddrGenMode;
-        config.mNetwork = p.network;
-        config.mDisplayName = p.displayName;
-        return config;
-    }
-
-    @Override
-    public String toString() {
-        return new StringJoiner(", ", getClass().getSimpleName() + "{", "}")
-                .add("mEnableIPv4: " + mEnableIPv4)
-                .add("mEnableIPv6: " + mEnableIPv6)
-                .add("mUsingMultinetworkPolicyTracker: " + mUsingMultinetworkPolicyTracker)
-                .add("mUsingIpReachabilityMonitor: " + mUsingIpReachabilityMonitor)
-                .add("mRequestedPreDhcpActionMs: " + mRequestedPreDhcpActionMs)
-                .add("mInitialConfig: " + mInitialConfig)
-                .add("mStaticIpConfig: " + mStaticIpConfig)
-                .add("mApfCapabilities: " + mApfCapabilities)
-                .add("mProvisioningTimeoutMs: " + mProvisioningTimeoutMs)
-                .add("mIPv6AddrGenMode: " + mIPv6AddrGenMode)
-                .add("mNetwork: " + mNetwork)
-                .add("mDisplayName: " + mDisplayName)
-                .toString();
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (!(obj instanceof ProvisioningConfiguration)) return false;
-        final ProvisioningConfiguration other = (ProvisioningConfiguration) obj;
-        return mEnableIPv4 == other.mEnableIPv4
-                && mEnableIPv6 == other.mEnableIPv6
-                && mUsingMultinetworkPolicyTracker == other.mUsingMultinetworkPolicyTracker
-                && mUsingIpReachabilityMonitor == other.mUsingIpReachabilityMonitor
-                && mRequestedPreDhcpActionMs == other.mRequestedPreDhcpActionMs
-                && Objects.equals(mInitialConfig, other.mInitialConfig)
-                && Objects.equals(mStaticIpConfig, other.mStaticIpConfig)
-                && Objects.equals(mApfCapabilities, other.mApfCapabilities)
-                && mProvisioningTimeoutMs == other.mProvisioningTimeoutMs
-                && mIPv6AddrGenMode == other.mIPv6AddrGenMode
-                && Objects.equals(mNetwork, other.mNetwork)
-                && Objects.equals(mDisplayName, other.mDisplayName);
-    }
-
-    public boolean isValid() {
-        return (mInitialConfig == null) || mInitialConfig.isValid();
-    }
-}
diff --git a/services/net/java/android/net/util/InterfaceParams.java b/services/net/java/android/net/util/InterfaceParams.java
deleted file mode 100644
index f6bb873..0000000
--- a/services/net/java/android/net/util/InterfaceParams.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.util;
-
-import static com.android.internal.util.Preconditions.checkArgument;
-
-import android.net.MacAddress;
-import android.text.TextUtils;
-
-import java.net.NetworkInterface;
-import java.net.SocketException;
-
-
-/**
- * Encapsulate the interface parameters common to IpClient/IpServer components.
- *
- * Basically all java.net.NetworkInterface methods throw Exceptions. IpClient
- * and IpServer (sub)components need most or all of this information at some
- * point during their lifecycles, so pass only this simplified object around
- * which can be created once when IpClient/IpServer are told to start.
- *
- * @hide
- */
-public class InterfaceParams {
-    public final String name;
-    public final int index;
-    public final MacAddress macAddr;
-    public final int defaultMtu;
-
-    // TODO: move the below to NetworkStackConstants when this class is moved to the NetworkStack.
-    private static final int ETHER_MTU = 1500;
-    private static final int IPV6_MIN_MTU = 1280;
-
-
-    public static InterfaceParams getByName(String name) {
-        final NetworkInterface netif = getNetworkInterfaceByName(name);
-        if (netif == null) return null;
-
-        // Not all interfaces have MAC addresses, e.g. rmnet_data0.
-        final MacAddress macAddr = getMacAddress(netif);
-
-        try {
-            return new InterfaceParams(name, netif.getIndex(), macAddr, netif.getMTU());
-        } catch (IllegalArgumentException|SocketException e) {
-            return null;
-        }
-    }
-
-    public InterfaceParams(String name, int index, MacAddress macAddr) {
-        this(name, index, macAddr, ETHER_MTU);
-    }
-
-    public InterfaceParams(String name, int index, MacAddress macAddr, int defaultMtu) {
-        checkArgument((!TextUtils.isEmpty(name)), "impossible interface name");
-        checkArgument((index > 0), "invalid interface index");
-        this.name = name;
-        this.index = index;
-        this.macAddr = (macAddr != null) ? macAddr : MacAddress.fromBytes(new byte[] {
-                0x02, 0x00, 0x00, 0x00, 0x00, 0x00 });
-        this.defaultMtu = (defaultMtu > IPV6_MIN_MTU) ? defaultMtu : IPV6_MIN_MTU;
-    }
-
-    @Override
-    public String toString() {
-        return String.format("%s/%d/%s/%d", name, index, macAddr, defaultMtu);
-    }
-
-    private static NetworkInterface getNetworkInterfaceByName(String name) {
-        try {
-            return NetworkInterface.getByName(name);
-        } catch (NullPointerException|SocketException e) {
-            return null;
-        }
-    }
-
-    private static MacAddress getMacAddress(NetworkInterface netif) {
-        try {
-            return MacAddress.fromBytes(netif.getHardwareAddress());
-        } catch (IllegalArgumentException|NullPointerException|SocketException e) {
-            return null;
-        }
-    }
-}
diff --git a/services/net/java/android/net/util/SharedLog.java b/services/net/java/android/net/util/SharedLog.java
deleted file mode 100644
index 2cdb2b0..0000000
--- a/services/net/java/android/net/util/SharedLog.java
+++ /dev/null
@@ -1,202 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.util;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.text.TextUtils;
-import android.util.LocalLog;
-import android.util.Log;
-
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-import java.util.StringJoiner;
-
-
-/**
- * Class to centralize logging functionality for tethering.
- *
- * All access to class methods other than dump() must be on the same thread.
- *
- * TODO: this is a copy of SharedLog in the NetworkStack. Remove after Tethering is migrated.
- * @hide
- */
-public class SharedLog {
-    private static final int DEFAULT_MAX_RECORDS = 500;
-    private static final String COMPONENT_DELIMITER = ".";
-
-    private enum Category {
-        NONE,
-        ERROR,
-        MARK,
-        WARN,
-    };
-
-    private final LocalLog mLocalLog;
-    // The tag to use for output to the system log. This is not output to the
-    // LocalLog because that would be redundant.
-    private final String mTag;
-    // The component (or subcomponent) of a system that is sharing this log.
-    // This can grow in depth if components call forSubComponent() to obtain
-    // their SharedLog instance. The tag is not included in the component for
-    // brevity.
-    private final String mComponent;
-
-    public SharedLog(String tag) {
-        this(DEFAULT_MAX_RECORDS, tag);
-    }
-
-    public SharedLog(int maxRecords, String tag) {
-        this(new LocalLog(maxRecords), tag, tag);
-    }
-
-    private SharedLog(LocalLog localLog, String tag, String component) {
-        mLocalLog = localLog;
-        mTag = tag;
-        mComponent = component;
-    }
-
-    public String getTag() {
-        return mTag;
-    }
-
-    /**
-     * Create a SharedLog based on this log with an additional component prefix on each logged line.
-     */
-    public SharedLog forSubComponent(String component) {
-        if (!isRootLogInstance()) {
-            component = mComponent + COMPONENT_DELIMITER + component;
-        }
-        return new SharedLog(mLocalLog, mTag, component);
-    }
-
-    /**
-     * Dump the contents of this log.
-     *
-     * <p>This method may be called on any thread.
-     */
-    public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
-        mLocalLog.readOnlyLocalLog().dump(fd, writer, args);
-    }
-
-    //////
-    // Methods that both log an entry and emit it to the system log.
-    //////
-
-    /**
-     * Log an error due to an exception. This does not include the exception stacktrace.
-     *
-     * <p>The log entry will be also added to the system log.
-     * @see #e(String, Throwable)
-     */
-    public void e(Exception e) {
-        Log.e(mTag, record(Category.ERROR, e.toString()));
-    }
-
-    /**
-     * Log an error message.
-     *
-     * <p>The log entry will be also added to the system log.
-     */
-    public void e(String msg) {
-        Log.e(mTag, record(Category.ERROR, msg));
-    }
-
-    /**
-     * Log an error due to an exception, with the exception stacktrace if provided.
-     *
-     * <p>The error and exception message appear in the shared log, but the stacktrace is only
-     * logged in general log output (logcat). The log entry will be also added to the system log.
-     */
-    public void e(@NonNull String msg, @Nullable Throwable exception) {
-        if (exception == null) {
-            e(msg);
-            return;
-        }
-        Log.e(mTag, record(Category.ERROR, msg + ": " + exception.getMessage()), exception);
-    }
-
-    /**
-     * Log an informational message.
-     *
-     * <p>The log entry will be also added to the system log.
-     */
-    public void i(String msg) {
-        Log.i(mTag, record(Category.NONE, msg));
-    }
-
-    /**
-     * Log a warning message.
-     *
-     * <p>The log entry will be also added to the system log.
-     */
-    public void w(String msg) {
-        Log.w(mTag, record(Category.WARN, msg));
-    }
-
-    //////
-    // Methods that only log an entry (and do NOT emit to the system log).
-    //////
-
-    /**
-     * Log a general message to be only included in the in-memory log.
-     *
-     * <p>The log entry will *not* be added to the system log.
-     */
-    public void log(String msg) {
-        record(Category.NONE, msg);
-    }
-
-    /**
-     * Log a general, formatted message to be only included in the in-memory log.
-     *
-     * <p>The log entry will *not* be added to the system log.
-     * @see String#format(String, Object...)
-     */
-    public void logf(String fmt, Object... args) {
-        log(String.format(fmt, args));
-    }
-
-    /**
-     * Log a message with MARK level.
-     *
-     * <p>The log entry will *not* be added to the system log.
-     */
-    public void mark(String msg) {
-        record(Category.MARK, msg);
-    }
-
-    private String record(Category category, String msg) {
-        final String entry = logLine(category, msg);
-        mLocalLog.log(entry);
-        return entry;
-    }
-
-    private String logLine(Category category, String msg) {
-        final StringJoiner sj = new StringJoiner(" ");
-        if (!isRootLogInstance()) sj.add("[" + mComponent + "]");
-        if (category != Category.NONE) sj.add(category.toString());
-        return sj.add(msg).toString();
-    }
-
-    // Check whether this SharedLog instance is nominally the top level in
-    // a potential hierarchy of shared logs (the root of a tree),
-    // or is a subcomponent within the hierarchy.
-    private boolean isRootLogInstance() {
-        return TextUtils.isEmpty(mComponent) || mComponent.equals(mTag);
-    }
-}
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/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/mockingservicestests/Android.bp b/services/tests/mockingservicestests/Android.bp
index 8699669..96fedf9 100644
--- a/services/tests/mockingservicestests/Android.bp
+++ b/services/tests/mockingservicestests/Android.bp
@@ -20,7 +20,7 @@
     static_libs: [
         "services.core",
         "services.net",
-        "jobscheduler-service",
+        "service-jobscheduler",
         "androidx.test.runner",
         "mockito-target-extended-minus-junit4",
         "platform-test-annotations",
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
index e7f6a74..6c09239 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
@@ -1027,11 +1027,28 @@
         bindService(client, client2, null, 0, mock(IBinder.class));
         client2.setHasForegroundServices(true, 0);
         bindService(client2, app, null, 0, mock(IBinder.class));
+        ArrayList<ProcessRecord> lru = sService.mProcessList.mLruProcesses;
+        lru.clear();
+        lru.add(app);
+        lru.add(client);
+        lru.add(client2);
         sService.mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE;
-        sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
+        sService.mOomAdjuster.updateOomAdjLocked(app, true, OomAdjuster.OOM_ADJ_REASON_NONE);
 
         assertProcStates(app, PROCESS_STATE_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
                 SCHED_GROUP_DEFAULT);
+        assertProcStates(client, PROCESS_STATE_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
+                SCHED_GROUP_DEFAULT);
+        assertProcStates(client2, PROCESS_STATE_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
+                SCHED_GROUP_DEFAULT);
+
+        client2.setHasForegroundServices(false, 0);
+        sService.mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE;
+        sService.mOomAdjuster.updateOomAdjLocked(client2, true, OomAdjuster.OOM_ADJ_REASON_NONE);
+
+        assertEquals(PROCESS_STATE_CACHED_EMPTY, client2.setProcState);
+        assertEquals(PROCESS_STATE_CACHED_EMPTY, client.setProcState);
+        assertEquals(PROCESS_STATE_CACHED_EMPTY, app.setProcState);
     }
 
     @SuppressWarnings("GuardedBy")
diff --git a/services/tests/servicestests/Android.bp b/services/tests/servicestests/Android.bp
index 52fb69e..0be5fe0 100644
--- a/services/tests/servicestests/Android.bp
+++ b/services/tests/servicestests/Android.bp
@@ -41,7 +41,7 @@
         "hamcrest-library",
         "servicestests-utils",
         "xml-writer-device-lib",
-        "jobscheduler-service",
+        "service-jobscheduler",
     ],
 
     aidl: {
diff --git a/services/tests/servicestests/src/com/android/server/pm/CrossProfileAppsServiceImplTest.java b/services/tests/servicestests/src/com/android/server/pm/CrossProfileAppsServiceImplTest.java
index 839b25f..e18ff61 100644
--- a/services/tests/servicestests/src/com/android/server/pm/CrossProfileAppsServiceImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/CrossProfileAppsServiceImplTest.java
@@ -509,7 +509,7 @@
         mActivityInfo = activityInfo;
 
         when(mPackageManagerInternal.queryIntentActivities(
-                any(Intent.class), anyInt(), anyInt(), anyInt()))
+                any(Intent.class), nullable(String.class), anyInt(), anyInt(), anyInt()))
                 .thenReturn(Collections.singletonList(resolveInfo));
     }
 
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/wmtests/src/com/android/server/wm/ActivityDisplayTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityDisplayTests.java
index 24db657..5336811 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityDisplayTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityDisplayTests.java
@@ -134,10 +134,9 @@
     public void testNotResumeHomeStackOnRemovingDisplay() {
         // Create a display which supports system decoration and allows reparenting stacks to
         // another display when the display is removed.
-        final ActivityDisplay display = createNewActivityDisplay();
+        final ActivityDisplay display = new TestActivityDisplay.Builder(
+                mService, 1000, 1500).setSystemDecorations(true).build();
         doReturn(false).when(display).shouldDestroyContentOnRemove();
-        doReturn(true).when(display).supportsSystemDecorations();
-        mRootActivityContainer.addChild(display, ActivityDisplay.POSITION_TOP);
 
         // Put home stack on the display.
         final ActivityStack homeStack = new StackBuilder(mRootActivityContainer)
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
index 3a6ed54..ba54859 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
@@ -1096,7 +1096,7 @@
         taskTop.finishing = true;
 
         final ActivityRecord newR = new ActivityBuilder(mService).build();
-        final ActivityRecord result = mStack.resetTaskIfNeededLocked(taskTop, newR);
+        final ActivityRecord result = mStack.resetTaskIfNeeded(taskTop, newR);
         assertThat(result).isEqualTo(taskTop);
     }
 
@@ -1118,7 +1118,7 @@
             r.setState(ActivityStack.ActivityState.INITIALIZING, "test");
             // Ensure precondition that the activity is opaque.
             assertTrue(r.occludesParent());
-            mSupervisor.startSpecificActivityLocked(r, false /* andResume */,
+            mSupervisor.startSpecificActivity(r, false /* andResume */,
                     false /* checkConfig */);
         }
         mSupervisor.endDeferResume();
@@ -1145,12 +1145,12 @@
         new ActivityBuilder(mService).setTask(mTask).build();
         doReturn(false).when(nonTopVisibleActivity).attachedToProcess();
         doReturn(true).when(nonTopVisibleActivity).shouldBeVisible(anyBoolean(), anyBoolean());
-        doNothing().when(mSupervisor).startSpecificActivityLocked(any(), anyBoolean(),
+        doNothing().when(mSupervisor).startSpecificActivity(any(), anyBoolean(),
                 anyBoolean());
 
-        mStack.ensureActivitiesVisibleLocked(null /* starting */, 0 /* configChanges */,
+        mStack.ensureActivitiesVisible(null /* starting */, 0 /* configChanges */,
                 false /* preserveWindows */);
-        verify(mSupervisor).startSpecificActivityLocked(any(), eq(false) /* andResume */,
+        verify(mSupervisor).startSpecificActivity(any(), eq(false) /* andResume */,
                 anyBoolean());
     }
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
index 9af90e3..ae1bb8e 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
@@ -760,8 +760,9 @@
                 false /* mockGetLaunchStack */);
 
         // Create a secondary display at bottom.
-        final TestActivityDisplay secondaryDisplay = createNewActivityDisplay();
-        mRootActivityContainer.addChild(secondaryDisplay, POSITION_BOTTOM);
+        final TestActivityDisplay secondaryDisplay =
+                new TestActivityDisplay.Builder(mService, 1000, 1500)
+                        .setPosition(POSITION_BOTTOM).build();
         final ActivityStack stack = secondaryDisplay.createStack(WINDOWING_MODE_FULLSCREEN,
                 ACTIVITY_TYPE_STANDARD, true /* onTop */);
 
@@ -798,7 +799,8 @@
                 false /* mockGetLaunchStack */);
 
         // Create a secondary display with an activity.
-        final TestActivityDisplay secondaryDisplay = createNewActivityDisplay();
+        final TestActivityDisplay secondaryDisplay =
+                new TestActivityDisplay.Builder(mService, 1000, 1500).build();
         mRootActivityContainer.addChild(secondaryDisplay, POSITION_TOP);
         final ActivityRecord singleTaskActivity = createSingleTaskActivityOn(
                 secondaryDisplay.createStack(WINDOWING_MODE_FULLSCREEN,
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
index e9546a2..dae1052 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
@@ -26,7 +26,9 @@
 
 import android.app.Activity;
 import android.app.ActivityManager;
+import android.content.res.Configuration;
 import android.graphics.Rect;
+import android.view.IDisplayWindowListener;
 import android.view.WindowContainerTransaction;
 
 import androidx.test.filters.MediumTest;
@@ -35,6 +37,8 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.util.ArrayList;
+
 /**
  * Tests for the {@link ActivityTaskManagerService} class.
  *
@@ -93,5 +97,56 @@
         mService.applyContainerTransaction(t);
         assertEquals(newBounds, stack.getBounds());
     }
+
+    @Test
+    public void testDisplayWindowListener() {
+        final ArrayList<Integer> added = new ArrayList<>();
+        final ArrayList<Integer> changed = new ArrayList<>();
+        final ArrayList<Integer> removed = new ArrayList<>();
+        IDisplayWindowListener listener = new IDisplayWindowListener.Stub() {
+            @Override
+            public void onDisplayAdded(int displayId) {
+                added.add(displayId);
+            }
+
+            @Override
+            public void onDisplayConfigurationChanged(int displayId, Configuration newConfig) {
+                changed.add(displayId);
+            }
+
+            @Override
+            public void onDisplayRemoved(int displayId) {
+                removed.add(displayId);
+            }
+        };
+        mService.mWindowManager.registerDisplayWindowListener(listener);
+        // Check that existing displays call added
+        assertEquals(1, added.size());
+        assertEquals(0, changed.size());
+        assertEquals(0, removed.size());
+        added.clear();
+        // Check adding a display
+        ActivityDisplay newDisp1 = new TestActivityDisplay.Builder(mService, 600, 800).build();
+        assertEquals(1, added.size());
+        assertEquals(0, changed.size());
+        assertEquals(0, removed.size());
+        added.clear();
+        // Check that changes are reported
+        Configuration c = new Configuration(newDisp1.getRequestedOverrideConfiguration());
+        c.windowConfiguration.setBounds(new Rect(0, 0, 1000, 1300));
+        newDisp1.onRequestedOverrideConfigurationChanged(c);
+        mService.mRootActivityContainer.ensureVisibilityAndConfig(null /* starting */,
+                newDisp1.mDisplayId, false /* markFrozenIfConfigChanged */,
+                false /* deferResume */);
+        assertEquals(0, added.size());
+        assertEquals(1, changed.size());
+        assertEquals(0, removed.size());
+        changed.clear();
+        // Check that removal is reported
+        newDisp1.remove();
+        assertEquals(0, added.size());
+        assertEquals(0, changed.size());
+        assertEquals(1, removed.size());
+    }
 }
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
index 47b39b0..7322ac3 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
@@ -43,7 +43,6 @@
 import android.os.Build;
 import android.os.UserHandle;
 import android.service.voice.IVoiceInteractionSession;
-import android.view.DisplayInfo;
 
 import com.android.server.AttributeCache;
 
@@ -78,27 +77,9 @@
         mRootActivityContainer = mService.mRootActivityContainer;
     }
 
-    /** Creates a {@link TestActivityDisplay}. */
-    TestActivityDisplay createNewActivityDisplay() {
-        return TestActivityDisplay.create(mSupervisor);
-    }
-
-    TestActivityDisplay createNewActivityDisplay(DisplayInfo info) {
-        return TestActivityDisplay.create(mSupervisor, info);
-    }
-
     /** Creates and adds a {@link TestActivityDisplay} to supervisor at the given position. */
     TestActivityDisplay addNewActivityDisplayAt(int position) {
-        final TestActivityDisplay display = createNewActivityDisplay();
-        mRootActivityContainer.addChild(display, position);
-        return display;
-    }
-
-    /** Creates and adds a {@link TestActivityDisplay} to supervisor at the given position. */
-    TestActivityDisplay addNewActivityDisplayAt(DisplayInfo info, int position) {
-        final TestActivityDisplay display = createNewActivityDisplay(info);
-        mRootActivityContainer.addChild(display, position);
-        return display;
+        return new TestActivityDisplay.Builder(mService, 1000, 1500).setPosition(position).build();
     }
 
     /** Sets the default minimum task size to 1 so that tests can use small task sizes */
@@ -271,7 +252,7 @@
                 doReturn(true).when(activity).occludesParent();
                 mTask.addChild(activity);
                 // Make visible by default...
-                activity.setHidden(false);
+                activity.setVisible(true);
             }
 
             final WindowProcessController wpc = new WindowProcessController(mService,
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java
index 6020453..d415f25 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java
@@ -62,7 +62,7 @@
         final ActivityRecord translucentOpening = createActivityRecord(mDisplayContent,
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
         translucentOpening.setOccludesParent(false);
-        translucentOpening.setHidden(true);
+        translucentOpening.setVisible(false);
         mDisplayContent.mOpeningApps.add(behind);
         mDisplayContent.mOpeningApps.add(translucentOpening);
         assertEquals(WindowManager.TRANSIT_TRANSLUCENT_ACTIVITY_OPEN,
@@ -90,7 +90,7 @@
         final ActivityRecord translucentOpening = createActivityRecord(mDisplayContent,
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
         translucentOpening.setOccludesParent(false);
-        translucentOpening.setHidden(true);
+        translucentOpening.setVisible(false);
         mDisplayContent.mOpeningApps.add(behind);
         mDisplayContent.mOpeningApps.add(translucentOpening);
         assertEquals(TRANSIT_TASK_CHANGE_WINDOWING_MODE,
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
index 1c15096..9f3bd75 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
@@ -252,7 +252,7 @@
     @Test
     @Presubmit
     public void testGetOrientation() {
-        mActivity.setHidden(false);
+        mActivity.setVisible(true);
 
         mActivity.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
 
@@ -261,7 +261,7 @@
         assertEquals(SCREEN_ORIENTATION_LANDSCAPE, mActivity.getOrientation());
 
         mActivity.setOccludesParent(true);
-        mActivity.setHidden(true);
+        mActivity.setVisible(false);
         // Can not specify orientation if app isn't visible even though it occludes parent.
         assertEquals(SCREEN_ORIENTATION_UNSET, mActivity.getOrientation());
         // Can specify orientation if the current orientation candidate is orientation behind.
@@ -313,7 +313,7 @@
 
     @Test
     public void testSetOrientation() {
-        mActivity.setHidden(false);
+        mActivity.setVisible(true);
 
         // Assert orientation is unspecified to start.
         assertEquals(SCREEN_ORIENTATION_UNSPECIFIED, mActivity.getOrientation());
diff --git a/services/tests/wmtests/src/com/android/server/wm/HighRefreshRateBlacklistTest.java b/services/tests/wmtests/src/com/android/server/wm/HighRefreshRateBlacklistTest.java
index 5fb6f45..56cb447 100644
--- a/services/tests/wmtests/src/com/android/server/wm/HighRefreshRateBlacklistTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/HighRefreshRateBlacklistTest.java
@@ -120,6 +120,23 @@
         assertFalse(mBlacklist.isBlacklisted(APP3));
     }
 
+    @Test
+    public void testOverriddenByDeviceConfigUnrelatedFlagChanged() {
+        final Resources r = createResources(APP1);
+        final FakeDeviceConfig config = new FakeDeviceConfig();
+        mBlacklist = new HighRefreshRateBlacklist(r, config);
+        config.setBlacklist(APP2 + "," + APP3);
+        assertFalse(mBlacklist.isBlacklisted(APP1));
+        assertTrue(mBlacklist.isBlacklisted(APP2));
+        assertTrue(mBlacklist.isBlacklisted(APP3));
+
+        //  Change an unrelated flag in our namespace and verify that the blacklist is intact
+        config.putPropertyAndNotify(DeviceConfig.NAMESPACE_DISPLAY_MANAGER, "someKey", "someValue");
+        assertFalse(mBlacklist.isBlacklisted(APP1));
+        assertTrue(mBlacklist.isBlacklisted(APP2));
+        assertTrue(mBlacklist.isBlacklisted(APP3));
+    }
+
     private Resources createResources(String... defaultBlacklist) {
         Resources r = mock(Resources.class);
         when(r.getStringArray(R.array.config_highRefreshRateBlacklist))
diff --git a/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java b/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java
index 0908f71..79ad0c4 100644
--- a/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java
@@ -36,7 +36,6 @@
 import android.graphics.Rect;
 import android.os.UserHandle;
 import android.platform.test.annotations.Presubmit;
-import android.view.DisplayInfo;
 
 import androidx.test.InstrumentationRegistry;
 import androidx.test.filters.MediumTest;
@@ -103,11 +102,8 @@
         deleteRecursively(mFolder);
 
         mDisplayUniqueId = "test:" + Integer.toString(sNextUniqueId++);
-        final DisplayInfo info = new DisplayInfo();
-        mService.mContext.getDisplay().getDisplayInfo(info);
-        info.uniqueId = mDisplayUniqueId;
-        mTestDisplay = createNewActivityDisplay(info);
-        mRootActivityContainer.addChild(mTestDisplay, ActivityDisplay.POSITION_TOP);
+        mTestDisplay = new TestActivityDisplay.Builder(mService, 1000, 1500)
+                .setUniqueId(mDisplayUniqueId).build();
         when(mRootActivityContainer.getActivityDisplay(eq(mDisplayUniqueId)))
                 .thenReturn(mTestDisplay);
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
index 7026004..1abd366 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
@@ -149,7 +149,7 @@
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
         final ActivityRecord hiddenActivity = createActivityRecord(mDisplayContent,
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
-        hiddenActivity.setHidden(true);
+        hiddenActivity.setVisible(false);
         mDisplayContent.getConfiguration().windowConfiguration.setRotation(
                 mDisplayContent.getRotation());
         mController.initialize(ACTIVITY_TYPE_HOME, new SparseBooleanArray(), homeActivity);
diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java
index d48b9d7..e67380c 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java
@@ -200,7 +200,7 @@
         startRecentsActivity();
 
         // Recents activity must be restarted, but not be resumed while running recents animation.
-        verify(mRootActivityContainer.mStackSupervisor).startSpecificActivityLocked(
+        verify(mRootActivityContainer.mStackSupervisor).startSpecificActivity(
                 eq(recentActivity), eq(false), anyBoolean());
         assertThat(recentActivity.getState()).isEqualTo(PAUSED);
     }
diff --git a/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java
index 3cc781c..e2bdf87 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java
@@ -35,7 +35,6 @@
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.times;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
-import static com.android.server.wm.ActivityDisplay.POSITION_TOP;
 import static com.android.server.wm.ActivityStackSupervisor.ON_TOP;
 import static com.android.server.wm.RootActivityContainer.MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE;
 
@@ -61,7 +60,6 @@
 import android.graphics.Rect;
 import android.platform.test.annotations.Presubmit;
 import android.util.Pair;
-import android.view.DisplayInfo;
 
 import androidx.test.filters.MediumTest;
 
@@ -518,9 +516,9 @@
         mockResolveSecondaryHomeActivity();
 
         // Create secondary displays.
-        final TestActivityDisplay secondDisplay = createNewActivityDisplay();
-        mRootActivityContainer.addChild(secondDisplay, POSITION_TOP);
-        doReturn(true).when(secondDisplay).supportsSystemDecorations();
+        final TestActivityDisplay secondDisplay =
+                new TestActivityDisplay.Builder(mService, 1000, 1500)
+                        .setSystemDecorations(true).build();
 
         doReturn(true).when(mRootActivityContainer)
                 .ensureVisibilityAndConfig(any(), anyInt(), anyBoolean(), anyBoolean());
@@ -585,10 +583,10 @@
     @Test
     public void testStartSecondaryHomeOnDisplayWithUserKeyLocked() {
         // Create secondary displays.
-        final TestActivityDisplay secondDisplay = createNewActivityDisplay();
-        mRootActivityContainer.addChild(secondDisplay, POSITION_TOP);
+        final TestActivityDisplay secondDisplay =
+                new TestActivityDisplay.Builder(mService, 1000, 1500)
+                        .setSystemDecorations(true).build();
 
-        doReturn(true).when(secondDisplay).supportsSystemDecorations();
         // Use invalid user id to let StorageManager.isUserKeyUnlocked() return false.
         final int currentUser = mRootActivityContainer.mCurrentUser;
         mRootActivityContainer.mCurrentUser = -1;
@@ -611,9 +609,9 @@
     @Test
     public void testStartSecondaryHomeOnDisplayWithoutSysDecorations() {
         // Create secondary displays.
-        final TestActivityDisplay secondDisplay = createNewActivityDisplay();
-        mRootActivityContainer.addChild(secondDisplay, POSITION_TOP);
-        doReturn(false).when(secondDisplay).supportsSystemDecorations();
+        final TestActivityDisplay secondDisplay =
+                new TestActivityDisplay.Builder(mService, 1000, 1500)
+                        .setSystemDecorations(false).build();
 
         mRootActivityContainer.startHomeOnDisplay(0 /* userId */, "testStartSecondaryHome",
                 secondDisplay.mDisplayId, true /* allowInstrumenting */, true /* fromHomeKey */);
@@ -834,12 +832,9 @@
     @Test
     public void testGetLaunchStackWithRealCallerId() {
         // Create a non-system owned virtual display.
-        final DisplayInfo info = new DisplayInfo();
-        mSupervisor.mService.mContext.getDisplay().getDisplayInfo(info);
-        info.type = TYPE_VIRTUAL;
-        info.ownerUid = 100;
-        final TestActivityDisplay secondaryDisplay = TestActivityDisplay.create(mSupervisor, info);
-        mRootActivityContainer.addChild(secondaryDisplay, POSITION_TOP);
+        final TestActivityDisplay secondaryDisplay =
+                new TestActivityDisplay.Builder(mService, 1000, 1500)
+                        .setType(TYPE_VIRTUAL).setOwnerUid(100).build();
 
         // Create an activity with specify the original launch pid / uid.
         final ActivityRecord r = new ActivityBuilder(mService).setLaunchedFromPid(200)
diff --git a/services/tests/wmtests/src/com/android/server/wm/RunningTasksTest.java b/services/tests/wmtests/src/com/android/server/wm/RunningTasksTest.java
index 15dcbf5..eba2bc8 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RunningTasksTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RunningTasksTest.java
@@ -18,7 +18,6 @@
 
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
 import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
-import static android.view.Display.DEFAULT_DISPLAY;
 
 import static com.google.common.truth.Truth.assertThat;
 
@@ -59,13 +58,15 @@
     public void testCollectTasksByLastActiveTime() {
         // Create a number of stacks with tasks (of incrementing active time)
         final ArrayList<ActivityDisplay> displays = new ArrayList<>();
-        final ActivityDisplay display = TestActivityDisplay.create(mSupervisor, DEFAULT_DISPLAY);
+        final ActivityDisplay display =
+                new TestActivityDisplay.Builder(mService, 1000, 2500).build();
         displays.add(display);
 
         final int numStacks = 2;
         for (int stackIndex = 0; stackIndex < numStacks; stackIndex++) {
             final ActivityStack stack = new StackBuilder(mRootActivityContainer)
                     .setCreateActivity(false)
+                    .setDisplay(display)
                     .setOnTop(false)
                     .build();
         }
diff --git a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
index b9e1d4b..212931b 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
@@ -290,10 +290,12 @@
     public void testFixedScreenLayoutSizeBits() {
         setUpApp(new TestActivityDisplay.Builder(mService, 1000, 2500).build());
         final int fixedScreenLayout = Configuration.SCREENLAYOUT_LONG_NO
-                | Configuration.SCREENLAYOUT_SIZE_NORMAL;
+                | Configuration.SCREENLAYOUT_SIZE_NORMAL
+                | Configuration.SCREENLAYOUT_COMPAT_NEEDED;
         final int layoutMask = Configuration.SCREENLAYOUT_LONG_MASK
                 | Configuration.SCREENLAYOUT_SIZE_MASK
-                | Configuration.SCREENLAYOUT_LAYOUTDIR_MASK;
+                | Configuration.SCREENLAYOUT_LAYOUTDIR_MASK
+                | Configuration.SCREENLAYOUT_COMPAT_NEEDED;
         Configuration c = new Configuration(mTask.getRequestedOverrideConfiguration());
         c.screenLayout = fixedScreenLayout | Configuration.SCREENLAYOUT_LAYOUTDIR_LTR;
         mTask.onRequestedOverrideConfigurationChanged(c);
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/TaskRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java
index b07a27b..c8f81f4 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java
@@ -37,7 +37,6 @@
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
 import static com.android.server.policy.WindowManagerPolicy.USER_ROTATION_FREE;
 import static com.android.server.wm.DisplayRotation.FIXED_TO_USER_ROTATION_ENABLED;
-import static com.android.server.wm.WindowContainer.POSITION_TOP;
 
 import static com.google.common.truth.Truth.assertThat;
 
@@ -266,11 +265,8 @@
     public void testFullscreenBoundsForcedOrientation() {
         final Rect fullScreenBounds = new Rect(0, 0, 1920, 1080);
         final Rect fullScreenBoundsPort = new Rect(0, 0, 1080, 1920);
-        DisplayInfo info = new DisplayInfo();
-        mService.mContext.getDisplay().getDisplayInfo(info);
-        info.logicalWidth = fullScreenBounds.width();
-        info.logicalHeight = fullScreenBounds.height();
-        ActivityDisplay display = addNewActivityDisplayAt(info, POSITION_TOP);
+        ActivityDisplay display = new TestActivityDisplay.Builder(
+                mService, fullScreenBounds.width(), fullScreenBounds.height()).build();
         assertTrue(mRootActivityContainer.getActivityDisplay(display.mDisplayId) != null);
         // Fix the display orientation to landscape which is the natural rotation (0) for the test
         // display.
@@ -332,11 +328,8 @@
     @Test
     public void testIgnoresForcedOrientationWhenParentHandles() {
         final Rect fullScreenBounds = new Rect(0, 0, 1920, 1080);
-        DisplayInfo info = new DisplayInfo();
-        mService.mContext.getDisplay().getDisplayInfo(info);
-        info.logicalWidth = fullScreenBounds.width();
-        info.logicalHeight = fullScreenBounds.height();
-        ActivityDisplay display = addNewActivityDisplayAt(info, POSITION_TOP);
+        ActivityDisplay display = new TestActivityDisplay.Builder(
+                mService, fullScreenBounds.width(), fullScreenBounds.height()).build();
 
         display.getRequestedOverrideConfiguration().orientation =
                 Configuration.ORIENTATION_LANDSCAPE;
diff --git a/services/tests/wmtests/src/com/android/server/wm/TestActivityDisplay.java b/services/tests/wmtests/src/com/android/server/wm/TestActivityDisplay.java
index 48ec261..247cd87 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TestActivityDisplay.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TestActivityDisplay.java
@@ -17,7 +17,6 @@
 package com.android.server.wm;
 
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
-import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS;
 
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyBoolean;
@@ -39,36 +38,6 @@
 class TestActivityDisplay extends ActivityDisplay {
     private final ActivityStackSupervisor mSupervisor;
 
-    static TestActivityDisplay create(ActivityStackSupervisor supervisor) {
-        return create(supervisor, SystemServicesTestRule.sNextDisplayId++);
-    }
-
-    static TestActivityDisplay create(ActivityStackSupervisor supervisor, DisplayInfo info) {
-        return create(supervisor, SystemServicesTestRule.sNextDisplayId++, info);
-    }
-
-    static TestActivityDisplay create(ActivityStackSupervisor supervisor, int displayId) {
-        final DisplayInfo info = new DisplayInfo();
-        supervisor.mService.mContext.getDisplay().getDisplayInfo(info);
-        return create(supervisor, displayId, info);
-    }
-
-    static TestActivityDisplay create(ActivityStackSupervisor supervisor, int displayId,
-            DisplayInfo info) {
-        if (displayId == DEFAULT_DISPLAY) {
-            synchronized (supervisor.mService.mGlobalLock) {
-                return new TestActivityDisplay(supervisor,
-                        supervisor.mRootActivityContainer.mDisplayManager.getDisplay(displayId));
-            }
-        }
-        final Display display = new Display(DisplayManagerGlobal.getInstance(), displayId,
-                info, DEFAULT_DISPLAY_ADJUSTMENTS);
-
-        synchronized (supervisor.mService.mGlobalLock) {
-            return new TestActivityDisplay(supervisor, display);
-        }
-    }
-
     private TestActivityDisplay(ActivityStackSupervisor supervisor, Display display) {
         super(supervisor.mService.mRootActivityContainer, display);
         // Normally this comes from display-properties as exposed by WM. Without that, just
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java
index cc90ca1..4d25a83 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java
@@ -18,8 +18,6 @@
 
 import static android.view.Display.INVALID_DISPLAY;
 
-import static com.android.server.wm.ActivityDisplay.POSITION_TOP;
-
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
@@ -132,8 +130,6 @@
     }
 
     private TestActivityDisplay createTestActivityDisplayInContainer() {
-        final TestActivityDisplay testActivityDisplay = createNewActivityDisplay();
-        mRootActivityContainer.addChild(testActivityDisplay, POSITION_TOP);
-        return testActivityDisplay;
+        return new TestActivityDisplay.Builder(mService, 1000, 1500).build();
     }
 }
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
index 8af47bc..eed5ef5 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
@@ -383,11 +383,11 @@
     @Test
     public void testCanAffectSystemUiFlags() {
         final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
-        app.mToken.setHidden(false);
+        app.mActivityRecord.setVisible(true);
         assertTrue(app.canAffectSystemUiFlags());
-        app.mToken.setHidden(true);
+        app.mActivityRecord.setVisible(false);
         assertFalse(app.canAffectSystemUiFlags());
-        app.mToken.setHidden(false);
+        app.mActivityRecord.setVisible(true);
         app.mAttrs.alpha = 0.0f;
         assertFalse(app.canAffectSystemUiFlags());
     }
@@ -395,7 +395,7 @@
     @Test
     public void testCanAffectSystemUiFlags_disallow() {
         final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
-        app.mToken.setHidden(false);
+        app.mActivityRecord.setVisible(true);
         assertTrue(app.canAffectSystemUiFlags());
         app.getTask().setCanAffectSystemUiFlags(false);
         assertFalse(app.canAffectSystemUiFlags());
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java
index 34a2369..26743c8 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java
@@ -74,7 +74,7 @@
     private static void postCreateActivitySetup(ActivityRecord activity, DisplayContent dc) {
         activity.onDisplayChanged(dc);
         activity.setOccludesParent(true);
-        activity.setHidden(false);
+        activity.setVisible(true);
         activity.mVisibleRequested = true;
     }
 
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..437b84b 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
@@ -36,8 +36,6 @@
 
 import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
 
-import static com.android.server.wm.ActivityDisplay.POSITION_TOP;
-
 import static org.mockito.Mockito.mock;
 
 import android.content.Context;
@@ -175,7 +173,7 @@
             }
 
             // Cleaned up everything in Handler.
-            mSystemServicesTestRule.cleanupWindowManagerHandlers();
+            cleanupWindowManagerHandlers();
         } catch (Exception e) {
             Log.e(TAG, "Failed to tear down test", e);
             throw e;
@@ -343,8 +341,7 @@
     /** Creates a {@link DisplayContent} and adds it to the system. */
     DisplayContent createNewDisplay(DisplayInfo info) {
         final ActivityDisplay display =
-                TestActivityDisplay.create(mWm.mAtmService.mStackSupervisor, info);
-        mWm.mAtmService.mRootActivityContainer.addChild(display, POSITION_TOP);
+                new TestActivityDisplay.Builder(mWm.mAtmService, info).build();
         return display.mDisplayContent;
     }
 
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/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index f9b3659..63b062e 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -347,7 +347,7 @@
                 Slog.i(TAG, "Attempted to unlock stopped or removed user " + userId);
                 return;
             }
-            userService.userUnlocked(System.currentTimeMillis());
+
             // Process all the pending reported events
             while (pendingEvents.peek() != null) {
                 reportEvent(pendingEvents.poll(), userId);
@@ -466,6 +466,7 @@
             if (mUserUnlockedStates.get(userId)) {
                 try {
                     service.init(currentTimeMillis);
+                    mUserState.put(userId, service);
                 } catch (Exception e) {
                     if (mUserManager.isUserUnlocked(userId)) {
                         throw e; // rethrow exception - user is unlocked
@@ -476,7 +477,6 @@
                     }
                 }
             }
-            mUserState.put(userId, service);
         }
         return service;
     }
diff --git a/services/usage/java/com/android/server/usage/UserUsageStatsService.java b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
index 5783932..c6a5fcf 100644
--- a/services/usage/java/com/android/server/usage/UserUsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
@@ -165,10 +165,6 @@
         }
     }
 
-    void userUnlocked(long currentTimeMillis) {
-        init(currentTimeMillis);
-    }
-
     void userStopped() {
         // Flush events to disk immediately to guarantee persistence.
         persistActiveStats();
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/provider/Telephony.java b/telephony/java/android/provider/Telephony.java
index 15bb002..7ed37c4 100644
--- a/telephony/java/android/provider/Telephony.java
+++ b/telephony/java/android/provider/Telephony.java
@@ -25,6 +25,7 @@
 import android.annotation.SystemApi;
 import android.annotation.TestApi;
 import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.ChangeId;
 import android.content.ComponentName;
 import android.content.ContentResolver;
 import android.content.ContentValues;
@@ -4033,6 +4034,16 @@
         @Retention(RetentionPolicy.SOURCE)
         public @interface Skip464XlatStatus {}
 
+        /**
+         * Compat framework change ID for the APN db read permission change.
+         *
+         * In API level 30 and beyond, accessing the APN database will require the
+         * {@link android.Manifest.permission#WRITE_APN_SETTINGS} permission. This change ID tracks
+         * apps that are affected because they don't hold this permission.
+         * @hide
+         */
+        @ChangeId
+        public static final long APN_READING_PERMISSION_CHANGE_ID = 124107808L;
     }
 
     /**
@@ -4090,9 +4101,7 @@
 
         /**
          * The subscription which received this cell broadcast message.
-         * @deprecated use {@link #SLOT_INDEX} instead.
          * <P>Type: INTEGER</P>
-         * @hide
          */
         public static final String SUB_ID = "sub_id";
 
@@ -4366,6 +4375,7 @@
         public static final String[] QUERY_COLUMNS_FWK = {
                 _ID,
                 SLOT_INDEX,
+                SUB_ID,
                 GEOGRAPHICAL_SCOPE,
                 PLMN,
                 LAC,
diff --git a/telephony/java/android/telephony/CellIdentityNr.java b/telephony/java/android/telephony/CellIdentityNr.java
index 6df60ba..edc838c 100644
--- a/telephony/java/android/telephony/CellIdentityNr.java
+++ b/telephony/java/android/telephony/CellIdentityNr.java
@@ -62,6 +62,12 @@
     }
 
     /** @hide */
+    public CellIdentityNr(android.hardware.radio.V1_4.CellIdentityNr cid) {
+        this(cid.pci, cid.tac, cid.nrarfcn, cid.mcc, cid.mnc, cid.nci, cid.operatorNames.alphaLong,
+                cid.operatorNames.alphaShort);
+    }
+
+    /** @hide */
     public CellIdentityNr sanitizeLocationInfo() {
         return new CellIdentityNr(CellInfo.UNAVAILABLE, CellInfo.UNAVAILABLE, CellInfo.UNAVAILABLE,
                 mMccStr, mMncStr, CellInfo.UNAVAILABLE, mAlphaLong, mAlphaShort);
diff --git a/telephony/java/android/telephony/CellInfo.java b/telephony/java/android/telephony/CellInfo.java
index 18687d4..ae45307 100644
--- a/telephony/java/android/telephony/CellInfo.java
+++ b/telephony/java/android/telephony/CellInfo.java
@@ -374,6 +374,7 @@
             case Info.hidl_discriminator.lte: return new CellInfoLte(ci, timeStamp);
             case Info.hidl_discriminator.wcdma: return new CellInfoWcdma(ci, timeStamp);
             case Info.hidl_discriminator.tdscdma: return new CellInfoTdscdma(ci, timeStamp);
+            case Info.hidl_discriminator.nr: return new CellInfoNr(ci, timeStamp);
             default: return null;
         }
     }
diff --git a/telephony/java/android/telephony/CellInfoNr.java b/telephony/java/android/telephony/CellInfoNr.java
index cea8323..8b41b8b 100644
--- a/telephony/java/android/telephony/CellInfoNr.java
+++ b/telephony/java/android/telephony/CellInfoNr.java
@@ -45,6 +45,14 @@
         mCellSignalStrength = other.mCellSignalStrength;
     }
 
+    /** @hide */
+    public CellInfoNr(android.hardware.radio.V1_4.CellInfo ci, long timeStamp) {
+        super(ci, timeStamp);
+        final android.hardware.radio.V1_4.CellInfoNr cil = ci.info.nr();
+        mCellIdentity = new CellIdentityNr(cil.cellidentity);
+        mCellSignalStrength = new CellSignalStrengthNr(cil.signalStrength);
+    }
+
     /**
      * @return a {@link CellIdentityNr} instance.
      */
diff --git a/telephony/java/android/telephony/SmsCbMessage.java b/telephony/java/android/telephony/SmsCbMessage.java
index 737ead1..fad70d2 100644
--- a/telephony/java/android/telephony/SmsCbMessage.java
+++ b/telephony/java/android/telephony/SmsCbMessage.java
@@ -205,7 +205,9 @@
     /** CMAS warning area coordinates. */
     private final List<Geometry> mGeometries;
 
-    private int mSlotIndex = 0;
+    private final int mSlotIndex;
+
+    private final int mSubId;
 
     /**
      * Create a new SmsCbMessage with the specified data.
@@ -214,11 +216,11 @@
     public SmsCbMessage(int messageFormat, int geographicalScope, int serialNumber,
             @NonNull SmsCbLocation location, int serviceCategory, @Nullable String language,
             @Nullable String body, int priority, @Nullable SmsCbEtwsInfo etwsWarningInfo,
-            @Nullable SmsCbCmasInfo cmasWarningInfo, int slotIndex) {
+            @Nullable SmsCbCmasInfo cmasWarningInfo, int slotIndex, int subId) {
 
         this(messageFormat, geographicalScope, serialNumber, location, serviceCategory, language,
                 body, priority, etwsWarningInfo, cmasWarningInfo, 0 /* maximumWaitingTime */,
-                null /* geometries */, System.currentTimeMillis(), slotIndex);
+                null /* geometries */, System.currentTimeMillis(), slotIndex, subId);
     }
 
     /**
@@ -226,10 +228,12 @@
      * coordinates information.
      */
     public SmsCbMessage(int messageFormat, int geographicalScope, int serialNumber,
-            @NonNull SmsCbLocation location, int serviceCategory, @Nullable String language,
-            @Nullable String body, int priority, @Nullable SmsCbEtwsInfo etwsWarningInfo,
-            @Nullable SmsCbCmasInfo cmasWarningInfo, int maximumWaitTimeSec,
-            @Nullable List<Geometry> geometries, long receivedTimeMillis, int slotIndex) {
+                        @NonNull SmsCbLocation location, int serviceCategory,
+                        @Nullable String language, @Nullable String body, int priority,
+                        @Nullable SmsCbEtwsInfo etwsWarningInfo,
+                        @Nullable SmsCbCmasInfo cmasWarningInfo, int maximumWaitTimeSec,
+                        @Nullable List<Geometry> geometries, long receivedTimeMillis, int slotIndex,
+                        int subId) {
         mMessageFormat = messageFormat;
         mGeographicalScope = geographicalScope;
         mSerialNumber = serialNumber;
@@ -244,6 +248,7 @@
         mGeometries = geometries;
         mMaximumWaitTimeSec = maximumWaitTimeSec;
         mSlotIndex = slotIndex;
+        mSubId = subId;
     }
 
     /**
@@ -282,6 +287,7 @@
         mGeometries = geoStr != null ? CbGeoUtils.parseGeometriesFromString(geoStr) : null;
         mMaximumWaitTimeSec = in.readInt();
         mSlotIndex = in.readInt();
+        mSubId = in.readInt();
     }
 
     /**
@@ -317,6 +323,7 @@
                 mGeometries != null ? CbGeoUtils.encodeGeometriesToString(mGeometries) : null);
         dest.writeInt(mMaximumWaitTimeSec);
         dest.writeInt(mSlotIndex);
+        dest.writeInt(mSubId);
     }
 
     @NonNull
@@ -427,14 +434,22 @@
     }
 
     /**
-     * Get the slotIndex associated with this message.
-     * @return the slotIndex associated with this message
+     * Get the slot index associated with this message.
+     * @return the slot index associated with this message
      */
     public int getSlotIndex() {
         return mSlotIndex;
     }
 
     /**
+     * Get the subscription id associated with this message.
+     * @return the subscription id associated with this message
+     */
+    public int getSubscriptionId() {
+        return mSubId;
+    }
+
+    /**
      * Get the message format ({@link #MESSAGE_FORMAT_3GPP} or {@link #MESSAGE_FORMAT_3GPP2}).
      * @return an integer representing 3GPP or 3GPP2 message format
      */
@@ -536,6 +551,7 @@
     public ContentValues getContentValues() {
         ContentValues cv = new ContentValues(16);
         cv.put(CellBroadcasts.SLOT_INDEX, mSlotIndex);
+        cv.put(CellBroadcasts.SUB_ID, mSubId);
         cv.put(CellBroadcasts.GEOGRAPHICAL_SCOPE, mGeographicalScope);
         if (mLocation.getPlmn() != null) {
             cv.put(CellBroadcasts.PLMN, mLocation.getPlmn());
@@ -577,7 +593,6 @@
         }
 
         cv.put(CellBroadcasts.MAXIMUM_WAIT_TIME, mMaximumWaitTimeSec);
-        cv.put(CellBroadcasts.SLOT_INDEX, mSlotIndex);
 
         return cv;
     }
@@ -600,6 +615,7 @@
         int format = cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.MESSAGE_FORMAT));
         int priority = cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.MESSAGE_PRIORITY));
         int slotIndex = cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.SLOT_INDEX));
+        int subId = cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.SUB_ID));
 
         String plmn;
         int plmnColumn = cursor.getColumnIndex(CellBroadcasts.PLMN);
@@ -697,7 +713,7 @@
 
         return new SmsCbMessage(format, geoScope, serialNum, location, category,
                 language, body, priority, etwsInfo, cmasInfo, maximumWaitTimeSec, geometries,
-                receivedTimeMillis, slotIndex);
+                receivedTimeMillis, slotIndex, subId);
     }
 
     /**
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 1357e9c..a55d166 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();
             }
@@ -11088,14 +11091,66 @@
     }
 
     /**
-     * Broadcast intent action for Ota emergency number database installation complete.
+     * Indicates Emergency number database version is invalid.
      *
      * @hide
      */
-    @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+    @TestApi
     @SystemApi
-    public static final String ACTION_OTA_EMERGENCY_NUMBER_DB_INSTALLED =
-            "android.telephony.action.OTA_EMERGENCY_NUMBER_DB_INSTALLED";
+    public static final int INVALID_EMERGENCY_NUMBER_DB_VERSION = -1;
+
+    /**
+     * Notify Telephony for OTA emergency number database installation complete.
+     *
+     * <p> Requires permission:
+     * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
+     *
+     * @hide
+     */
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+    @SystemApi
+    public void notifyOtaEmergencyNumberDbInstalled() {
+        try {
+            ITelephony telephony = getITelephony();
+            if (telephony != null) {
+                telephony.notifyOtaEmergencyNumberDbInstalled();
+            } else {
+                throw new IllegalStateException("telephony service is null.");
+            }
+        } catch (RemoteException ex) {
+            Log.e(TAG, "notifyOtaEmergencyNumberDatabaseInstalled RemoteException", ex);
+            ex.rethrowAsRuntimeException();
+        }
+    }
+
+    /**
+     * Override the file path for testing OTA emergency number database in a file partition.
+     *
+     * @param otaFilePath The test OTA emergency number database file path;
+     *                    if "RESET", recover the original database file partition.
+     *                    Format: <root file folder>@<file path>
+     *
+     * <p> Requires permission:
+     * {@link android.Manifest.permission#READ_ACTIVE_EMERGENCY_SESSION}
+     *
+     * @hide
+     */
+    @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION)
+    @SystemApi
+    @TestApi
+    public void updateTestOtaEmergencyNumberDbFilePath(@NonNull String otaFilePath) {
+        try {
+            ITelephony telephony = getITelephony();
+            if (telephony != null) {
+                telephony.updateTestOtaEmergencyNumberDbFilePath(otaFilePath);
+            } else {
+                throw new IllegalStateException("telephony service is null.");
+            }
+        } catch (RemoteException ex) {
+            Log.e(TAG, "notifyOtaEmergencyNumberDatabaseInstalled RemoteException", ex);
+            ex.rethrowAsRuntimeException();
+        }
+    }
 
     /**
      * Returns whether {@link TelephonyManager#ACTION_EMERGENCY_ASSISTANCE emergency assistance} is
@@ -11293,6 +11348,29 @@
         return false;
     }
 
+    /**
+     * A test API to return the emergency number db version.
+     *
+     * <p>Requires Permission:
+     *   {@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE READ_PRIVILEGED_PHONE_STATE}
+     *
+     * @hide
+     */
+    @TestApi
+    @SystemApi
+    public int getEmergencyNumberDbVersion() {
+        try {
+            ITelephony telephony = getITelephony();
+            if (telephony != null) {
+                return telephony.getEmergencyNumberDbVersion(getSubId());
+            }
+        } catch (RemoteException ex) {
+            Log.e(TAG, "getEmergencyNumberDbVersion RemoteException", ex);
+            ex.rethrowAsRuntimeException();
+        }
+        return INVALID_EMERGENCY_NUMBER_DB_VERSION;
+    }
+
     /** @hide */
     @Retention(RetentionPolicy.SOURCE)
     @IntDef(prefix = {"SET_OPPORTUNISTIC_SUB"}, value = {
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index e895bae..0ec54ec 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -2048,6 +2048,21 @@
     List<String> getEmergencyNumberListTestMode();
 
     /**
+     * A test API to return the emergency number db version.
+     */
+    int getEmergencyNumberDbVersion(int subId);
+
+    /**
+     * Notify Telephony for OTA emergency number database installation complete.
+     */
+    void notifyOtaEmergencyNumberDbInstalled();
+
+    /**
+     * Override the file partition name for testing OTA emergency number database.
+     */
+    void updateTestOtaEmergencyNumberDbFilePath(String otaFilePath);
+
+    /**
      * Enable or disable a logical modem stack associated with the slotIndex.
      */
     boolean enableModemForSlot(int slotIndex, boolean enable);
diff --git a/telephony/java/com/android/internal/telephony/SmsMessageBase.java b/telephony/java/com/android/internal/telephony/SmsMessageBase.java
index f0687b4..a3efb75 100644
--- a/telephony/java/com/android/internal/telephony/SmsMessageBase.java
+++ b/telephony/java/com/android/internal/telephony/SmsMessageBase.java
@@ -20,7 +20,6 @@
 import android.os.Build;
 import android.provider.Telephony;
 import android.telephony.SmsMessage;
-import android.text.Emoji;
 
 import com.android.internal.telephony.GsmAlphabet.TextEncodingDetails;
 
@@ -403,9 +402,9 @@
             if (!breakIterator.isBoundary(nextPos)) {
                 int breakPos = breakIterator.preceding(nextPos);
                 while (breakPos + 4 <= nextPos
-                        && Emoji.isRegionalIndicatorSymbol(
+                        && isRegionalIndicatorSymbol(
                             Character.codePointAt(msgBody, breakPos))
-                        && Emoji.isRegionalIndicatorSymbol(
+                        && isRegionalIndicatorSymbol(
                             Character.codePointAt(msgBody, breakPos + 2))) {
                     // skip forward over flags (pairs of Regional Indicator Symbol)
                     breakPos += 4;
@@ -421,6 +420,11 @@
         return nextPos;
     }
 
+    private static boolean isRegionalIndicatorSymbol(int codePoint) {
+        /** Based on http://unicode.org/Public/emoji/3.0/emoji-sequences.txt */
+        return 0x1F1E6 <= codePoint && codePoint <= 0x1F1FF;
+    }
+
     /**
      * Calculate the TextEncodingDetails of a message encoded in Unicode.
      */
diff --git a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
index 6fc0228..1f7715b 100644
--- a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
+++ b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
@@ -875,9 +875,10 @@
      * Parses a broadcast SMS, possibly containing a CMAS alert.
      *
      * @param plmn the PLMN for a broadcast SMS
-     * @param subId
+     * @param slotIndex SIM slot index
+     * @param subId Subscription id
      */
-    public SmsCbMessage parseBroadcastSms(String plmn, int subId) {
+    public SmsCbMessage parseBroadcastSms(String plmn, int slotIndex, int subId) {
         BearerData bData = BearerData.decode(mEnvelope.bearerData, mEnvelope.serviceCategory);
         if (bData == null) {
             Rlog.w(LOG_TAG, "BearerData.decode() returned null");
@@ -893,7 +894,7 @@
         return new SmsCbMessage(SmsCbMessage.MESSAGE_FORMAT_3GPP2,
                 SmsCbMessage.GEOGRAPHICAL_SCOPE_PLMN_WIDE, bData.messageId, location,
                 mEnvelope.serviceCategory, bData.getLanguage(), bData.userData.payloadStr,
-                bData.priority, null, bData.cmasWarningInfo, subId);
+                bData.priority, null, bData.cmasWarningInfo, slotIndex, subId);
     }
 
     /**
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmSmsCbMessage.java b/telephony/java/com/android/internal/telephony/gsm/GsmSmsCbMessage.java
index d03419d..c16eafb 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmSmsCbMessage.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmSmsCbMessage.java
@@ -33,6 +33,7 @@
 import android.telephony.Rlog;
 import android.telephony.SmsCbLocation;
 import android.telephony.SmsCbMessage;
+import android.telephony.SubscriptionManager;
 import android.util.Pair;
 
 import com.android.internal.R;
@@ -95,6 +96,14 @@
     public static SmsCbMessage createSmsCbMessage(Context context, SmsCbHeader header,
             SmsCbLocation location, byte[][] pdus, int slotIndex)
             throws IllegalArgumentException {
+        SubscriptionManager sm = (SubscriptionManager) context.getSystemService(
+                Context.TELEPHONY_SUBSCRIPTION_SERVICE);
+        int subId = SubscriptionManager.DEFAULT_SUBSCRIPTION_ID;
+        int[] subIds = sm.getSubscriptionIds(slotIndex);
+        if (subIds != null && subIds.length > 0) {
+            subId = subIds[0];
+        }
+
         long receivedTimeMillis = System.currentTimeMillis();
         if (header.isEtwsPrimaryNotification()) {
             // ETSI TS 23.041 ETWS Primary Notification message
@@ -105,7 +114,8 @@
                     header.getSerialNumber(), location, header.getServiceCategory(), null,
                     getEtwsPrimaryMessage(context, header.getEtwsInfo().getWarningType()),
                     SmsCbMessage.MESSAGE_PRIORITY_EMERGENCY, header.getEtwsInfo(),
-                    header.getCmasInfo(), 0, null /* geometries */, receivedTimeMillis, slotIndex);
+                    header.getCmasInfo(), 0, null /* geometries */, receivedTimeMillis, slotIndex,
+                    subId);
         } else if (header.isUmtsFormat()) {
             // UMTS format has only 1 PDU
             byte[] pdu = pdus[0];
@@ -139,7 +149,7 @@
                     header.getGeographicalScope(), header.getSerialNumber(), location,
                     header.getServiceCategory(), language, body, priority,
                     header.getEtwsInfo(), header.getCmasInfo(), maximumWaitingTimeSec, geometries,
-                    receivedTimeMillis, slotIndex);
+                    receivedTimeMillis, slotIndex, subId);
         } else {
             String language = null;
             StringBuilder sb = new StringBuilder();
@@ -155,7 +165,7 @@
                     header.getGeographicalScope(), header.getSerialNumber(), location,
                     header.getServiceCategory(), language, sb.toString(), priority,
                     header.getEtwsInfo(), header.getCmasInfo(), 0, null /* geometries */,
-                    receivedTimeMillis, slotIndex);
+                    receivedTimeMillis, slotIndex, subId);
         }
     }
 
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/BackgroundDexOptServiceIntegrationTests/AndroidManifest.xml b/tests/BackgroundDexOptServiceIntegrationTests/AndroidManifest.xml
index 7291dc7..aec9f77 100644
--- a/tests/BackgroundDexOptServiceIntegrationTests/AndroidManifest.xml
+++ b/tests/BackgroundDexOptServiceIntegrationTests/AndroidManifest.xml
@@ -28,8 +28,6 @@
     <uses-permission android:name="android.permission.SET_TIME" />
     <uses-permission android:name="android.permission.UPDATE_DEVICE_STATS" />
     <uses-permission android:name="android.permission.WAKE_LOCK" />
-    <uses-permission android:name="android.permission.WRITE_DEVICE_CONFIG" />
-    <uses-permission android:name="android.permission.READ_DEVICE_CONFIG" />
 
     <application>
         <uses-library android:name="android.test.runner" />
diff --git a/tests/BackgroundDexOptServiceIntegrationTests/src/com/android/server/pm/BackgroundDexOptServiceIntegrationTests.java b/tests/BackgroundDexOptServiceIntegrationTests/src/com/android/server/pm/BackgroundDexOptServiceIntegrationTests.java
index 4cd56c3..7d826f7 100644
--- a/tests/BackgroundDexOptServiceIntegrationTests/src/com/android/server/pm/BackgroundDexOptServiceIntegrationTests.java
+++ b/tests/BackgroundDexOptServiceIntegrationTests/src/com/android/server/pm/BackgroundDexOptServiceIntegrationTests.java
@@ -22,7 +22,6 @@
 import android.os.ParcelFileDescriptor;
 import android.os.SystemProperties;
 import android.os.storage.StorageManager;
-import android.provider.DeviceConfig;
 import android.util.Log;
 
 import androidx.test.InstrumentationRegistry;
@@ -31,9 +30,7 @@
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.BeforeClass;
-import org.junit.Rule;
 import org.junit.Test;
-import org.junit.rules.ExpectedException;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
 
@@ -55,13 +52,6 @@
  * 3. Under low storage conditions and package is recently used, check
  * that dexopt upgrades test app to $(getprop pm.dexopt.bg-dexopt).
  *
- * When downgrade feature is on (downgrade_unused_apps_enabled flag is set to true):
- * 4  On low storage, check that the inactive packages are downgraded.
- * 5. On low storage, check that used packages are upgraded.
- * 6. On storage completely full, dexopt fails.
- * 7. Not on low storage, unused packages are upgraded.
- * 8. Low storage, unused app is downgraded. When app is used again, app is upgraded.
- *
  * Each test case runs "cmd package bg-dexopt-job com.android.frameworks.bgdexopttest".
  *
  * The setup for these tests make sure this package has been configured to have been recently used
@@ -69,10 +59,6 @@
  * recently used, it sets the time forward more than
  * `getprop pm.dexopt.downgrade_after_inactive_days` days.
  *
- * For some of the tests, the DeviceConfig flags inactive_app_threshold_days and
- * downgrade_unused_apps_enabled are set. These turn on/off the downgrade unused apps feature for
- * all devices and set the time threshold for unused apps.
- *
  * For tests that require low storage, the phone is filled up.
  *
  * Run with "atest BackgroundDexOptServiceIntegrationTests".
@@ -94,14 +80,10 @@
             "pm.dexopt.downgrade_after_inactive_days", 0);
     // Needs to be between 1.0 and 2.0.
     private static final double LOW_STORAGE_MULTIPLIER = 1.5;
-    private static final int DOWNGRADE_FEATURE_PKG_INACTIVE_AFTER_DAYS = 15;
 
     // The file used to fill up storage.
     private File mBigFile;
 
-    @Rule
-    public ExpectedException mExpectedException = ExpectedException.none();
-
     // Remember start time.
     @BeforeClass
     public static void setUpAll() {
@@ -214,27 +196,11 @@
         logSpaceRemaining();
     }
 
-    private void fillUpStorageCompletely() throws IOException {
-        fillUpStorage((getStorageLowBytes()));
-    }
-
     // Fill up storage so that device is in low storage condition.
     private void fillUpToLowStorage() throws IOException {
         fillUpStorage((long) (getStorageLowBytes() * LOW_STORAGE_MULTIPLIER));
     }
 
-    private void setInactivePackageThreshold(int threshold) {
-        DeviceConfig.setProperty(
-                DeviceConfig.NAMESPACE_PACKAGE_MANAGER_SERVICE,
-                "inactive_app_threshold_days", Integer.toString(threshold), false);
-    }
-
-    private void enableDowngradeFeature(boolean enabled) {
-        DeviceConfig.setProperty(
-                DeviceConfig.NAMESPACE_PACKAGE_MANAGER_SERVICE,
-                "downgrade_unused_apps_enabled", Boolean.toString(enabled), false);
-    }
-
     // TODO(aeubanks): figure out how to get scheduled bg-dexopt to run
     private static void runBackgroundDexOpt() throws IOException {
         String result = runShellCommand("cmd package bg-dexopt-job " + PACKAGE_NAME);
@@ -278,7 +244,7 @@
 
     // Test that background dexopt under normal conditions succeeds.
     @Test
-    public void testBackgroundDexOpt_normalConditions_dexOptSucceeds() throws IOException {
+    public void testBackgroundDexOpt() throws IOException {
         // Set filter to quicken.
         compilePackageWithFilter(PACKAGE_NAME, "verify");
         Assert.assertEquals("verify", getCompilerFilter(PACKAGE_NAME));
@@ -291,16 +257,17 @@
 
     // Test that background dexopt under low storage conditions upgrades used packages.
     @Test
-    public void testBackgroundDexOpt_lowStorage_usedPkgsUpgraded() throws IOException {
+    public void testBackgroundDexOptDowngradeSkipRecentlyUsedPackage() throws IOException {
         // Should be less than DOWNGRADE_AFTER_DAYS.
         long deltaDays = DOWNGRADE_AFTER_DAYS - 1;
         try {
-            enableDowngradeFeature(false);
             // Set time to future.
             setTimeFutureDays(deltaDays);
+
             // Set filter to quicken.
             compilePackageWithFilter(PACKAGE_NAME, "quicken");
             Assert.assertEquals("quicken", getCompilerFilter(PACKAGE_NAME));
+
             // Fill up storage to trigger low storage threshold.
             fillUpToLowStorage();
 
@@ -315,20 +282,18 @@
     }
 
     // Test that background dexopt under low storage conditions downgrades unused packages.
-    // This happens if the system property pm.dexopt.downgrade_after_inactive_days is set
-    // (e.g. on Android Go devices).
     @Test
-    public void testBackgroundDexOpt_lowStorage_unusedPkgsDowngraded()
-            throws IOException {
+    public void testBackgroundDexOptDowngradeSuccessful() throws IOException {
         // Should be more than DOWNGRADE_AFTER_DAYS.
         long deltaDays = DOWNGRADE_AFTER_DAYS + 1;
         try {
-            enableDowngradeFeature(false);
             // Set time to future.
             setTimeFutureDays(deltaDays);
+
             // Set filter to quicken.
             compilePackageWithFilter(PACKAGE_NAME, "quicken");
             Assert.assertEquals("quicken", getCompilerFilter(PACKAGE_NAME));
+
             // Fill up storage to trigger low storage threshold.
             fillUpToLowStorage();
 
@@ -342,134 +307,4 @@
         }
     }
 
-    // Test that the background dexopt downgrades inactive packages when the downgrade feature is
-    // enabled.
-    @Test
-    public void testBackgroundDexOpt_downgradeFeatureEnabled_lowStorage_inactivePkgsDowngraded()
-            throws IOException {
-        // Should be more than DOWNGRADE_FEATURE_PKG_INACTIVE_AFTER_DAYS.
-        long deltaDays = DOWNGRADE_FEATURE_PKG_INACTIVE_AFTER_DAYS + 1;
-        try {
-            enableDowngradeFeature(true);
-            setInactivePackageThreshold(DOWNGRADE_FEATURE_PKG_INACTIVE_AFTER_DAYS);
-            // Set time to future.
-            setTimeFutureDays(deltaDays);
-            // Set filter to quicken.
-            compilePackageWithFilter(PACKAGE_NAME, "quicken");
-            Assert.assertEquals("quicken", getCompilerFilter(PACKAGE_NAME));
-            // Fill up storage to trigger low storage threshold.
-            fillUpToLowStorage();
-
-            runBackgroundDexOpt();
-
-            // Verify that downgrade is successful.
-            Assert.assertEquals(DOWNGRADE_COMPILER_FILTER, getCompilerFilter(PACKAGE_NAME));
-        } finally {
-            // Reset time.
-            setTimeFutureDays(-deltaDays);
-        }
-    }
-
-    // Test that the background dexopt upgrades used packages when the downgrade feature is enabled.
-    // This test doesn't fill the device storage completely, but to a multiplier of the low storage
-    // threshold and this is why apps can still be optimized.
-    @Test
-    public void testBackgroundDexOpt_downgradeFeatureEnabled_lowStorage_usedPkgsUpgraded()
-            throws IOException {
-        enableDowngradeFeature(true);
-        // Set filter to quicken.
-        compilePackageWithFilter(PACKAGE_NAME, "quicken");
-        Assert.assertEquals("quicken", getCompilerFilter(PACKAGE_NAME));
-        // Fill up storage to trigger low storage threshold.
-        fillUpToLowStorage();
-
-        runBackgroundDexOpt();
-
-        /// Verify that bg-dexopt is successful in upgrading the used packages.
-        Assert.assertEquals(BG_DEXOPT_COMPILER_FILTER, getCompilerFilter(PACKAGE_NAME));
-    }
-
-    // Test that the background dexopt fails and doesn't change the compilation filter of used
-    // packages when the downgrade feature is enabled and the storage is filled up completely.
-    // The bg-dexopt shouldn't optimise nor downgrade these packages.
-    @Test
-    public void testBackgroundDexOpt_downgradeFeatureEnabled_fillUpStorageCompletely_dexOptFails()
-            throws IOException {
-        enableDowngradeFeature(true);
-        String previousCompilerFilter = getCompilerFilter(PACKAGE_NAME);
-
-        // Fill up storage completely, without using a multiplier for the low storage threshold.
-        fillUpStorageCompletely();
-
-        // When the bg dexopt runs with the storage filled up completely, it will fail.
-        mExpectedException.expect(IllegalStateException.class);
-        runBackgroundDexOpt();
-
-        /// Verify that bg-dexopt doesn't change the compilation filter of used apps.
-        Assert.assertEquals(previousCompilerFilter, getCompilerFilter(PACKAGE_NAME));
-    }
-
-    // Test that the background dexopt upgrades the unused packages when the downgrade feature is
-    // on if the device is not low on storage.
-    @Test
-    public void testBackgroundDexOpt_downgradeFeatureEnabled_notLowStorage_unusedPkgsUpgraded()
-            throws IOException {
-        // Should be more than DOWNGRADE_FEATURE_PKG_INACTIVE_AFTER_DAYS.
-        long deltaDays = DOWNGRADE_FEATURE_PKG_INACTIVE_AFTER_DAYS + 1;
-        try {
-            enableDowngradeFeature(true);
-            setInactivePackageThreshold(DOWNGRADE_FEATURE_PKG_INACTIVE_AFTER_DAYS);
-            // Set time to future.
-            setTimeFutureDays(deltaDays);
-            // Set filter to quicken.
-            compilePackageWithFilter(PACKAGE_NAME, "quicken");
-            Assert.assertEquals("quicken", getCompilerFilter(PACKAGE_NAME));
-
-            runBackgroundDexOpt();
-
-            // Verify that bg-dexopt is successful in upgrading the unused packages when the device
-            // is not low on storage.
-            Assert.assertEquals(BG_DEXOPT_COMPILER_FILTER, getCompilerFilter(PACKAGE_NAME));
-        } finally {
-            // Reset time.
-            setTimeFutureDays(-deltaDays);
-        }
-    }
-
-    // Test that when an unused package (which was downgraded) is used again, it's re-optimized when
-    // bg-dexopt runs again.
-    @Test
-    public void testBackgroundDexOpt_downgradeFeatureEnabled_downgradedPkgsUpgradedAfterUse()
-            throws IOException {
-        // Should be more than DOWNGRADE_FEATURE_PKG_INACTIVE_AFTER_DAYS.
-        long deltaDays = DOWNGRADE_FEATURE_PKG_INACTIVE_AFTER_DAYS + 1;
-        try {
-            enableDowngradeFeature(true);
-            setInactivePackageThreshold(DOWNGRADE_FEATURE_PKG_INACTIVE_AFTER_DAYS);
-            // Set time to future.
-            setTimeFutureDays(deltaDays);
-            // Fill up storage to trigger low storage threshold.
-            fillUpToLowStorage();
-            // Set filter to quicken.
-            compilePackageWithFilter(PACKAGE_NAME, "quicken");
-            Assert.assertEquals("quicken", getCompilerFilter(PACKAGE_NAME));
-
-            runBackgroundDexOpt();
-
-            // Verify that downgrade is successful.
-            Assert.assertEquals(DOWNGRADE_COMPILER_FILTER, getCompilerFilter(PACKAGE_NAME));
-
-            // Reset time.
-            setTimeFutureDays(-deltaDays);
-            deltaDays = 0;
-            runBackgroundDexOpt();
-
-            // Verify that bg-dexopt is successful in upgrading the unused packages that were used
-            // again.
-            Assert.assertEquals(BG_DEXOPT_COMPILER_FILTER, getCompilerFilter(PACKAGE_NAME));
-        } finally {
-            // Reset time.
-            setTimeFutureDays(-deltaDays);
-        }
-    }
 }
diff --git a/tests/JobSchedulerPerfTests/Android.bp b/tests/JobSchedulerPerfTests/Android.bp
index c51b811..2ae8c33 100644
--- a/tests/JobSchedulerPerfTests/Android.bp
+++ b/tests/JobSchedulerPerfTests/Android.bp
@@ -19,7 +19,7 @@
         "androidx.test.rules",
         "apct-perftests-utils",
         "services",
-        "jobscheduler-service",
+        "service-jobscheduler",
     ],
     platform_apis: true,
     certificate: "platform",
diff --git a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java
index 599ee56..abe6c61 100644
--- a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java
+++ b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java
@@ -1054,4 +1054,48 @@
             InstallUtils.dropShellPermissionIdentity();
         }
     }
+
+    @Test
+    public void testEnableRollbackTimeoutFailsRollback_MultiPackage() throws Exception {
+        try {
+            InstallUtils.adoptShellPermissionIdentity(
+                    Manifest.permission.INSTALL_PACKAGES,
+                    Manifest.permission.DELETE_PACKAGES,
+                    Manifest.permission.TEST_MANAGE_ROLLBACKS,
+                    Manifest.permission.MANAGE_ROLLBACKS,
+                    Manifest.permission.WRITE_DEVICE_CONFIG);
+
+            DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ROLLBACK,
+                    PROPERTY_ENABLE_ROLLBACK_TIMEOUT_MILLIS,
+                    Long.toString(5000), false /* makeDefault*/);
+            RollbackManager rm = RollbackUtils.getRollbackManager();
+
+            Uninstall.packages(TestApp.A, TestApp.B);
+            Install.multi(TestApp.A1, TestApp.B1).commit();
+            waitForUnavailableRollback(TestApp.A);
+
+            // Block the 2nd session for 10s so it will not be able to enable the rollback in time.
+            rm.blockRollbackManager(TimeUnit.SECONDS.toMillis(0));
+            rm.blockRollbackManager(TimeUnit.SECONDS.toMillis(10));
+            Install.multi(TestApp.A2, TestApp.B2).setEnableRollback().commit();
+
+            assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2);
+            assertThat(InstallUtils.getInstalledVersion(TestApp.B)).isEqualTo(2);
+
+            // Give plenty of time for RollbackManager to unblock and attempt
+            // to make the rollback available before asserting that the
+            // rollback was not made available.
+            Thread.sleep(TimeUnit.SECONDS.toMillis(2));
+
+            List<RollbackInfo> available = rm.getAvailableRollbacks();
+            assertThat(getUniqueRollbackInfoForPackage(available, TestApp.A)).isNull();
+            assertThat(getUniqueRollbackInfoForPackage(available, TestApp.B)).isNull();
+        } finally {
+            //setting the timeout back to default
+            DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ROLLBACK,
+                    PROPERTY_ENABLE_ROLLBACK_TIMEOUT_MILLIS,
+                    null, false /* makeDefault*/);
+            InstallUtils.dropShellPermissionIdentity();
+        }
+    }
 }
diff --git a/tests/net/java/android/net/ip/InterfaceControllerTest.java b/tests/net/java/android/net/ip/InterfaceControllerTest.java
deleted file mode 100644
index 7a56b3a..0000000
--- a/tests/net/java/android/net/ip/InterfaceControllerTest.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.ip;
-
-import static org.junit.Assert.assertArrayEquals;
-import static org.junit.Assert.assertEquals;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-
-import android.net.INetd;
-import android.net.InetAddresses;
-import android.net.InterfaceConfigurationParcel;
-import android.net.LinkAddress;
-import android.net.util.SharedLog;
-
-import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Captor;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-@RunWith(AndroidJUnit4.class)
-@SmallTest
-public class InterfaceControllerTest {
-    private static final String TEST_IFACE = "testif";
-    private static final String TEST_IPV4_ADDR = "192.168.123.28";
-    private static final int TEST_PREFIXLENGTH = 31;
-
-    @Mock private INetd mNetd;
-    @Mock private SharedLog mLog;
-    @Captor private ArgumentCaptor<InterfaceConfigurationParcel> mConfigCaptor;
-
-    private InterfaceController mController;
-
-    @Before
-    public void setUp() throws Exception {
-        MockitoAnnotations.initMocks(this);
-        mController = new InterfaceController(TEST_IFACE, mNetd, mLog);
-
-        doNothing().when(mNetd).interfaceSetCfg(mConfigCaptor.capture());
-    }
-
-    @Test
-    public void testSetIPv4Address() throws Exception {
-        mController.setIPv4Address(
-                new LinkAddress(InetAddresses.parseNumericAddress(TEST_IPV4_ADDR),
-                        TEST_PREFIXLENGTH));
-        verify(mNetd, times(1)).interfaceSetCfg(any());
-        final InterfaceConfigurationParcel parcel = mConfigCaptor.getValue();
-        assertEquals(TEST_IFACE, parcel.ifName);
-        assertEquals(TEST_IPV4_ADDR, parcel.ipv4Addr);
-        assertEquals(TEST_PREFIXLENGTH, parcel.prefixLength);
-        assertEquals("", parcel.hwAddr);
-        assertArrayEquals(new String[0], parcel.flags);
-    }
-
-    @Test
-    public void testClearIPv4Address() throws Exception {
-        mController.clearIPv4Address();
-        verify(mNetd, times(1)).interfaceSetCfg(any());
-        final InterfaceConfigurationParcel parcel = mConfigCaptor.getValue();
-        assertEquals(TEST_IFACE, parcel.ifName);
-        assertEquals("0.0.0.0", parcel.ipv4Addr);
-        assertEquals(0, parcel.prefixLength);
-        assertEquals("", parcel.hwAddr);
-        assertArrayEquals(new String[0], parcel.flags);
-    }
-}
diff --git a/tests/net/java/android/net/netlink/ConntrackMessageTest.java b/tests/net/java/android/net/netlink/ConntrackMessageTest.java
deleted file mode 100644
index 5c86757..0000000
--- a/tests/net/java/android/net/netlink/ConntrackMessageTest.java
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.netlink;
-
-import static org.junit.Assert.assertArrayEquals;
-import static org.junit.Assume.assumeTrue;
-
-import android.system.OsConstants;
-
-import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
-
-import libcore.util.HexEncoding;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.net.Inet4Address;
-import java.net.InetAddress;
-import java.nio.ByteOrder;
-
-@RunWith(AndroidJUnit4.class)
-@SmallTest
-public class ConntrackMessageTest {
-    private static final boolean USING_LE = (ByteOrder.nativeOrder() == ByteOrder.LITTLE_ENDIAN);
-
-    // Example 1: TCP (192.168.43.209, 44333) -> (23.211.13.26, 443)
-    public static final String CT_V4UPDATE_TCP_HEX =
-            // struct nlmsghdr
-            "50000000" +      // length = 80
-            "0001" +          // type = (1 << 8) | 0
-            "0501" +          // flags
-            "01000000" +      // seqno = 1
-            "00000000" +      // pid = 0
-            // struct nfgenmsg
-            "02" +            // nfgen_family  = AF_INET
-            "00" +            // version = NFNETLINK_V0
-            "0000" +          // res_id
-            // struct nlattr
-            "3400" +          // nla_len = 52
-            "0180" +          // nla_type = nested CTA_TUPLE_ORIG
-                // struct nlattr
-                "1400" +      // nla_len = 20
-                "0180" +      // nla_type = nested CTA_TUPLE_IP
-                    "0800 0100 C0A82BD1" +  // nla_type=CTA_IP_V4_SRC, ip=192.168.43.209
-                    "0800 0200 17D30D1A" +  // nla_type=CTA_IP_V4_DST, ip=23.211.13.26
-                // struct nlattr
-                "1C00" +      // nla_len = 28
-                "0280" +      // nla_type = nested CTA_TUPLE_PROTO
-                    "0500 0100 06 000000" +  // nla_type=CTA_PROTO_NUM, proto=6
-                    "0600 0200 AD2D 0000" +  // nla_type=CTA_PROTO_SRC_PORT, port=44333 (big endian)
-                    "0600 0300 01BB 0000" +  // nla_type=CTA_PROTO_DST_PORT, port=443 (big endian)
-            // struct nlattr
-            "0800" +          // nla_len = 8
-            "0700" +          // nla_type = CTA_TIMEOUT
-            "00069780";       // nla_value = 432000 (big endian)
-    public static final byte[] CT_V4UPDATE_TCP_BYTES =
-            HexEncoding.decode(CT_V4UPDATE_TCP_HEX.replaceAll(" ", "").toCharArray(), false);
-
-    // Example 2: UDP (100.96.167.146, 37069) -> (216.58.197.10, 443)
-    public static final String CT_V4UPDATE_UDP_HEX =
-            // struct nlmsghdr
-            "50000000" +      // length = 80
-            "0001" +          // type = (1 << 8) | 0
-            "0501" +          // flags
-            "01000000" +      // seqno = 1
-            "00000000" +      // pid = 0
-            // struct nfgenmsg
-            "02" +            // nfgen_family  = AF_INET
-            "00" +            // version = NFNETLINK_V0
-            "0000" +          // res_id
-            // struct nlattr
-            "3400" +          // nla_len = 52
-            "0180" +          // nla_type = nested CTA_TUPLE_ORIG
-                // struct nlattr
-                "1400" +      // nla_len = 20
-                "0180" +      // nla_type = nested CTA_TUPLE_IP
-                    "0800 0100 6460A792" +  // nla_type=CTA_IP_V4_SRC, ip=100.96.167.146
-                    "0800 0200 D83AC50A" +  // nla_type=CTA_IP_V4_DST, ip=216.58.197.10
-                // struct nlattr
-                "1C00" +      // nla_len = 28
-                "0280" +      // nla_type = nested CTA_TUPLE_PROTO
-                    "0500 0100 11 000000" +  // nla_type=CTA_PROTO_NUM, proto=17
-                    "0600 0200 90CD 0000" +  // nla_type=CTA_PROTO_SRC_PORT, port=37069 (big endian)
-                    "0600 0300 01BB 0000" +  // nla_type=CTA_PROTO_DST_PORT, port=443 (big endian)
-            // struct nlattr
-            "0800" +          // nla_len = 8
-            "0700" +          // nla_type = CTA_TIMEOUT
-            "000000B4";       // nla_value = 180 (big endian)
-    public static final byte[] CT_V4UPDATE_UDP_BYTES =
-            HexEncoding.decode(CT_V4UPDATE_UDP_HEX.replaceAll(" ", "").toCharArray(), false);
-
-    @Test
-    public void testConntrackIPv4TcpTimeoutUpdate() throws Exception {
-        assumeTrue(USING_LE);
-
-        final byte[] tcp = ConntrackMessage.newIPv4TimeoutUpdateRequest(
-                OsConstants.IPPROTO_TCP,
-                (Inet4Address) InetAddress.getByName("192.168.43.209"), 44333,
-                (Inet4Address) InetAddress.getByName("23.211.13.26"), 443,
-                432000);
-        assertArrayEquals(CT_V4UPDATE_TCP_BYTES, tcp);
-    }
-
-    @Test
-    public void testConntrackIPv4UdpTimeoutUpdate() throws Exception {
-        assumeTrue(USING_LE);
-
-        final byte[] udp = ConntrackMessage.newIPv4TimeoutUpdateRequest(
-                OsConstants.IPPROTO_UDP,
-                (Inet4Address) InetAddress.getByName("100.96.167.146"), 37069,
-                (Inet4Address) InetAddress.getByName("216.58.197.10"), 443,
-                180);
-        assertArrayEquals(CT_V4UPDATE_UDP_BYTES, udp);
-    }
-}
diff --git a/tests/net/java/android/net/netlink/InetDiagSocketTest.java b/tests/net/java/android/net/netlink/InetDiagSocketTest.java
deleted file mode 100644
index 84c5784..0000000
--- a/tests/net/java/android/net/netlink/InetDiagSocketTest.java
+++ /dev/null
@@ -1,448 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.netlink;
-
-import static android.net.netlink.StructNlMsgHdr.NLM_F_DUMP;
-import static android.net.netlink.StructNlMsgHdr.NLM_F_REQUEST;
-import static android.system.OsConstants.AF_INET;
-import static android.system.OsConstants.AF_INET6;
-import static android.system.OsConstants.IPPROTO_TCP;
-import static android.system.OsConstants.IPPROTO_UDP;
-import static android.system.OsConstants.SOCK_DGRAM;
-import static android.system.OsConstants.SOCK_STREAM;
-
-import static org.junit.Assert.assertArrayEquals;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-import android.app.Instrumentation;
-import android.content.Context;
-import android.net.ConnectivityManager;
-import android.net.netlink.StructNlMsgHdr;
-import android.os.Process;
-import android.system.Os;
-
-import androidx.test.InstrumentationRegistry;
-import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
-
-import libcore.util.HexEncoding;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.io.FileDescriptor;
-import java.net.Inet4Address;
-import java.net.Inet6Address;
-import java.net.InetAddress;
-import java.net.InetSocketAddress;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-
-@RunWith(AndroidJUnit4.class)
-@SmallTest
-public class InetDiagSocketTest {
-    private final String TAG = "InetDiagSocketTest";
-    private ConnectivityManager mCm;
-    private Context mContext;
-    private final static int SOCKET_TIMEOUT_MS = 100;
-
-    @Before
-    public void setUp() throws Exception {
-        Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
-        mContext = instrumentation.getTargetContext();
-        mCm = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
-    }
-
-    private class Connection {
-        public int socketDomain;
-        public int socketType;
-        public InetAddress localAddress;
-        public InetAddress remoteAddress;
-        public InetAddress localhostAddress;
-        public InetSocketAddress local;
-        public InetSocketAddress remote;
-        public int protocol;
-        public FileDescriptor localFd;
-        public FileDescriptor remoteFd;
-
-        public FileDescriptor createSocket() throws Exception {
-            return Os.socket(socketDomain, socketType, protocol);
-        }
-
-        public Connection(String to, String from) throws Exception {
-            remoteAddress = InetAddress.getByName(to);
-            if (from != null) {
-                localAddress = InetAddress.getByName(from);
-            } else {
-                localAddress = (remoteAddress instanceof Inet4Address) ?
-                        Inet4Address.getByName("localhost") : Inet6Address.getByName("::");
-            }
-            if ((localAddress instanceof Inet4Address) && (remoteAddress instanceof Inet4Address)) {
-                socketDomain = AF_INET;
-                localhostAddress = Inet4Address.getByName("localhost");
-            } else {
-                socketDomain = AF_INET6;
-                localhostAddress = Inet6Address.getByName("::");
-            }
-        }
-
-        public void close() throws Exception {
-            Os.close(localFd);
-        }
-    }
-
-    private class TcpConnection extends Connection {
-        public TcpConnection(String to, String from) throws Exception {
-            super(to, from);
-            protocol = IPPROTO_TCP;
-            socketType = SOCK_STREAM;
-
-            remoteFd = createSocket();
-            Os.bind(remoteFd, remoteAddress, 0);
-            Os.listen(remoteFd, 10);
-            int remotePort = ((InetSocketAddress) Os.getsockname(remoteFd)).getPort();
-
-            localFd = createSocket();
-            Os.bind(localFd, localAddress, 0);
-            Os.connect(localFd, remoteAddress, remotePort);
-
-            local = (InetSocketAddress) Os.getsockname(localFd);
-            remote = (InetSocketAddress) Os.getpeername(localFd);
-        }
-
-        public void close() throws Exception {
-            super.close();
-            Os.close(remoteFd);
-        }
-    }
-    private class UdpConnection extends Connection {
-        public UdpConnection(String to, String from) throws Exception {
-            super(to, from);
-            protocol = IPPROTO_UDP;
-            socketType = SOCK_DGRAM;
-
-            remoteFd = null;
-            localFd = createSocket();
-            Os.bind(localFd, localAddress, 0);
-
-            Os.connect(localFd, remoteAddress, 7);
-            local = (InetSocketAddress) Os.getsockname(localFd);
-            remote = new InetSocketAddress(remoteAddress, 7);
-        }
-    }
-
-    private void checkConnectionOwnerUid(int protocol, InetSocketAddress local,
-                                         InetSocketAddress remote, boolean expectSuccess) {
-        final int uid = mCm.getConnectionOwnerUid(protocol, local, remote);
-
-        if (expectSuccess) {
-            assertEquals(Process.myUid(), uid);
-        } else {
-            assertNotEquals(Process.myUid(), uid);
-        }
-    }
-
-    private int findLikelyFreeUdpPort(UdpConnection conn) throws Exception {
-        UdpConnection udp = new UdpConnection(conn.remoteAddress.getHostAddress(),
-                conn.localAddress.getHostAddress());
-        final int localPort = udp.local.getPort();
-        udp.close();
-        return localPort;
-    }
-
-    /**
-     * Create a test connection for UDP and TCP sockets and verify that this
-     * {protocol, local, remote} socket result in receiving a valid UID.
-     */
-    public void checkGetConnectionOwnerUid(String to, String from) throws Exception {
-        TcpConnection tcp = new TcpConnection(to, from);
-        checkConnectionOwnerUid(tcp.protocol, tcp.local, tcp.remote, true);
-        checkConnectionOwnerUid(IPPROTO_UDP, tcp.local, tcp.remote, false);
-        checkConnectionOwnerUid(tcp.protocol, new InetSocketAddress(0), tcp.remote, false);
-        checkConnectionOwnerUid(tcp.protocol, tcp.local, new InetSocketAddress(0), false);
-        tcp.close();
-
-        UdpConnection udp = new UdpConnection(to,from);
-        checkConnectionOwnerUid(udp.protocol, udp.local, udp.remote, true);
-        checkConnectionOwnerUid(IPPROTO_TCP, udp.local, udp.remote, false);
-        checkConnectionOwnerUid(udp.protocol, new InetSocketAddress(findLikelyFreeUdpPort(udp)),
-                udp.remote, false);
-        udp.close();
-    }
-
-    @Test
-    public void testGetConnectionOwnerUid() throws Exception {
-        checkGetConnectionOwnerUid("::", null);
-        checkGetConnectionOwnerUid("::", "::");
-        checkGetConnectionOwnerUid("0.0.0.0", null);
-        checkGetConnectionOwnerUid("0.0.0.0", "0.0.0.0");
-        checkGetConnectionOwnerUid("127.0.0.1", null);
-        checkGetConnectionOwnerUid("127.0.0.1", "127.0.0.2");
-        checkGetConnectionOwnerUid("::1", null);
-        checkGetConnectionOwnerUid("::1", "::1");
-    }
-
-    /* Verify fix for b/141603906 */
-    @Test
-    public void testB141603906() throws Exception {
-        final InetSocketAddress src = new InetSocketAddress(0);
-        final InetSocketAddress dst = new InetSocketAddress(0);
-        final int numThreads = 8;
-        final int numSockets = 5000;
-        final Thread[] threads = new Thread[numThreads];
-
-        for (int i = 0; i < numThreads; i++) {
-            threads[i] = new Thread(() -> {
-                for (int j = 0; j < numSockets; j++) {
-                    mCm.getConnectionOwnerUid(IPPROTO_TCP, src, dst);
-                }
-            });
-        }
-
-        for (Thread thread : threads) {
-            thread.start();
-        }
-
-        for (Thread thread : threads) {
-            thread.join();
-        }
-    }
-
-    // Hexadecimal representation of InetDiagReqV2 request.
-    private static final String INET_DIAG_REQ_V2_UDP_INET4_HEX =
-            // struct nlmsghdr
-            "48000000" +     // length = 72
-            "1400" +         // type = SOCK_DIAG_BY_FAMILY
-            "0103" +         // flags = NLM_F_REQUEST | NLM_F_DUMP
-            "00000000" +     // seqno
-            "00000000" +     // pid (0 == kernel)
-            // struct inet_diag_req_v2
-            "02" +           // family = AF_INET
-            "11" +           // protcol = IPPROTO_UDP
-            "00" +           // idiag_ext
-            "00" +           // pad
-            "ffffffff" +     // idiag_states
-            // inet_diag_sockid
-            "a5de" +         // idiag_sport = 42462
-            "b971" +         // idiag_dport = 47473
-            "0a006402000000000000000000000000" + // idiag_src = 10.0.100.2
-            "08080808000000000000000000000000" + // idiag_dst = 8.8.8.8
-            "00000000" +     // idiag_if
-            "ffffffffffffffff"; // idiag_cookie = INET_DIAG_NOCOOKIE
-    private static final byte[] INET_DIAG_REQ_V2_UDP_INET4_BYTES =
-            HexEncoding.decode(INET_DIAG_REQ_V2_UDP_INET4_HEX.toCharArray(), false);
-
-    @Test
-    public void testInetDiagReqV2UdpInet4() throws Exception {
-        InetSocketAddress local = new InetSocketAddress(InetAddress.getByName("10.0.100.2"),
-                42462);
-        InetSocketAddress remote = new InetSocketAddress(InetAddress.getByName("8.8.8.8"),
-                47473);
-        final byte[] msg = InetDiagMessage.InetDiagReqV2(IPPROTO_UDP, local, remote, AF_INET,
-                (short) (NLM_F_REQUEST | NLM_F_DUMP));
-        assertArrayEquals(INET_DIAG_REQ_V2_UDP_INET4_BYTES, msg);
-    }
-
-    // Hexadecimal representation of InetDiagReqV2 request.
-    private static final String INET_DIAG_REQ_V2_TCP_INET6_HEX =
-            // struct nlmsghdr
-            "48000000" +     // length = 72
-            "1400" +         // type = SOCK_DIAG_BY_FAMILY
-            "0100" +         // flags = NLM_F_REQUEST
-            "00000000" +     // seqno
-            "00000000" +     // pid (0 == kernel)
-            // struct inet_diag_req_v2
-            "0a" +           // family = AF_INET6
-            "06" +           // protcol = IPPROTO_TCP
-            "00" +           // idiag_ext
-            "00" +           // pad
-            "ffffffff" +     // idiag_states
-                // inet_diag_sockid
-                "a5de" +         // idiag_sport = 42462
-                "b971" +         // idiag_dport = 47473
-                "fe8000000000000086c9b2fffe6aed4b" + // idiag_src = fe80::86c9:b2ff:fe6a:ed4b
-                "08080808000000000000000000000000" + // idiag_dst = 8.8.8.8
-                "00000000" +     // idiag_if
-                "ffffffffffffffff"; // idiag_cookie = INET_DIAG_NOCOOKIE
-    private static final byte[] INET_DIAG_REQ_V2_TCP_INET6_BYTES =
-            HexEncoding.decode(INET_DIAG_REQ_V2_TCP_INET6_HEX.toCharArray(), false);
-
-    @Test
-    public void testInetDiagReqV2TcpInet6() throws Exception {
-        InetSocketAddress local = new InetSocketAddress(
-                InetAddress.getByName("fe80::86c9:b2ff:fe6a:ed4b"), 42462);
-        InetSocketAddress remote = new InetSocketAddress(InetAddress.getByName("8.8.8.8"),
-                47473);
-        byte[] msg = InetDiagMessage.InetDiagReqV2(IPPROTO_TCP, local, remote, AF_INET6,
-                NLM_F_REQUEST);
-
-        assertArrayEquals(INET_DIAG_REQ_V2_TCP_INET6_BYTES, msg);
-    }
-
-    // Hexadecimal representation of InetDiagReqV2 request with extension, INET_DIAG_INFO.
-    private static final String INET_DIAG_REQ_V2_TCP_INET_INET_DIAG_HEX =
-            // struct nlmsghdr
-            "48000000" +     // length = 72
-            "1400" +         // type = SOCK_DIAG_BY_FAMILY
-            "0100" +         // flags = NLM_F_REQUEST
-            "00000000" +     // seqno
-            "00000000" +     // pid (0 == kernel)
-            // struct inet_diag_req_v2
-            "02" +           // family = AF_INET
-            "06" +           // protcol = IPPROTO_TCP
-            "02" +           // idiag_ext = INET_DIAG_INFO
-            "00" +           // pad
-            "ffffffff" +   // idiag_states
-            // inet_diag_sockid
-            "3039" +         // idiag_sport = 12345
-            "d431" +         // idiag_dport = 54321
-            "01020304000000000000000000000000" + // idiag_src = 1.2.3.4
-            "08080404000000000000000000000000" + // idiag_dst = 8.8.4.4
-            "00000000" +     // idiag_if
-            "ffffffffffffffff"; // idiag_cookie = INET_DIAG_NOCOOKIE
-
-    private static final byte[] INET_DIAG_REQ_V2_TCP_INET_INET_DIAG_BYTES =
-            HexEncoding.decode(INET_DIAG_REQ_V2_TCP_INET_INET_DIAG_HEX.toCharArray(), false);
-    private static final int TCP_ALL_STATES = 0xffffffff;
-    @Test
-    public void testInetDiagReqV2TcpInetWithExt() throws Exception {
-        InetSocketAddress local = new InetSocketAddress(
-                InetAddress.getByName("1.2.3.4"), 12345);
-        InetSocketAddress remote = new InetSocketAddress(InetAddress.getByName("8.8.4.4"),
-                54321);
-        byte[] msg = InetDiagMessage.InetDiagReqV2(IPPROTO_TCP, local, remote, AF_INET,
-                NLM_F_REQUEST, 0 /* pad */, 2 /* idiagExt */, TCP_ALL_STATES);
-
-        assertArrayEquals(INET_DIAG_REQ_V2_TCP_INET_INET_DIAG_BYTES, msg);
-
-        local = new InetSocketAddress(
-                InetAddress.getByName("fe80::86c9:b2ff:fe6a:ed4b"), 42462);
-        remote = new InetSocketAddress(InetAddress.getByName("8.8.8.8"),
-                47473);
-        msg = InetDiagMessage.InetDiagReqV2(IPPROTO_TCP, local, remote, AF_INET6,
-                NLM_F_REQUEST, 0 /* pad */, 0 /* idiagExt */, TCP_ALL_STATES);
-
-        assertArrayEquals(INET_DIAG_REQ_V2_TCP_INET6_BYTES, msg);
-    }
-
-    // Hexadecimal representation of InetDiagReqV2 request with no socket specified.
-    private static final String INET_DIAG_REQ_V2_TCP_INET6_NO_ID_SPECIFIED_HEX =
-            // struct nlmsghdr
-            "48000000" +     // length = 72
-            "1400" +         // type = SOCK_DIAG_BY_FAMILY
-            "0100" +         // flags = NLM_F_REQUEST
-            "00000000" +     // seqno
-            "00000000" +     // pid (0 == kernel)
-            // struct inet_diag_req_v2
-            "0a" +           // family = AF_INET6
-            "06" +           // protcol = IPPROTO_TCP
-            "00" +           // idiag_ext
-            "00" +           // pad
-            "ffffffff" +     // idiag_states
-            // inet_diag_sockid
-            "0000" +         // idiag_sport
-            "0000" +         // idiag_dport
-            "00000000000000000000000000000000" + // idiag_src
-            "00000000000000000000000000000000" + // idiag_dst
-            "00000000" +     // idiag_if
-            "0000000000000000"; // idiag_cookie
-
-    private static final byte[] INET_DIAG_REQ_V2_TCP_INET6_NO_ID_SPECIFED_BYTES =
-            HexEncoding.decode(INET_DIAG_REQ_V2_TCP_INET6_NO_ID_SPECIFIED_HEX.toCharArray(), false);
-
-    @Test
-    public void testInetDiagReqV2TcpInet6NoIdSpecified() throws Exception {
-        InetSocketAddress local = new InetSocketAddress(
-                InetAddress.getByName("fe80::fe6a:ed4b"), 12345);
-        InetSocketAddress remote = new InetSocketAddress(InetAddress.getByName("8.8.4.4"),
-                54321);
-        // Verify no socket specified if either local or remote socket address is null.
-        byte[] msgExt = InetDiagMessage.InetDiagReqV2(IPPROTO_TCP, null, null, AF_INET6,
-                NLM_F_REQUEST, 0 /* pad */, 0 /* idiagExt */, TCP_ALL_STATES);
-        byte[] msg;
-        try {
-            msg = InetDiagMessage.InetDiagReqV2(IPPROTO_TCP, null, remote, AF_INET6,
-                    NLM_F_REQUEST);
-            fail("Both remote and local should be null, expected UnknownHostException");
-        } catch (NullPointerException e) {
-        }
-
-        try {
-            msg = InetDiagMessage.InetDiagReqV2(IPPROTO_TCP, local, null, AF_INET6,
-                    NLM_F_REQUEST, 0 /* pad */, 0 /* idiagExt */, TCP_ALL_STATES);
-            fail("Both remote and local should be null, expected UnknownHostException");
-        } catch (NullPointerException e) {
-        }
-
-        msg = InetDiagMessage.InetDiagReqV2(IPPROTO_TCP, null, null, AF_INET6,
-                NLM_F_REQUEST, 0 /* pad */, 0 /* idiagExt */, TCP_ALL_STATES);
-        assertArrayEquals(INET_DIAG_REQ_V2_TCP_INET6_NO_ID_SPECIFED_BYTES, msg);
-        assertArrayEquals(INET_DIAG_REQ_V2_TCP_INET6_NO_ID_SPECIFED_BYTES, msgExt);
-    }
-
-    // Hexadecimal representation of InetDiagReqV2 request.
-    private static final String INET_DIAG_MSG_HEX =
-            // struct nlmsghdr
-            "58000000" +     // length = 88
-            "1400" +         // type = SOCK_DIAG_BY_FAMILY
-            "0200" +         // flags = NLM_F_MULTI
-            "00000000" +     // seqno
-            "f5220000" +     // pid (0 == kernel)
-            // struct inet_diag_msg
-            "0a" +           // family = AF_INET6
-            "01" +           // idiag_state
-            "00" +           // idiag_timer
-            "00" +           // idiag_retrans
-                // inet_diag_sockid
-                "a817" +     // idiag_sport = 43031
-                "960f" +     // idiag_dport = 38415
-                "fe8000000000000086c9b2fffe6aed4b" + // idiag_src = fe80::86c9:b2ff:fe6a:ed4b
-                "00000000000000000000ffff08080808" + // idiag_dst = 8.8.8.8
-                "00000000" + // idiag_if
-                "ffffffffffffffff" + // idiag_cookie = INET_DIAG_NOCOOKIE
-            "00000000" +     // idiag_expires
-            "00000000" +     // idiag_rqueue
-            "00000000" +     // idiag_wqueue
-            "a3270000" +     // idiag_uid
-            "A57E1900";      // idiag_inode
-    private static final byte[] INET_DIAG_MSG_BYTES =
-            HexEncoding.decode(INET_DIAG_MSG_HEX.toCharArray(), false);
-
-    @Test
-    public void testParseInetDiagResponse() throws Exception {
-        final ByteBuffer byteBuffer = ByteBuffer.wrap(INET_DIAG_MSG_BYTES);
-        byteBuffer.order(ByteOrder.LITTLE_ENDIAN);
-        final NetlinkMessage msg = NetlinkMessage.parse(byteBuffer);
-        assertNotNull(msg);
-
-        assertTrue(msg instanceof InetDiagMessage);
-        final InetDiagMessage inetDiagMsg = (InetDiagMessage) msg;
-        assertEquals(10147, inetDiagMsg.mStructInetDiagMsg.idiag_uid);
-
-        final StructNlMsgHdr hdr = inetDiagMsg.getHeader();
-        assertNotNull(hdr);
-        assertEquals(NetlinkConstants.SOCK_DIAG_BY_FAMILY, hdr.nlmsg_type);
-        assertEquals(StructNlMsgHdr.NLM_F_MULTI, hdr.nlmsg_flags);
-        assertEquals(0, hdr.nlmsg_seq);
-        assertEquals(8949, hdr.nlmsg_pid);
-    }
-}
diff --git a/tests/net/java/android/net/netlink/NetlinkErrorMessageTest.java b/tests/net/java/android/net/netlink/NetlinkErrorMessageTest.java
deleted file mode 100644
index 44ab605..0000000
--- a/tests/net/java/android/net/netlink/NetlinkErrorMessageTest.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.netlink;
-
-import static android.net.netlink.StructNlMsgHdr.NLM_F_ACK;
-import static android.net.netlink.StructNlMsgHdr.NLM_F_REPLACE;
-import static android.net.netlink.StructNlMsgHdr.NLM_F_REQUEST;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-
-import android.net.netlink.NetlinkConstants;
-import android.net.netlink.NetlinkErrorMessage;
-import android.net.netlink.NetlinkMessage;
-import android.net.netlink.StructNlMsgErr;
-
-import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
-
-import libcore.util.HexEncoding;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-
-@RunWith(AndroidJUnit4.class)
-@SmallTest
-public class NetlinkErrorMessageTest {
-    private final String TAG = "NetlinkErrorMessageTest";
-
-    // Hexadecimal representation of packet capture.
-    public static final String NLM_ERROR_OK_HEX =
-            // struct nlmsghdr
-            "24000000" +     // length = 36
-            "0200"     +     // type = 2 (NLMSG_ERROR)
-            "0000"     +     // flags
-            "26350000" +     // seqno
-            "64100000" +     // pid = userspace process
-            // error integer
-            "00000000" +     // "errno" (0 == OK)
-            // struct nlmsghdr
-            "30000000" +     // length (48) of original request
-            "1C00"     +     // type = 28 (RTM_NEWNEIGH)
-            "0501"     +     // flags (NLM_F_REQUEST | NLM_F_ACK | NLM_F_REPLACE)
-            "26350000" +     // seqno
-            "00000000";      // pid = kernel
-    public static final byte[] NLM_ERROR_OK =
-            HexEncoding.decode(NLM_ERROR_OK_HEX.toCharArray(), false);
-
-    @Test
-    public void testParseNlmErrorOk() {
-        final ByteBuffer byteBuffer = ByteBuffer.wrap(NLM_ERROR_OK);
-        byteBuffer.order(ByteOrder.LITTLE_ENDIAN);  // For testing.
-        final NetlinkMessage msg = NetlinkMessage.parse(byteBuffer);
-        assertNotNull(msg);
-        assertTrue(msg instanceof NetlinkErrorMessage);
-        final NetlinkErrorMessage errorMsg = (NetlinkErrorMessage) msg;
-
-        final StructNlMsgHdr hdr = errorMsg.getHeader();
-        assertNotNull(hdr);
-        assertEquals(36, hdr.nlmsg_len);
-        assertEquals(NetlinkConstants.NLMSG_ERROR, hdr.nlmsg_type);
-        assertEquals(0, hdr.nlmsg_flags);
-        assertEquals(13606, hdr.nlmsg_seq);
-        assertEquals(4196, hdr.nlmsg_pid);
-
-        final StructNlMsgErr err = errorMsg.getNlMsgError();
-        assertNotNull(err);
-        assertEquals(0, err.error);
-        assertNotNull(err.msg);
-        assertEquals(48, err.msg.nlmsg_len);
-        assertEquals(NetlinkConstants.RTM_NEWNEIGH, err.msg.nlmsg_type);
-        assertEquals((NLM_F_REQUEST | NLM_F_ACK | NLM_F_REPLACE), err.msg.nlmsg_flags);
-        assertEquals(13606, err.msg.nlmsg_seq);
-        assertEquals(0, err.msg.nlmsg_pid);
-    }
-}
diff --git a/tests/net/java/android/net/netlink/NetlinkSocketTest.java b/tests/net/java/android/net/netlink/NetlinkSocketTest.java
deleted file mode 100644
index 3916578..0000000
--- a/tests/net/java/android/net/netlink/NetlinkSocketTest.java
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.netlink;
-
-import static android.net.netlink.NetlinkSocket.DEFAULT_RECV_BUFSIZE;
-import static android.system.OsConstants.NETLINK_ROUTE;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-
-import android.net.netlink.NetlinkSocket;
-import android.net.netlink.RtNetlinkNeighborMessage;
-import android.net.netlink.StructNlMsgHdr;
-import android.system.NetlinkSocketAddress;
-import android.system.Os;
-
-import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
-
-import libcore.io.IoUtils;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.io.FileDescriptor;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-
-@RunWith(AndroidJUnit4.class)
-@SmallTest
-public class NetlinkSocketTest {
-    private final String TAG = "NetlinkSocketTest";
-
-    @Test
-    public void testBasicWorkingGetNeighborsQuery() throws Exception {
-        final FileDescriptor fd = NetlinkSocket.forProto(NETLINK_ROUTE);
-        assertNotNull(fd);
-
-        NetlinkSocket.connectToKernel(fd);
-
-        final NetlinkSocketAddress localAddr = (NetlinkSocketAddress) Os.getsockname(fd);
-        assertNotNull(localAddr);
-        assertEquals(0, localAddr.getGroupsMask());
-        assertTrue(0 != localAddr.getPortId());
-
-        final int TEST_SEQNO = 5;
-        final byte[] req = RtNetlinkNeighborMessage.newGetNeighborsRequest(TEST_SEQNO);
-        assertNotNull(req);
-
-        final long TIMEOUT = 500;
-        assertEquals(req.length, NetlinkSocket.sendMessage(fd, req, 0, req.length, TIMEOUT));
-
-        int neighMessageCount = 0;
-        int doneMessageCount = 0;
-
-        while (doneMessageCount == 0) {
-            ByteBuffer response = NetlinkSocket.recvMessage(fd, DEFAULT_RECV_BUFSIZE, TIMEOUT);
-            assertNotNull(response);
-            assertTrue(StructNlMsgHdr.STRUCT_SIZE <= response.limit());
-            assertEquals(0, response.position());
-            assertEquals(ByteOrder.nativeOrder(), response.order());
-
-            // Verify the messages at least appears minimally reasonable.
-            while (response.remaining() > 0) {
-                final NetlinkMessage msg = NetlinkMessage.parse(response);
-                assertNotNull(msg);
-                final StructNlMsgHdr hdr = msg.getHeader();
-                assertNotNull(hdr);
-
-                if (hdr.nlmsg_type == NetlinkConstants.NLMSG_DONE) {
-                    doneMessageCount++;
-                    continue;
-                }
-
-                assertEquals(NetlinkConstants.RTM_NEWNEIGH, hdr.nlmsg_type);
-                assertTrue(msg instanceof RtNetlinkNeighborMessage);
-                assertTrue((hdr.nlmsg_flags & StructNlMsgHdr.NLM_F_MULTI) != 0);
-                assertEquals(TEST_SEQNO, hdr.nlmsg_seq);
-                assertEquals(localAddr.getPortId(), hdr.nlmsg_pid);
-
-                neighMessageCount++;
-            }
-        }
-
-        assertEquals(1, doneMessageCount);
-        // TODO: make sure this test passes sanely in airplane mode.
-        assertTrue(neighMessageCount > 0);
-
-        IoUtils.closeQuietly(fd);
-    }
-}
diff --git a/tests/net/java/android/net/netlink/RtNetlinkNeighborMessageTest.java b/tests/net/java/android/net/netlink/RtNetlinkNeighborMessageTest.java
deleted file mode 100644
index 8162522..0000000
--- a/tests/net/java/android/net/netlink/RtNetlinkNeighborMessageTest.java
+++ /dev/null
@@ -1,270 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.netlink;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-
-import android.net.netlink.NetlinkConstants;
-import android.net.netlink.NetlinkMessage;
-import android.net.netlink.RtNetlinkNeighborMessage;
-import android.net.netlink.StructNdMsg;
-import android.net.netlink.StructNlMsgHdr;
-import android.system.OsConstants;
-
-import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
-
-import libcore.util.HexEncoding;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.net.Inet4Address;
-import java.net.InetAddress;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.util.Arrays;
-
-@RunWith(AndroidJUnit4.class)
-@SmallTest
-public class RtNetlinkNeighborMessageTest {
-    private final String TAG = "RtNetlinkNeighborMessageTest";
-
-    // Hexadecimal representation of packet capture.
-    public static final String RTM_DELNEIGH_HEX =
-            // struct nlmsghdr
-            "4c000000" +     // length = 76
-            "1d00" +         // type = 29 (RTM_DELNEIGH)
-            "0000" +         // flags
-            "00000000" +     // seqno
-            "00000000" +     // pid (0 == kernel)
-            // struct ndmsg
-            "02" +           // family
-            "00" +           // pad1
-            "0000" +         // pad2
-            "15000000" +     // interface index (21  == wlan0, on test device)
-            "0400" +         // NUD state (0x04 == NUD_STALE)
-            "00" +           // flags
-            "01" +           // type
-            // struct nlattr: NDA_DST
-            "0800" +         // length = 8
-            "0100" +         // type (1 == NDA_DST, for neighbor messages)
-            "c0a89ffe" +     // IPv4 address (== 192.168.159.254)
-            // struct nlattr: NDA_LLADDR
-            "0a00" +         // length = 10
-            "0200" +         // type (2 == NDA_LLADDR, for neighbor messages)
-            "00005e000164" + // MAC Address (== 00:00:5e:00:01:64)
-            "0000" +         // padding, for 4 byte alignment
-            // struct nlattr: NDA_PROBES
-            "0800" +         // length = 8
-            "0400" +         // type (4 == NDA_PROBES, for neighbor messages)
-            "01000000" +     // number of probes
-            // struct nlattr: NDA_CACHEINFO
-            "1400" +         // length = 20
-            "0300" +         // type (3 == NDA_CACHEINFO, for neighbor messages)
-            "05190000" +     // ndm_used, as "clock ticks ago"
-            "05190000" +     // ndm_confirmed, as "clock ticks ago"
-            "190d0000" +     // ndm_updated, as "clock ticks ago"
-            "00000000";      // ndm_refcnt
-    public static final byte[] RTM_DELNEIGH =
-            HexEncoding.decode(RTM_DELNEIGH_HEX.toCharArray(), false);
-
-    // Hexadecimal representation of packet capture.
-    public static final String RTM_NEWNEIGH_HEX =
-            // struct nlmsghdr
-            "58000000" +     // length = 88
-            "1c00" +         // type = 28 (RTM_NEWNEIGH)
-            "0000" +         // flags
-            "00000000" +     // seqno
-            "00000000" +     // pid (0 == kernel)
-            // struct ndmsg
-            "0a" +           // family
-            "00" +           // pad1
-            "0000" +         // pad2
-            "15000000" +     // interface index (21  == wlan0, on test device)
-            "0400" +         // NUD state (0x04 == NUD_STALE)
-            "80" +           // flags
-            "01" +           // type
-            // struct nlattr: NDA_DST
-            "1400" +         // length = 20
-            "0100" +         // type (1 == NDA_DST, for neighbor messages)
-            "fe8000000000000086c9b2fffe6aed4b" + // IPv6 address (== fe80::86c9:b2ff:fe6a:ed4b)
-            // struct nlattr: NDA_LLADDR
-            "0a00" +         // length = 10
-            "0200" +         // type (2 == NDA_LLADDR, for neighbor messages)
-            "84c9b26aed4b" + // MAC Address (== 84:c9:b2:6a:ed:4b)
-            "0000" +         // padding, for 4 byte alignment
-            // struct nlattr: NDA_PROBES
-            "0800" +         // length = 8
-            "0400" +         // type (4 == NDA_PROBES, for neighbor messages)
-            "01000000" +     // number of probes
-            // struct nlattr: NDA_CACHEINFO
-            "1400" +         // length = 20
-            "0300" +         // type (3 == NDA_CACHEINFO, for neighbor messages)
-            "eb0e0000" +     // ndm_used, as "clock ticks ago"
-            "861f0000" +     // ndm_confirmed, as "clock ticks ago"
-            "00000000" +     // ndm_updated, as "clock ticks ago"
-            "05000000";      // ndm_refcnt
-    public static final byte[] RTM_NEWNEIGH =
-            HexEncoding.decode(RTM_NEWNEIGH_HEX.toCharArray(), false);
-
-    // An example of the full response from an RTM_GETNEIGH query.
-    private static final String RTM_GETNEIGH_RESPONSE_HEX =
-            // <-- struct nlmsghr             -->|<-- struct ndmsg           -->|<-- struct nlattr: NDA_DST             -->|<-- NDA_LLADDR          -->|<-- NDA_PROBES -->|<-- NDA_CACHEINFO                         -->|
-            "58000000 1c00 0200 00000000 3e2b0000 0a 00 0000 15000000 4000 00 05 1400 0100 ff020000000000000000000000000001 0a00 0200 333300000001 0000 0800 0400 00000000 1400 0300 a2280000 32110000 32110000 01000000" +
-            "58000000 1c00 0200 00000000 3e2b0000 0a 00 0000 15000000 4000 00 05 1400 0100 ff0200000000000000000001ff000001 0a00 0200 3333ff000001 0000 0800 0400 00000000 1400 0300 0d280000 9d100000 9d100000 00000000" +
-            "58000000 1c00 0200 00000000 3e2b0000 0a 00 0000 15000000 0400 80 01 1400 0100 20010db800040ca00000000000000001 0a00 0200 84c9b26aed4b 0000 0800 0400 04000000 1400 0300 90100000 90100000 90080000 01000000" +
-            "58000000 1c00 0200 00000000 3e2b0000 0a 00 0000 15000000 4000 00 05 1400 0100 ff0200000000000000000001ff47da19 0a00 0200 3333ff47da19 0000 0800 0400 00000000 1400 0300 a1280000 31110000 31110000 01000000" +
-            "58000000 1c00 0200 00000000 3e2b0000 0a 00 0000 14000000 4000 00 05 1400 0100 ff020000000000000000000000000016 0a00 0200 333300000016 0000 0800 0400 00000000 1400 0300 912a0000 21130000 21130000 00000000" +
-            "58000000 1c00 0200 00000000 3e2b0000 0a 00 0000 14000000 4000 00 05 1400 0100 ff0200000000000000000001ffeace3b 0a00 0200 3333ffeace3b 0000 0800 0400 00000000 1400 0300 922a0000 22130000 22130000 00000000" +
-            "58000000 1c00 0200 00000000 3e2b0000 0a 00 0000 15000000 4000 00 05 1400 0100 ff0200000000000000000001ff5c2a83 0a00 0200 3333ff5c2a83 0000 0800 0400 00000000 1400 0300 391c0000 c9040000 c9040000 01000000" +
-            "58000000 1c00 0200 00000000 3e2b0000 0a 00 0000 01000000 4000 00 02 1400 0100 00000000000000000000000000000000 0a00 0200 000000000000 0000 0800 0400 00000000 1400 0300 cd180200 5d010200 5d010200 08000000" +
-            "58000000 1c00 0200 00000000 3e2b0000 0a 00 0000 15000000 4000 00 05 1400 0100 ff020000000000000000000000000002 0a00 0200 333300000002 0000 0800 0400 00000000 1400 0300 352a0000 c5120000 c5120000 00000000" +
-            "58000000 1c00 0200 00000000 3e2b0000 0a 00 0000 15000000 4000 00 05 1400 0100 ff020000000000000000000000000016 0a00 0200 333300000016 0000 0800 0400 00000000 1400 0300 982a0000 28130000 28130000 00000000" +
-            "58000000 1c00 0200 00000000 3e2b0000 0a 00 0000 15000000 0800 80 01 1400 0100 fe8000000000000086c9b2fffe6aed4b 0a00 0200 84c9b26aed4b 0000 0800 0400 00000000 1400 0300 23000000 24000000 57000000 13000000" +
-            "58000000 1c00 0200 00000000 3e2b0000 0a 00 0000 15000000 4000 00 05 1400 0100 ff0200000000000000000001ffeace3b 0a00 0200 3333ffeace3b 0000 0800 0400 00000000 1400 0300 992a0000 29130000 29130000 01000000" +
-            "58000000 1c00 0200 00000000 3e2b0000 0a 00 0000 14000000 4000 00 05 1400 0100 ff020000000000000000000000000002 0a00 0200 333300000002 0000 0800 0400 00000000 1400 0300 2e2a0000 be120000 be120000 00000000" +
-            "44000000 1c00 0200 00000000 3e2b0000 02 00 0000 18000000 4000 00 03 0800 0100 00000000                         0400 0200                   0800 0400 00000000 1400 0300 75280000 05110000 05110000 22000000";
-    public static final byte[] RTM_GETNEIGH_RESPONSE =
-            HexEncoding.decode(RTM_GETNEIGH_RESPONSE_HEX.replaceAll(" ", "").toCharArray(), false);
-
-    @Test
-    public void testParseRtmDelNeigh() {
-        final ByteBuffer byteBuffer = ByteBuffer.wrap(RTM_DELNEIGH);
-        byteBuffer.order(ByteOrder.LITTLE_ENDIAN);  // For testing.
-        final NetlinkMessage msg = NetlinkMessage.parse(byteBuffer);
-        assertNotNull(msg);
-        assertTrue(msg instanceof RtNetlinkNeighborMessage);
-        final RtNetlinkNeighborMessage neighMsg = (RtNetlinkNeighborMessage) msg;
-
-        final StructNlMsgHdr hdr = neighMsg.getHeader();
-        assertNotNull(hdr);
-        assertEquals(76, hdr.nlmsg_len);
-        assertEquals(NetlinkConstants.RTM_DELNEIGH, hdr.nlmsg_type);
-        assertEquals(0, hdr.nlmsg_flags);
-        assertEquals(0, hdr.nlmsg_seq);
-        assertEquals(0, hdr.nlmsg_pid);
-
-        final StructNdMsg ndmsgHdr = neighMsg.getNdHeader();
-        assertNotNull(ndmsgHdr);
-        assertEquals((byte) OsConstants.AF_INET, ndmsgHdr.ndm_family);
-        assertEquals(21, ndmsgHdr.ndm_ifindex);
-        assertEquals(StructNdMsg.NUD_STALE, ndmsgHdr.ndm_state);
-        final InetAddress destination = neighMsg.getDestination();
-        assertNotNull(destination);
-        assertEquals(InetAddress.parseNumericAddress("192.168.159.254"), destination);
-    }
-
-    @Test
-    public void testParseRtmNewNeigh() {
-        final ByteBuffer byteBuffer = ByteBuffer.wrap(RTM_NEWNEIGH);
-        byteBuffer.order(ByteOrder.LITTLE_ENDIAN);  // For testing.
-        final NetlinkMessage msg = NetlinkMessage.parse(byteBuffer);
-        assertNotNull(msg);
-        assertTrue(msg instanceof RtNetlinkNeighborMessage);
-        final RtNetlinkNeighborMessage neighMsg = (RtNetlinkNeighborMessage) msg;
-
-        final StructNlMsgHdr hdr = neighMsg.getHeader();
-        assertNotNull(hdr);
-        assertEquals(88, hdr.nlmsg_len);
-        assertEquals(NetlinkConstants.RTM_NEWNEIGH, hdr.nlmsg_type);
-        assertEquals(0, hdr.nlmsg_flags);
-        assertEquals(0, hdr.nlmsg_seq);
-        assertEquals(0, hdr.nlmsg_pid);
-
-        final StructNdMsg ndmsgHdr = neighMsg.getNdHeader();
-        assertNotNull(ndmsgHdr);
-        assertEquals((byte) OsConstants.AF_INET6, ndmsgHdr.ndm_family);
-        assertEquals(21, ndmsgHdr.ndm_ifindex);
-        assertEquals(StructNdMsg.NUD_STALE, ndmsgHdr.ndm_state);
-        final InetAddress destination = neighMsg.getDestination();
-        assertNotNull(destination);
-        assertEquals(InetAddress.parseNumericAddress("fe80::86c9:b2ff:fe6a:ed4b"), destination);
-    }
-
-    @Test
-    public void testParseRtmGetNeighResponse() {
-        final ByteBuffer byteBuffer = ByteBuffer.wrap(RTM_GETNEIGH_RESPONSE);
-        byteBuffer.order(ByteOrder.LITTLE_ENDIAN);  // For testing.
-
-        int messageCount = 0;
-        while (byteBuffer.remaining() > 0) {
-            final NetlinkMessage msg = NetlinkMessage.parse(byteBuffer);
-            assertNotNull(msg);
-            assertTrue(msg instanceof RtNetlinkNeighborMessage);
-            final RtNetlinkNeighborMessage neighMsg = (RtNetlinkNeighborMessage) msg;
-
-            final StructNlMsgHdr hdr = neighMsg.getHeader();
-            assertNotNull(hdr);
-            assertEquals(NetlinkConstants.RTM_NEWNEIGH, hdr.nlmsg_type);
-            assertEquals(StructNlMsgHdr.NLM_F_MULTI, hdr.nlmsg_flags);
-            assertEquals(0, hdr.nlmsg_seq);
-            assertEquals(11070, hdr.nlmsg_pid);
-
-            messageCount++;
-        }
-        // TODO: add more detailed spot checks.
-        assertEquals(14, messageCount);
-    }
-
-    @Test
-    public void testCreateRtmNewNeighMessage() {
-        final int seqNo = 2635;
-        final int ifIndex = 14;
-        final byte[] llAddr =
-                new byte[] { (byte) 1, (byte) 2, (byte) 3, (byte) 4, (byte) 5, (byte) 6 };
-
-        // Hexadecimal representation of our created packet.
-        final String expectedNewNeighHex =
-                // struct nlmsghdr
-                "30000000" +     // length = 48
-                "1c00" +         // type = 28 (RTM_NEWNEIGH)
-                "0501" +         // flags (NLM_F_REQUEST | NLM_F_ACK | NLM_F_REPLACE)
-                "4b0a0000" +     // seqno
-                "00000000" +     // pid (0 == kernel)
-                // struct ndmsg
-                "02" +           // family
-                "00" +           // pad1
-                "0000" +         // pad2
-                "0e000000" +     // interface index (14)
-                "0800" +         // NUD state (0x08 == NUD_DELAY)
-                "00" +           // flags
-                "00" +           // type
-                // struct nlattr: NDA_DST
-                "0800" +         // length = 8
-                "0100" +         // type (1 == NDA_DST, for neighbor messages)
-                "7f000001" +     // IPv4 address (== 127.0.0.1)
-                // struct nlattr: NDA_LLADDR
-                "0a00" +         // length = 10
-                "0200" +         // type (2 == NDA_LLADDR, for neighbor messages)
-                "010203040506" + // MAC Address (== 01:02:03:04:05:06)
-                "0000";          // padding, for 4 byte alignment
-        final byte[] expectedNewNeigh =
-                HexEncoding.decode(expectedNewNeighHex.toCharArray(), false);
-
-        final byte[] bytes = RtNetlinkNeighborMessage.newNewNeighborMessage(
-            seqNo, Inet4Address.LOOPBACK, StructNdMsg.NUD_DELAY, ifIndex, llAddr);
-        if (!Arrays.equals(expectedNewNeigh, bytes)) {
-            assertEquals(expectedNewNeigh.length, bytes.length);
-            for (int i = 0; i < Math.min(expectedNewNeigh.length, bytes.length); i++) {
-                assertEquals(expectedNewNeigh[i], bytes[i]);
-            }
-        }
-    }
-}
diff --git a/tests/net/java/android/net/shared/Inet4AddressUtilsTest.java b/tests/net/java/android/net/shared/Inet4AddressUtilsTest.java
deleted file mode 100644
index 35f8c79..0000000
--- a/tests/net/java/android/net/shared/Inet4AddressUtilsTest.java
+++ /dev/null
@@ -1,210 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.shared;
-
-import static android.net.shared.Inet4AddressUtils.getBroadcastAddress;
-import static android.net.shared.Inet4AddressUtils.getImplicitNetmask;
-import static android.net.shared.Inet4AddressUtils.getPrefixMaskAsInet4Address;
-import static android.net.shared.Inet4AddressUtils.inet4AddressToIntHTH;
-import static android.net.shared.Inet4AddressUtils.inet4AddressToIntHTL;
-import static android.net.shared.Inet4AddressUtils.intToInet4AddressHTH;
-import static android.net.shared.Inet4AddressUtils.intToInet4AddressHTL;
-import static android.net.shared.Inet4AddressUtils.netmaskToPrefixLength;
-import static android.net.shared.Inet4AddressUtils.prefixLengthToV4NetmaskIntHTH;
-import static android.net.shared.Inet4AddressUtils.prefixLengthToV4NetmaskIntHTL;
-
-import static junit.framework.Assert.assertEquals;
-
-import static org.junit.Assert.fail;
-
-import android.net.InetAddresses;
-
-import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.net.Inet4Address;
-
-@RunWith(AndroidJUnit4.class)
-@SmallTest
-public class Inet4AddressUtilsTest {
-
-    @Test
-    public void testInet4AddressToIntHTL() {
-        assertEquals(0, inet4AddressToIntHTL(ipv4Address("0.0.0.0")));
-        assertEquals(0x000080ff, inet4AddressToIntHTL(ipv4Address("255.128.0.0")));
-        assertEquals(0x0080ff0a, inet4AddressToIntHTL(ipv4Address("10.255.128.0")));
-        assertEquals(0x00feff0a, inet4AddressToIntHTL(ipv4Address("10.255.254.0")));
-        assertEquals(0xfeffa8c0, inet4AddressToIntHTL(ipv4Address("192.168.255.254")));
-        assertEquals(0xffffa8c0, inet4AddressToIntHTL(ipv4Address("192.168.255.255")));
-    }
-
-    @Test
-    public void testIntToInet4AddressHTL() {
-        assertEquals(ipv4Address("0.0.0.0"), intToInet4AddressHTL(0));
-        assertEquals(ipv4Address("255.128.0.0"), intToInet4AddressHTL(0x000080ff));
-        assertEquals(ipv4Address("10.255.128.0"), intToInet4AddressHTL(0x0080ff0a));
-        assertEquals(ipv4Address("10.255.254.0"), intToInet4AddressHTL(0x00feff0a));
-        assertEquals(ipv4Address("192.168.255.254"), intToInet4AddressHTL(0xfeffa8c0));
-        assertEquals(ipv4Address("192.168.255.255"), intToInet4AddressHTL(0xffffa8c0));
-    }
-
-    @Test
-    public void testInet4AddressToIntHTH() {
-        assertEquals(0, inet4AddressToIntHTH(ipv4Address("0.0.0.0")));
-        assertEquals(0xff800000, inet4AddressToIntHTH(ipv4Address("255.128.0.0")));
-        assertEquals(0x0aff8000, inet4AddressToIntHTH(ipv4Address("10.255.128.0")));
-        assertEquals(0x0afffe00, inet4AddressToIntHTH(ipv4Address("10.255.254.0")));
-        assertEquals(0xc0a8fffe, inet4AddressToIntHTH(ipv4Address("192.168.255.254")));
-        assertEquals(0xc0a8ffff, inet4AddressToIntHTH(ipv4Address("192.168.255.255")));
-    }
-
-    @Test
-    public void testIntToInet4AddressHTH() {
-        assertEquals(ipv4Address("0.0.0.0"), intToInet4AddressHTH(0));
-        assertEquals(ipv4Address("255.128.0.0"), intToInet4AddressHTH(0xff800000));
-        assertEquals(ipv4Address("10.255.128.0"), intToInet4AddressHTH(0x0aff8000));
-        assertEquals(ipv4Address("10.255.254.0"), intToInet4AddressHTH(0x0afffe00));
-        assertEquals(ipv4Address("192.168.255.254"), intToInet4AddressHTH(0xc0a8fffe));
-        assertEquals(ipv4Address("192.168.255.255"), intToInet4AddressHTH(0xc0a8ffff));
-    }
-
-
-    @Test
-    public void testPrefixLengthToV4NetmaskIntHTL() {
-        assertEquals(0, prefixLengthToV4NetmaskIntHTL(0));
-        assertEquals(0x000080ff /* 255.128.0.0 */, prefixLengthToV4NetmaskIntHTL(9));
-        assertEquals(0x0080ffff /* 255.255.128.0 */, prefixLengthToV4NetmaskIntHTL(17));
-        assertEquals(0x00feffff /* 255.255.254.0 */, prefixLengthToV4NetmaskIntHTL(23));
-        assertEquals(0xfeffffff /* 255.255.255.254 */, prefixLengthToV4NetmaskIntHTL(31));
-        assertEquals(0xffffffff /* 255.255.255.255 */, prefixLengthToV4NetmaskIntHTL(32));
-    }
-
-    @Test
-    public void testPrefixLengthToV4NetmaskIntHTH() {
-        assertEquals(0, prefixLengthToV4NetmaskIntHTH(0));
-        assertEquals(0xff800000 /* 255.128.0.0 */, prefixLengthToV4NetmaskIntHTH(9));
-        assertEquals(0xffff8000 /* 255.255.128.0 */, prefixLengthToV4NetmaskIntHTH(17));
-        assertEquals(0xfffffe00 /* 255.255.254.0 */, prefixLengthToV4NetmaskIntHTH(23));
-        assertEquals(0xfffffffe /* 255.255.255.254 */, prefixLengthToV4NetmaskIntHTH(31));
-        assertEquals(0xffffffff /* 255.255.255.255 */, prefixLengthToV4NetmaskIntHTH(32));
-    }
-
-    @Test(expected = IllegalArgumentException.class)
-    public void testPrefixLengthToV4NetmaskIntHTH_NegativeLength() {
-        prefixLengthToV4NetmaskIntHTH(-1);
-    }
-
-    @Test(expected = IllegalArgumentException.class)
-    public void testPrefixLengthToV4NetmaskIntHTH_LengthTooLarge() {
-        prefixLengthToV4NetmaskIntHTH(33);
-    }
-
-    private void checkAddressMasking(String expectedAddr, String addr, int prefixLength) {
-        final int prefix = prefixLengthToV4NetmaskIntHTH(prefixLength);
-        final int addrInt = inet4AddressToIntHTH(ipv4Address(addr));
-        assertEquals(ipv4Address(expectedAddr), intToInet4AddressHTH(prefix & addrInt));
-    }
-
-    @Test
-    public void testPrefixLengthToV4NetmaskIntHTH_MaskAddr() {
-        checkAddressMasking("192.168.0.0", "192.168.128.1", 16);
-        checkAddressMasking("255.240.0.0", "255.255.255.255", 12);
-        checkAddressMasking("255.255.255.255", "255.255.255.255", 32);
-        checkAddressMasking("0.0.0.0", "255.255.255.255", 0);
-    }
-
-    @Test
-    public void testGetImplicitNetmask() {
-        assertEquals(8, getImplicitNetmask(ipv4Address("4.2.2.2")));
-        assertEquals(8, getImplicitNetmask(ipv4Address("10.5.6.7")));
-        assertEquals(16, getImplicitNetmask(ipv4Address("173.194.72.105")));
-        assertEquals(16, getImplicitNetmask(ipv4Address("172.23.68.145")));
-        assertEquals(24, getImplicitNetmask(ipv4Address("192.0.2.1")));
-        assertEquals(24, getImplicitNetmask(ipv4Address("192.168.5.1")));
-        assertEquals(32, getImplicitNetmask(ipv4Address("224.0.0.1")));
-        assertEquals(32, getImplicitNetmask(ipv4Address("255.6.7.8")));
-    }
-
-    private void assertInvalidNetworkMask(Inet4Address addr) {
-        try {
-            netmaskToPrefixLength(addr);
-            fail("Invalid netmask " + addr.getHostAddress() + " did not cause exception");
-        } catch (IllegalArgumentException expected) {
-        }
-    }
-
-    @Test
-    public void testNetmaskToPrefixLength() {
-        assertEquals(0, netmaskToPrefixLength(ipv4Address("0.0.0.0")));
-        assertEquals(9, netmaskToPrefixLength(ipv4Address("255.128.0.0")));
-        assertEquals(17, netmaskToPrefixLength(ipv4Address("255.255.128.0")));
-        assertEquals(23, netmaskToPrefixLength(ipv4Address("255.255.254.0")));
-        assertEquals(31, netmaskToPrefixLength(ipv4Address("255.255.255.254")));
-        assertEquals(32, netmaskToPrefixLength(ipv4Address("255.255.255.255")));
-
-        assertInvalidNetworkMask(ipv4Address("0.0.0.1"));
-        assertInvalidNetworkMask(ipv4Address("255.255.255.253"));
-        assertInvalidNetworkMask(ipv4Address("255.255.0.255"));
-    }
-
-    @Test
-    public void testGetPrefixMaskAsAddress() {
-        assertEquals("255.255.240.0", getPrefixMaskAsInet4Address(20).getHostAddress());
-        assertEquals("255.0.0.0", getPrefixMaskAsInet4Address(8).getHostAddress());
-        assertEquals("0.0.0.0", getPrefixMaskAsInet4Address(0).getHostAddress());
-        assertEquals("255.255.255.255", getPrefixMaskAsInet4Address(32).getHostAddress());
-    }
-
-    @Test
-    public void testGetBroadcastAddress() {
-        assertEquals("192.168.15.255",
-                getBroadcastAddress(ipv4Address("192.168.0.123"), 20).getHostAddress());
-        assertEquals("192.255.255.255",
-                getBroadcastAddress(ipv4Address("192.168.0.123"), 8).getHostAddress());
-        assertEquals("192.168.0.123",
-                getBroadcastAddress(ipv4Address("192.168.0.123"), 32).getHostAddress());
-        assertEquals("255.255.255.255",
-                getBroadcastAddress(ipv4Address("192.168.0.123"), 0).getHostAddress());
-    }
-
-    @Test(expected = IllegalArgumentException.class)
-    public void testGetBroadcastAddress_PrefixTooLarge() {
-        getBroadcastAddress(ipv4Address("192.168.0.123"), 33);
-    }
-
-    @Test(expected = IllegalArgumentException.class)
-    public void testGetBroadcastAddress_NegativePrefix() {
-        getBroadcastAddress(ipv4Address("192.168.0.123"), -1);
-    }
-
-    @Test(expected = IllegalArgumentException.class)
-    public void testGetPrefixMaskAsAddress_PrefixTooLarge() {
-        getPrefixMaskAsInet4Address(33);
-    }
-
-    @Test(expected = IllegalArgumentException.class)
-    public void testGetPrefixMaskAsAddress_NegativePrefix() {
-        getPrefixMaskAsInet4Address(-1);
-    }
-
-    private Inet4Address ipv4Address(String addr) {
-        return (Inet4Address) InetAddresses.parseNumericAddress(addr);
-    }
-}
diff --git a/tests/net/java/android/net/shared/InitialConfigurationTest.java b/tests/net/java/android/net/shared/InitialConfigurationTest.java
deleted file mode 100644
index 17f8324..0000000
--- a/tests/net/java/android/net/shared/InitialConfigurationTest.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.shared;
-
-import static android.net.InetAddresses.parseNumericAddress;
-
-import static com.android.testutils.MiscAssertsKt.assertFieldCountEquals;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotEquals;
-
-import android.net.IpPrefix;
-import android.net.LinkAddress;
-
-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.util.Arrays;
-import java.util.function.Consumer;
-
-/**
- * Tests for {@link InitialConfiguration}
- */
-@RunWith(AndroidJUnit4.class)
-@SmallTest
-public class InitialConfigurationTest {
-    private InitialConfiguration mConfig;
-
-    @Before
-    public void setUp() {
-        mConfig = new InitialConfiguration();
-        mConfig.ipAddresses.addAll(Arrays.asList(
-                new LinkAddress(parseNumericAddress("192.168.45.45"), 16),
-                new LinkAddress(parseNumericAddress("2001:db8::45"), 33)));
-        mConfig.directlyConnectedRoutes.addAll(Arrays.asList(
-                new IpPrefix(parseNumericAddress("192.168.46.46"), 17),
-                new IpPrefix(parseNumericAddress("2001:db8::46"), 34)));
-        mConfig.dnsServers.addAll(Arrays.asList(
-                parseNumericAddress("192.168.47.47"),
-                parseNumericAddress("2001:db8::47")));
-        // Any added InitialConfiguration field must be included in equals() to be tested properly
-        assertFieldCountEquals(3, InitialConfiguration.class);
-    }
-
-    @Test
-    public void testParcelUnparcelInitialConfiguration() {
-        final InitialConfiguration unparceled =
-                InitialConfiguration.fromStableParcelable(mConfig.toStableParcelable());
-        assertEquals(mConfig, unparceled);
-    }
-
-    @Test
-    public void testEquals() {
-        assertEquals(mConfig, InitialConfiguration.copy(mConfig));
-
-        assertNotEqualsAfterChange(c -> c.ipAddresses.add(
-                new LinkAddress(parseNumericAddress("192.168.47.47"), 24)));
-        assertNotEqualsAfterChange(c -> c.directlyConnectedRoutes.add(
-                new IpPrefix(parseNumericAddress("192.168.46.46"), 32)));
-        assertNotEqualsAfterChange(c -> c.dnsServers.add(parseNumericAddress("2001:db8::49")));
-        assertFieldCountEquals(3, InitialConfiguration.class);
-    }
-
-    private void assertNotEqualsAfterChange(Consumer<InitialConfiguration> mutator) {
-        final InitialConfiguration newConfig = InitialConfiguration.copy(mConfig);
-        mutator.accept(newConfig);
-        assertNotEquals(mConfig, newConfig);
-    }
-}
diff --git a/tests/net/java/android/net/shared/IpConfigurationParcelableUtilTest.java b/tests/net/java/android/net/shared/IpConfigurationParcelableUtilTest.java
deleted file mode 100644
index f987389..0000000
--- a/tests/net/java/android/net/shared/IpConfigurationParcelableUtilTest.java
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.shared;
-
-import static android.net.InetAddresses.parseNumericAddress;
-import static android.net.shared.IpConfigurationParcelableUtil.fromStableParcelable;
-import static android.net.shared.IpConfigurationParcelableUtil.toStableParcelable;
-
-import static com.android.testutils.MiscAssertsKt.assertFieldCountEquals;
-
-import static org.junit.Assert.assertEquals;
-
-import android.net.DhcpResults;
-import android.net.LinkAddress;
-
-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.net.Inet4Address;
-
-/**
- * Tests for {@link IpConfigurationParcelableUtil}.
- */
-@RunWith(AndroidJUnit4.class)
-@SmallTest
-public class IpConfigurationParcelableUtilTest {
-    private DhcpResults mDhcpResults;
-
-    @Before
-    public void setUp() {
-        mDhcpResults = new DhcpResults();
-        mDhcpResults.ipAddress = new LinkAddress(parseNumericAddress("2001:db8::42"), 64);
-        mDhcpResults.gateway = parseNumericAddress("192.168.42.42");
-        mDhcpResults.dnsServers.add(parseNumericAddress("2001:db8::43"));
-        mDhcpResults.dnsServers.add(parseNumericAddress("192.168.43.43"));
-        mDhcpResults.domains = "example.com";
-        mDhcpResults.serverAddress = (Inet4Address) parseNumericAddress("192.168.44.44");
-        mDhcpResults.vendorInfo = "TEST_VENDOR_INFO";
-        mDhcpResults.leaseDuration = 3600;
-        mDhcpResults.serverHostName = "dhcp.example.com";
-        mDhcpResults.mtu = 1450;
-        // Any added DhcpResults field must be included in equals() to be tested properly
-        assertFieldCountEquals(9, DhcpResults.class);
-    }
-
-    @Test
-    public void testParcelUnparcelDhcpResults() {
-        doDhcpResultsParcelUnparcelTest();
-    }
-
-    @Test
-    public void testParcelUnparcelDhcpResults_NullIpAddress() {
-        mDhcpResults.ipAddress = null;
-        doDhcpResultsParcelUnparcelTest();
-    }
-
-    @Test
-    public void testParcelUnparcelDhcpResults_NullGateway() {
-        mDhcpResults.gateway = null;
-        doDhcpResultsParcelUnparcelTest();
-    }
-
-    @Test
-    public void testParcelUnparcelDhcpResults_NullDomains() {
-        mDhcpResults.domains = null;
-        doDhcpResultsParcelUnparcelTest();
-    }
-
-    @Test
-    public void testParcelUnparcelDhcpResults_EmptyDomains() {
-        mDhcpResults.domains = "";
-        doDhcpResultsParcelUnparcelTest();
-    }
-
-    @Test
-    public void testParcelUnparcelDhcpResults_NullServerAddress() {
-        mDhcpResults.serverAddress = null;
-        doDhcpResultsParcelUnparcelTest();
-    }
-
-    @Test
-    public void testParcelUnparcelDhcpResults_NullVendorInfo() {
-        mDhcpResults.vendorInfo = null;
-        doDhcpResultsParcelUnparcelTest();
-    }
-
-    @Test
-    public void testParcelUnparcelDhcpResults_NullServerHostName() {
-        mDhcpResults.serverHostName = null;
-        doDhcpResultsParcelUnparcelTest();
-    }
-
-    private void doDhcpResultsParcelUnparcelTest() {
-        final DhcpResults unparceled = fromStableParcelable(toStableParcelable(mDhcpResults));
-        assertEquals(mDhcpResults, unparceled);
-    }
-}
diff --git a/tests/net/java/android/net/shared/ProvisioningConfigurationTest.java b/tests/net/java/android/net/shared/ProvisioningConfigurationTest.java
deleted file mode 100644
index 7079a28..0000000
--- a/tests/net/java/android/net/shared/ProvisioningConfigurationTest.java
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.shared;
-
-import static android.net.InetAddresses.parseNumericAddress;
-import static android.net.shared.ProvisioningConfiguration.fromStableParcelable;
-
-import static com.android.testutils.MiscAssertsKt.assertFieldCountEquals;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotEquals;
-
-import android.net.LinkAddress;
-import android.net.Network;
-import android.net.StaticIpConfiguration;
-import android.net.apf.ApfCapabilities;
-
-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.util.function.Consumer;
-
-/**
- * Tests for {@link ProvisioningConfiguration}.
- */
-@RunWith(AndroidJUnit4.class)
-@SmallTest
-public class ProvisioningConfigurationTest {
-    private ProvisioningConfiguration mConfig;
-
-    @Before
-    public void setUp() {
-        mConfig = new ProvisioningConfiguration();
-        mConfig.mEnableIPv4 = true;
-        mConfig.mEnableIPv6 = true;
-        mConfig.mUsingMultinetworkPolicyTracker = true;
-        mConfig.mUsingIpReachabilityMonitor = true;
-        mConfig.mRequestedPreDhcpActionMs = 42;
-        mConfig.mInitialConfig = new InitialConfiguration();
-        mConfig.mInitialConfig.ipAddresses.add(
-                new LinkAddress(parseNumericAddress("192.168.42.42"), 24));
-        mConfig.mStaticIpConfig = new StaticIpConfiguration();
-        mConfig.mStaticIpConfig.ipAddress =
-                new LinkAddress(parseNumericAddress("2001:db8::42"), 90);
-        // Not testing other InitialConfig or StaticIpConfig members: they have their own unit tests
-        mConfig.mApfCapabilities = new ApfCapabilities(1, 2, 3);
-        mConfig.mProvisioningTimeoutMs = 4200;
-        mConfig.mIPv6AddrGenMode = 123;
-        mConfig.mNetwork = new Network(321);
-        mConfig.mDisplayName = "test_config";
-        // Any added field must be included in equals() to be tested properly
-        assertFieldCountEquals(12, ProvisioningConfiguration.class);
-    }
-
-    @Test
-    public void testParcelUnparcel() {
-        doParcelUnparcelTest();
-    }
-
-    @Test
-    public void testParcelUnparcel_NullInitialConfiguration() {
-        mConfig.mInitialConfig = null;
-        doParcelUnparcelTest();
-    }
-
-    @Test
-    public void testParcelUnparcel_NullStaticConfiguration() {
-        mConfig.mStaticIpConfig = null;
-        doParcelUnparcelTest();
-    }
-
-    @Test
-    public void testParcelUnparcel_NullApfCapabilities() {
-        mConfig.mApfCapabilities = null;
-        doParcelUnparcelTest();
-    }
-
-    @Test
-    public void testParcelUnparcel_NullNetwork() {
-        mConfig.mNetwork = null;
-        doParcelUnparcelTest();
-    }
-
-    private void doParcelUnparcelTest() {
-        final ProvisioningConfiguration unparceled =
-                fromStableParcelable(mConfig.toStableParcelable());
-        assertEquals(mConfig, unparceled);
-    }
-
-    @Test
-    public void testEquals() {
-        assertEquals(mConfig, new ProvisioningConfiguration(mConfig));
-
-        assertNotEqualsAfterChange(c -> c.mEnableIPv4 = false);
-        assertNotEqualsAfterChange(c -> c.mEnableIPv6 = false);
-        assertNotEqualsAfterChange(c -> c.mUsingMultinetworkPolicyTracker = false);
-        assertNotEqualsAfterChange(c -> c.mUsingIpReachabilityMonitor = false);
-        assertNotEqualsAfterChange(c -> c.mRequestedPreDhcpActionMs++);
-        assertNotEqualsAfterChange(c -> c.mInitialConfig.ipAddresses.add(
-                new LinkAddress(parseNumericAddress("192.168.47.47"), 16)));
-        assertNotEqualsAfterChange(c -> c.mInitialConfig = null);
-        assertNotEqualsAfterChange(c -> c.mStaticIpConfig.ipAddress =
-                new LinkAddress(parseNumericAddress("2001:db8::47"), 64));
-        assertNotEqualsAfterChange(c -> c.mStaticIpConfig = null);
-        assertNotEqualsAfterChange(c -> c.mApfCapabilities = new ApfCapabilities(4, 5, 6));
-        assertNotEqualsAfterChange(c -> c.mApfCapabilities = null);
-        assertNotEqualsAfterChange(c -> c.mProvisioningTimeoutMs++);
-        assertNotEqualsAfterChange(c -> c.mIPv6AddrGenMode++);
-        assertNotEqualsAfterChange(c -> c.mNetwork = new Network(123));
-        assertNotEqualsAfterChange(c -> c.mNetwork = null);
-        assertNotEqualsAfterChange(c -> c.mDisplayName = "other_test");
-        assertNotEqualsAfterChange(c -> c.mDisplayName = null);
-        assertFieldCountEquals(12, ProvisioningConfiguration.class);
-    }
-
-    private void assertNotEqualsAfterChange(Consumer<ProvisioningConfiguration> mutator) {
-        final ProvisioningConfiguration newConfig = new ProvisioningConfiguration(mConfig);
-        mutator.accept(newConfig);
-        assertNotEquals(mConfig, newConfig);
-    }
-}
diff --git a/tests/net/java/android/net/util/InterfaceParamsTest.java b/tests/net/java/android/net/util/InterfaceParamsTest.java
deleted file mode 100644
index 141455c..0000000
--- a/tests/net/java/android/net/util/InterfaceParamsTest.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.util;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-
-import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-@RunWith(AndroidJUnit4.class)
-@SmallTest
-public class InterfaceParamsTest {
-    @Test
-    public void testNullInterfaceReturnsNull() {
-        assertNull(InterfaceParams.getByName(null));
-    }
-
-    @Test
-    public void testNonExistentInterfaceReturnsNull() {
-        assertNull(InterfaceParams.getByName("doesnotexist0"));
-    }
-
-    @Test
-    public void testLoopback() {
-        final InterfaceParams ifParams = InterfaceParams.getByName("lo");
-        assertNotNull(ifParams);
-        assertEquals("lo", ifParams.name);
-        assertTrue(ifParams.index > 0);
-        assertNotNull(ifParams.macAddr);
-        assertTrue(ifParams.defaultMtu >= NetworkConstants.ETHER_MTU);
-    }
-}
diff --git a/tests/net/java/android/net/util/SharedLogTest.java b/tests/net/java/android/net/util/SharedLogTest.java
deleted file mode 100644
index e1dba36..0000000
--- a/tests/net/java/android/net/util/SharedLogTest.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.util;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.io.ByteArrayOutputStream;
-import java.io.PrintWriter;
-
-@RunWith(AndroidJUnit4.class)
-@SmallTest
-public class SharedLogTest {
-    private static final String TIMESTAMP_PATTERN = "\\d{2}:\\d{2}:\\d{2}";
-    private static final String TIMESTAMP = "HH:MM:SS";
-
-    @Test
-    public void testBasicOperation() {
-        final SharedLog logTop = new SharedLog("top");
-        logTop.mark("first post!");
-
-        final SharedLog logLevel2a = logTop.forSubComponent("twoA");
-        final SharedLog logLevel2b = logTop.forSubComponent("twoB");
-        logLevel2b.e("2b or not 2b");
-        logLevel2b.e("No exception", null);
-        logLevel2b.e("Wait, here's one", new Exception("Test"));
-        logLevel2a.w("second post?");
-
-        final SharedLog logLevel3 = logLevel2a.forSubComponent("three");
-        logTop.log("still logging");
-        logLevel3.log("3 >> 2");
-        logLevel2a.mark("ok: last post");
-
-        final String[] expected = {
-            " - MARK first post!",
-            " - [twoB] ERROR 2b or not 2b",
-            " - [twoB] ERROR No exception",
-            // No stacktrace in shared log, only in logcat
-            " - [twoB] ERROR Wait, here's one: Test",
-            " - [twoA] WARN second post?",
-            " - still logging",
-            " - [twoA.three] 3 >> 2",
-            " - [twoA] MARK ok: last post",
-        };
-        // Verify the logs are all there and in the correct order.
-        verifyLogLines(expected, logTop);
-
-        // In fact, because they all share the same underlying LocalLog,
-        // every subcomponent SharedLog's dump() is identical.
-        verifyLogLines(expected, logLevel2a);
-        verifyLogLines(expected, logLevel2b);
-        verifyLogLines(expected, logLevel3);
-    }
-
-    private static void verifyLogLines(String[] expected, SharedLog log) {
-        final ByteArrayOutputStream ostream = new ByteArrayOutputStream();
-        final PrintWriter pw = new PrintWriter(ostream, true);
-        log.dump(null, pw, null);
-
-        final String dumpOutput = ostream.toString();
-        assertTrue(dumpOutput != null);
-        assertTrue(!"".equals(dumpOutput));
-
-        final String[] lines = dumpOutput.split("\n");
-        assertEquals(expected.length, lines.length);
-
-        for (int i = 0; i < expected.length; i++) {
-            String got = lines[i];
-            String want = expected[i];
-            assertTrue(String.format("'%s' did not contain '%s'", got, want), got.endsWith(want));
-            assertTrue(String.format("'%s' did not contain a %s timestamp", got, TIMESTAMP),
-                    got.replaceFirst(TIMESTAMP_PATTERN, TIMESTAMP).contains(TIMESTAMP));
-        }
-    }
-}
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/RttManager.java b/wifi/java/android/net/wifi/RttManager.java
index 6a03c73..73c52ab 100644
--- a/wifi/java/android/net/wifi/RttManager.java
+++ b/wifi/java/android/net/wifi/RttManager.java
@@ -1212,7 +1212,7 @@
      *
      * @hide
      */
-    public RttManager(Context context, WifiRttManager service) {
+    public RttManager(@NonNull Context context, @NonNull WifiRttManager service) {
         mNewService = service;
         mContext = context;
 
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/WifiFrameworkInitializer.java b/wifi/java/android/net/wifi/WifiFrameworkInitializer.java
new file mode 100644
index 0000000..775043a
--- /dev/null
+++ b/wifi/java/android/net/wifi/WifiFrameworkInitializer.java
@@ -0,0 +1,119 @@
+/*
+ * 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.net.wifi;
+
+import android.annotation.SystemApi;
+import android.app.SystemServiceRegistry;
+import android.content.Context;
+import android.net.wifi.aware.IWifiAwareManager;
+import android.net.wifi.aware.WifiAwareManager;
+import android.net.wifi.p2p.IWifiP2pManager;
+import android.net.wifi.p2p.WifiP2pManager;
+import android.net.wifi.rtt.IWifiRttManager;
+import android.net.wifi.rtt.WifiRttManager;
+import android.os.HandlerThread;
+import android.os.Looper;
+
+/**
+ * Class for performing registration for all Wifi services.
+ *
+ * @hide
+ */
+@SystemApi
+public class WifiFrameworkInitializer {
+
+    /**
+     * A class implementing the lazy holder idiom: the unique static instance
+     * of {@link #INSTANCE} is instantiated in a thread-safe way (guaranteed by
+     * the language specs) the first time that NoPreloadHolder is referenced in getInstanceLooper().
+     *
+     * This is necessary because we can't spawn a new thread in {@link #registerServiceWrappers()}.
+     * {@link #registerServiceWrappers()} is called during the Zygote phase, which disallows
+     * spawning new threads. Naming the class "NoPreloadHolder" ensures that the classloader will
+     * not preload this class, inadvertently spawning the thread too early.
+     */
+    private static class NoPreloadHolder {
+        private static final HandlerThread INSTANCE = createInstance();
+
+        private static HandlerThread createInstance() {
+            HandlerThread thread = new HandlerThread("WifiManagerThread");
+            thread.start();
+            return thread;
+        }
+    }
+
+    private static Looper getInstanceLooper() {
+        return NoPreloadHolder.INSTANCE.getLooper();
+    }
+
+    private WifiFrameworkInitializer() {}
+
+    /**
+     * Called by {@link SystemServiceRegistry}'s static initializer and registers all Wifi 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.WIFI_SERVICE,
+                WifiManager.class,
+                context -> new WifiManager(context, getInstanceLooper())
+        );
+        SystemServiceRegistry.registerStaticService(
+                Context.WIFI_P2P_SERVICE,
+                WifiP2pManager.class,
+                serviceBinder -> {
+                    IWifiP2pManager service = IWifiP2pManager.Stub.asInterface(serviceBinder);
+                    return new WifiP2pManager(service);
+                }
+        );
+        SystemServiceRegistry.registerContextAwareService(
+                Context.WIFI_AWARE_SERVICE,
+                WifiAwareManager.class,
+                (context, serviceBinder) -> {
+                    IWifiAwareManager service = IWifiAwareManager.Stub.asInterface(serviceBinder);
+                    return new WifiAwareManager(context, service);
+                }
+        );
+        SystemServiceRegistry.registerContextAwareService(
+                Context.WIFI_SCANNING_SERVICE,
+                WifiScanner.class,
+                (context, serviceBinder) -> {
+                    IWifiScanner service = IWifiScanner.Stub.asInterface(serviceBinder);
+                    return new WifiScanner(context, service, getInstanceLooper());
+                }
+        );
+        SystemServiceRegistry.registerContextAwareService(
+                Context.WIFI_RTT_SERVICE,
+                RttManager.class,
+                (context, serviceBinder) -> {
+                    IWifiRttManager service = IWifiRttManager.Stub.asInterface(serviceBinder);
+                    WifiRttManager wifiRttManager = new WifiRttManager(context, service);
+                    return new RttManager(context, wifiRttManager);
+                }
+        );
+        SystemServiceRegistry.registerContextAwareService(
+                Context.WIFI_RTT_RANGING_SERVICE,
+                WifiRttManager.class,
+                (context, serviceBinder) -> {
+                    IWifiRttManager service = IWifiRttManager.Stub.asInterface(serviceBinder);
+                    return new WifiRttManager(context, service);
+                }
+        );
+    }
+}
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 6c2a08c..942d795 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;
 
     /**
@@ -1215,11 +1213,13 @@
      * Applications will almost always want to use
      * {@link android.content.Context#getSystemService Context.getSystemService()} to retrieve
      * the standard {@link android.content.Context#WIFI_SERVICE Context.WIFI_SERVICE}.
+     *
      * @param context the application context
-     * @hide - hide this because it takes in a parameter of type IWifiManager, which
-     * is a system private class.
+     * @param looper the Looper used to deliver callbacks
+     *
+     * @hide
      */
-    public WifiManager(Context context, Looper looper) {
+    public WifiManager(@NonNull Context context, @NonNull Looper looper) {
         mContext = context;
         mLooper = looper;
         mTargetSdkVersion = context.getApplicationInfo().targetSdkVersion;
@@ -2782,11 +2782,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 +2802,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 +3237,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>
diff --git a/wifi/java/android/net/wifi/WifiNetworkScoreCache.java b/wifi/java/android/net/wifi/WifiNetworkScoreCache.java
index b22ae070..5a212a8 100755
--- a/wifi/java/android/net/wifi/WifiNetworkScoreCache.java
+++ b/wifi/java/android/net/wifi/WifiNetworkScoreCache.java
@@ -22,6 +22,7 @@
 import android.content.Context;
 import android.net.INetworkScoreCache;
 import android.net.NetworkKey;
+import android.net.NetworkScoreManager;
 import android.net.ScoredNetwork;
 import android.os.Handler;
 import android.os.Process;
@@ -40,7 +41,8 @@
  *
  * @hide
  */
-public class WifiNetworkScoreCache extends INetworkScoreCache.Stub {
+public class WifiNetworkScoreCache extends INetworkScoreCache.Stub
+        implements NetworkScoreManager.NetworkScoreCallback {
     private static final String TAG = "WifiNetworkScoreCache";
     private static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG);
 
@@ -246,6 +248,17 @@
     }
 
     @Override protected final void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
+        WifiManager wifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
+        dumpWithLatestScanResults(fd, writer, args, wifiManager.getScanResults());
+    }
+
+    /**
+     * This is directly invoked from within Wifi-Service (on it's instance of this class), hence
+     * avoid making the WifiManager.getScanResults() call to avoid a deadlock.
+     */
+    public final void dumpWithLatestScanResults(
+            FileDescriptor fd, PrintWriter writer, String[] args,
+            List<ScanResult> latestScanResults) {
         mContext.enforceCallingOrSelfPermission(permission.DUMP, TAG);
         String header = String.format("WifiNetworkScoreCache (%s/%d)",
                 mContext.getPackageName(), Process.myUid());
@@ -256,8 +269,7 @@
                 writer.println("    " + score);
             }
             writer.println("  Network scores for latest ScanResults:");
-            WifiManager wifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
-            for (ScanResult scanResult : wifiManager.getScanResults()) {
+            for (ScanResult scanResult : latestScanResults) {
                 writer.println(
                         "    " + buildNetworkKey(scanResult) + ": " + getNetworkScore(scanResult));
             }
diff --git a/wifi/java/android/net/wifi/WifiScanner.java b/wifi/java/android/net/wifi/WifiScanner.java
index 0d36718..0de5066 100644
--- a/wifi/java/android/net/wifi/WifiScanner.java
+++ b/wifi/java/android/net/wifi/WifiScanner.java
@@ -789,12 +789,11 @@
 
     /**
      * Enable/Disable wifi scanning.
-     * Note: WifiService calls this after any client interface mode changes (i.e. a new interface
-     * set up or an existing interface torn down)
-     * If there are >= 1 active client interface, invoke setScanningEnabled(true)
-     * If there are 0 active client interface, invoke setScanningEnabled(false)
+     *
+     * @param enable set to true to enable scanning, set to false to disable all types of scanning.
      * {@hide}
      */
+    @SystemApi
     @RequiresPermission(Manifest.permission.NETWORK_STACK)
     public void setScanningEnabled(boolean enable) {
         validateChannel();
@@ -1291,12 +1290,15 @@
      * Applications will almost always want to use
      * {@link android.content.Context#getSystemService Context.getSystemService()} to retrieve
      * the standard {@link android.content.Context#WIFI_SERVICE Context.WIFI_SERVICE}.
+     *
      * @param context the application context
-     * @param service the Binder interface
+     * @param service the Binder interface for {@link Context#WIFI_SCANNING_SERVICE}
      * @param looper the Looper used to deliver callbacks
+     *
      * @hide
      */
-    public WifiScanner(Context context, IWifiScanner service, Looper looper) {
+    public WifiScanner(@NonNull Context context, @NonNull IWifiScanner service,
+            @NonNull Looper looper) {
         mContext = context;
         mService = service;
 
diff --git a/wifi/java/android/net/wifi/aware/WifiAwareManager.java b/wifi/java/android/net/wifi/aware/WifiAwareManager.java
index 5aab347..7b37d65 100644
--- a/wifi/java/android/net/wifi/aware/WifiAwareManager.java
+++ b/wifi/java/android/net/wifi/aware/WifiAwareManager.java
@@ -158,7 +158,7 @@
     private final Object mLock = new Object(); // lock access to the following vars
 
     /** @hide */
-    public WifiAwareManager(Context context, IWifiAwareManager service) {
+    public WifiAwareManager(@NonNull Context context, @NonNull IWifiAwareManager service) {
         mContext = context;
         mService = service;
     }
diff --git a/wifi/java/android/net/wifi/rtt/WifiRttManager.java b/wifi/java/android/net/wifi/rtt/WifiRttManager.java
index 770a120..cb0c5d4 100644
--- a/wifi/java/android/net/wifi/rtt/WifiRttManager.java
+++ b/wifi/java/android/net/wifi/rtt/WifiRttManager.java
@@ -77,7 +77,7 @@
             "android.net.wifi.rtt.action.WIFI_RTT_STATE_CHANGED";
 
     /** @hide */
-    public WifiRttManager(Context context, IWifiRttManager service) {
+    public WifiRttManager(@NonNull Context context, @NonNull IWifiRttManager service) {
         mContext = context;
         mService = service;
     }
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);
+    }
 }